From ad599de9728837ec5ca375a23cc1ba93b6d458d1 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Mon, 9 Dec 2024 11:30:14 +0530 Subject: [PATCH 01/13] WIP: staking tests --- tests/integration/v2/staking/common_test.go | 214 ++++ .../integration/v2/staking/delegation_test.go | 118 +++ .../v2/staking/deterministic_test.go | 918 ++++++++++++++++++ tests/integration/v2/staking/genesis_test.go | 238 +++++ .../integration/v2/staking/grpc_query_test.go | 915 +++++++++++++++++ .../integration/v2/staking/msg_server_test.go | 390 ++++++++ tests/integration/v2/staking/slash_test.go | 767 +++++++++++++++ .../integration/v2/staking/unbonding_test.go | 460 +++++++++ .../v2/staking/validator_bench_test.go | 181 ++++ .../integration/v2/staking/validator_test.go | 887 +++++++++++++++++ .../v2/staking/vote_extensions_test.go | 153 +++ 11 files changed, 5241 insertions(+) create mode 100644 tests/integration/v2/staking/common_test.go create mode 100644 tests/integration/v2/staking/delegation_test.go create mode 100644 tests/integration/v2/staking/deterministic_test.go create mode 100644 tests/integration/v2/staking/genesis_test.go create mode 100644 tests/integration/v2/staking/grpc_query_test.go create mode 100644 tests/integration/v2/staking/msg_server_test.go create mode 100644 tests/integration/v2/staking/slash_test.go create mode 100644 tests/integration/v2/staking/unbonding_test.go create mode 100644 tests/integration/v2/staking/validator_bench_test.go create mode 100644 tests/integration/v2/staking/validator_test.go create mode 100644 tests/integration/v2/staking/vote_extensions_test.go diff --git a/tests/integration/v2/staking/common_test.go b/tests/integration/v2/staking/common_test.go new file mode 100644 index 000000000000..4832f98074d6 --- /dev/null +++ b/tests/integration/v2/staking/common_test.go @@ -0,0 +1,214 @@ +package staking + +import ( + "context" + "math/big" + "testing" + + "go.uber.org/mock/gomock" + "gotest.tools/v3/assert" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/log" + "cosmossdk.io/math" + 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" + pooltypes "cosmossdk.io/x/protocolpool/types" + "cosmossdk.io/x/staking" + stakingkeeper "cosmossdk.io/x/staking/keeper" + "cosmossdk.io/x/staking/testutil" + "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" + 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" + authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" + authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var PKs = simtestutil.CreateTestPubKeys(500) + +type fixture struct { + app *integration.App + + sdkCtx sdk.Context + cdc codec.Codec + keys map[string]*storetypes.KVStoreKey + + accountKeeper authkeeper.AccountKeeper + bankKeeper bankkeeper.Keeper + stakingKeeper *stakingkeeper.Keeper +} + +func init() { + sdk.DefaultPowerReduction = math.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) +} + +// intended to be used with require/assert: require.True(ValEq(...)) +func ValEq(t *testing.T, exp, got types.Validator) (*testing.T, bool, string, types.Validator, types.Validator) { + t.Helper() + return t, exp.MinEqual(&got), "expected:\n%v\ngot:\n%v", exp, got +} + +// generateAddresses generates numAddrs of normal AccAddrs and ValAddrs +func generateAddresses(f *fixture, numAddrs int) ([]sdk.AccAddress, []sdk.ValAddress) { + addrDels := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, numAddrs, math.NewInt(10000)) + addrVals := simtestutil.ConvertAddrsToValAddrs(addrDels) + + return addrDels, addrVals +} + +func createValidators( + t *testing.T, + f *fixture, + powers []int64, +) ([]sdk.AccAddress, []sdk.ValAddress, []types.Validator) { + t.Helper() + addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, 5, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 300)) + valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) + pks := simtestutil.CreateTestPubKeys(5) + + val1 := testutil.NewValidator(t, valAddrs[0], pks[0]) + val2 := testutil.NewValidator(t, valAddrs[1], pks[1]) + vals := []types.Validator{val1, val2} + + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, val1)) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, val2)) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val1)) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val2)) + assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val1)) + assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val2)) + + for _, addr := range addrs { + acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) + f.accountKeeper.SetAccount(f.sdkCtx, acc) + } + + _, err := f.stakingKeeper.Delegate(f.sdkCtx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[0]), types.Unbonded, val1, true) + assert.NilError(t, err) + _, err = f.stakingKeeper.Delegate(f.sdkCtx, addrs[1], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[1]), types.Unbonded, val2, true) + assert.NilError(t, err) + _, err = f.stakingKeeper.Delegate(f.sdkCtx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[2]), types.Unbonded, val2, true) + assert.NilError(t, err) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) + + return addrs, valAddrs, vals +} + +func initFixture(tb testing.TB) *fixture { + tb.Helper() + keys := storetypes.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, types.StoreKey, consensustypes.StoreKey, + ) + encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, staking.AppModule{}) + cdc := encodingCfg.Codec + + msgRouter := baseapp.NewMsgServiceRouter() + queryRouter := baseapp.NewGRPCQueryRouter() + + logger := log.NewTestLogger(tb) + authority := authtypes.NewModuleAddress("gov") + + maccPerms := map[string][]string{ + pooltypes.ModuleName: {}, + minttypes.ModuleName: {authtypes.Minter}, + types.ModuleName: {authtypes.Minter}, + types.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + types.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + } + + // gomock initializations + ctrl := gomock.NewController(tb) + acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl) + var lastAccNum uint64 + acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) { + lastAccNum++ + return lastAccNum, 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()), + cdc, + accountKeeper, + blockedAddresses, + authority.String(), + ) + + consensusParamsKeeper := consensusparamkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensustypes.StoreKey]), log.NewNopLogger()), authtypes.NewModuleAddress("gov").String()) + + stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[types.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), accountKeeper, bankKeeper, consensusParamsKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr), runtime.NewContextAwareCometInfoService()) + + authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) + bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) + consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) + + integrationApp := integration.NewIntegrationApp(logger, keys, cdc, + encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), + encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), + map[string]appmodule.AppModule{ + authtypes.ModuleName: authModule, + banktypes.ModuleName: bankModule, + types.ModuleName: stakingModule, + consensustypes.ModuleName: consensusModule, + }, + msgRouter, + queryRouter, + ) + + sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) + + // Register MsgServer and QueryServer + types.RegisterMsgServer(integrationApp.MsgServiceRouter(), stakingkeeper.NewMsgServerImpl(stakingKeeper)) + types.RegisterQueryServer(integrationApp.QueryHelper(), stakingkeeper.NewQuerier(stakingKeeper)) + + // set default staking params + assert.NilError(tb, stakingKeeper.Params.Set(sdkCtx, types.DefaultParams())) + accNum := uint64(0) + acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) { + currentNum := accNum + accNum++ + return currentNum, nil + }) + + f := fixture{ + app: integrationApp, + sdkCtx: sdkCtx, + cdc: cdc, + keys: keys, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + stakingKeeper: stakingKeeper, + } + + return &f +} diff --git a/tests/integration/v2/staking/delegation_test.go b/tests/integration/v2/staking/delegation_test.go new file mode 100644 index 000000000000..c061680ac7ef --- /dev/null +++ b/tests/integration/v2/staking/delegation_test.go @@ -0,0 +1,118 @@ +package staking + +import ( + "testing" + "time" + + "gotest.tools/v3/assert" + + "cosmossdk.io/core/header" + "cosmossdk.io/math" + banktestutil "cosmossdk.io/x/bank/testutil" + "cosmossdk.io/x/staking/keeper" + "cosmossdk.io/x/staking/testutil" + "cosmossdk.io/x/staking/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestUnbondingDelegationsMaxEntries(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + + initTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, int64(1000)) + assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)))) + + addrDel := sdk.AccAddress([]byte("addr")) + accAmt := math.NewInt(10000) + bondDenom, err := f.stakingKeeper.BondDenom(ctx) + assert.NilError(t, err) + + initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt)) + assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, initCoins)) + assert.NilError(t, f.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addrDel, initCoins)) + addrVal := sdk.ValAddress(addrDel) + + startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 10) + + notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx) + + assert.NilError(t, banktestutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + f.accountKeeper.SetModuleAccount(ctx, notBondedPool) + + // create a validator and a delegator to that validator + validator := testutil.NewValidator(t, addrVal, PKs[0]) + + validator, issuedShares := validator.AddTokensFromDel(startTokens) + assert.DeepEqual(t, startTokens, issuedShares.RoundInt()) + + validator = keeper.TestingUpdateValidator(f.stakingKeeper, ctx, validator, true) + assert.Assert(math.IntEq(t, startTokens, validator.BondedTokens())) + assert.Assert(t, validator.IsBonded()) + + delegation := types.NewDelegation(addrDel.String(), addrVal.String(), issuedShares) + assert.NilError(t, f.stakingKeeper.SetDelegation(ctx, delegation)) + + maxEntries, err := f.stakingKeeper.MaxEntries(ctx) + assert.NilError(t, err) + + oldBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + oldNotBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + // should all pass + var completionTime time.Time + totalUnbonded := math.NewInt(0) + for i := int64(0); i < int64(maxEntries); i++ { + var err error + ctx = ctx.WithHeaderInfo(header.Info{Height: i}) + var amount math.Int + completionTime, amount, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1)) + assert.NilError(t, err) + totalUnbonded = totalUnbonded.Add(amount) + } + + newBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + newNotBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, newBonded, oldBonded.SubRaw(int64(maxEntries)))) + assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(int64(maxEntries)))) + assert.Assert(math.IntEq(t, totalUnbonded, oldBonded.Sub(newBonded))) + assert.Assert(math.IntEq(t, totalUnbonded, newNotBonded.Sub(oldNotBonded))) + + oldBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + oldNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + // an additional unbond should fail due to max entries + _, _, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1)) + assert.Error(t, err, "too many unbonding delegation entries for (delegator, validator) tuple") + + newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + assert.Assert(math.IntEq(t, newBonded, oldBonded)) + assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded)) + + // mature unbonding delegations + ctx = ctx.WithHeaderInfo(header.Info{Time: completionTime}) + acc := f.accountKeeper.NewAccountWithAddress(ctx, addrDel) + f.accountKeeper.SetAccount(ctx, acc) + _, err = f.stakingKeeper.CompleteUnbonding(ctx, addrDel, addrVal) + assert.NilError(t, err) + + newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, newBonded, oldBonded)) + assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.SubRaw(int64(maxEntries)))) + + oldNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + // unbonding should work again + _, _, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1)) + assert.NilError(t, err) + + newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, newBonded, oldBonded.SubRaw(1))) + assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1))) +} diff --git a/tests/integration/v2/staking/deterministic_test.go b/tests/integration/v2/staking/deterministic_test.go new file mode 100644 index 000000000000..bd733c3708c8 --- /dev/null +++ b/tests/integration/v2/staking/deterministic_test.go @@ -0,0 +1,918 @@ +package staking + +import ( + "context" + "fmt" + "net/url" + "testing" + "time" + + "go.uber.org/mock/gomock" + "gotest.tools/v3/assert" + "pgregory.net/rapid" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/log" + "cosmossdk.io/math" + storetypes "cosmossdk.io/store/types" + "cosmossdk.io/x/bank" + bankkeeper "cosmossdk.io/x/bank/keeper" + banktestutil "cosmossdk.io/x/bank/testutil" + banktypes "cosmossdk.io/x/bank/types" + "cosmossdk.io/x/consensus" + consensusparamkeeper "cosmossdk.io/x/consensus/keeper" + consensusparamtypes "cosmossdk.io/x/consensus/types" + "cosmossdk.io/x/distribution" + minttypes "cosmossdk.io/x/mint/types" + "cosmossdk.io/x/staking" + stakingkeeper "cosmossdk.io/x/staking/keeper" + 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" + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + "github.com/cosmos/cosmos-sdk/runtime" + "github.com/cosmos/cosmos-sdk/testutil/integration" + "github.com/cosmos/cosmos-sdk/testutil/testdata" + 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" + authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" + authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var ( + validator1 = "cosmosvaloper1qqqryrs09ggeuqszqygqyqd2tgqmsqzewacjj7" + validatorAddr1, _ = sdk.ValAddressFromBech32(validator1) + validator2 = "cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj" + validatorAddr2, _ = sdk.ValAddressFromBech32(validator2) + delegator1 = "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl" + delegatorAddr1 = sdk.MustAccAddressFromBech32(delegator1) + delegator2 = "cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5" + delegatorAddr2 = sdk.MustAccAddressFromBech32(delegator2) +) + +type deterministicFixture struct { + app *integration.App + + ctx sdk.Context + cdc codec.Codec + keys map[string]*storetypes.KVStoreKey + + accountKeeper authkeeper.AccountKeeper + bankKeeper bankkeeper.BaseKeeper + stakingKeeper *stakingkeeper.Keeper + + queryClient stakingtypes.QueryClient + amt1 math.Int + amt2 math.Int +} + +func initDeterministicFixture(t *testing.T) *deterministicFixture { + t.Helper() + keys := storetypes.NewKVStoreKeys( + authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, consensusparamtypes.StoreKey, + ) + encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, distribution.AppModule{}) + cdc := encodingCfg.Codec + + logger := log.NewTestLogger(t) + authority := authtypes.NewModuleAddress("gov") + + maccPerms := map[string][]string{ + minttypes.ModuleName: {authtypes.Minter}, + stakingtypes.ModuleName: {authtypes.Minter}, + stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, + stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, + } + + // gomock initializations + ctrl := gomock.NewController(t) + 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()), + 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()), + cdc, + accountKeeper, + blockedAddresses, + authority.String(), + ) + + consensusParamsKeeper := consensusparamkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]), log.NewNopLogger()), authtypes.NewModuleAddress("gov").String()) + + stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), log.NewNopLogger()), accountKeeper, bankKeeper, consensusParamsKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr), runtime.NewContextAwareCometInfoService()) + + authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) + bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) + stakingModule := staking.NewAppModule(cdc, stakingKeeper) + consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) + + integrationApp := integration.NewIntegrationApp(logger, keys, cdc, + encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), + encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), + map[string]appmodule.AppModule{ + authtypes.ModuleName: authModule, + banktypes.ModuleName: bankModule, + stakingtypes.ModuleName: stakingModule, + consensusparamtypes.ModuleName: consensusModule, + }, + baseapp.NewMsgServiceRouter(), + baseapp.NewGRPCQueryRouter(), + ) + + ctx := integrationApp.Context() + + // Register MsgServer and QueryServer + stakingtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), stakingkeeper.NewMsgServerImpl(stakingKeeper)) + stakingtypes.RegisterQueryServer(integrationApp.QueryHelper(), stakingkeeper.NewQuerier(stakingKeeper)) + + // set default staking params + assert.NilError(t, stakingKeeper.Params.Set(ctx, stakingtypes.DefaultParams())) + + // set pools + startTokens := stakingKeeper.TokensFromConsensusPower(ctx, 10) + bondDenom, err := stakingKeeper.BondDenom(ctx) + assert.NilError(t, err) + notBondedPool := stakingKeeper.GetNotBondedPool(ctx) + assert.NilError(t, banktestutil.FundModuleAccount(ctx, bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + accountKeeper.SetModuleAccount(ctx, notBondedPool) + bondedPool := stakingKeeper.GetBondedPool(ctx) + assert.NilError(t, banktestutil.FundModuleAccount(ctx, bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + accountKeeper.SetModuleAccount(ctx, bondedPool) + + qr := integrationApp.QueryHelper() + queryClient := stakingtypes.NewQueryClient(qr) + + amt1 := stakingKeeper.TokensFromConsensusPower(ctx, 101) + amt2 := stakingKeeper.TokensFromConsensusPower(ctx, 102) + + f := deterministicFixture{ + app: integrationApp, + ctx: sdk.UnwrapSDKContext(ctx), + cdc: cdc, + keys: keys, + accountKeeper: accountKeeper, + bankKeeper: bankKeeper, + stakingKeeper: stakingKeeper, + queryClient: queryClient, + amt1: amt1, + amt2: amt2, + } + + return &f +} + +func durationGenerator() *rapid.Generator[time.Duration] { + return rapid.Custom(func(t *rapid.T) time.Duration { + now := time.Now() + // range from current time to 365days. + duration := rapid.Int64Range(now.Unix(), 365*24*60*60*now.Unix()).Draw(t, "time") + return time.Duration(duration) + }) +} + +func pubKeyGenerator() *rapid.Generator[ed25519.PubKey] { + return rapid.Custom(func(t *rapid.T) ed25519.PubKey { + pkBz := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "hex") + return ed25519.PubKey{Key: pkBz} + }) +} + +func bondTypeGenerator() *rapid.Generator[stakingtypes.BondStatus] { + bondTypes := []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Unbonded, stakingtypes.Unbonding} + return rapid.Custom(func(t *rapid.T) stakingtypes.BondStatus { + return bondTypes[rapid.IntRange(0, 2).Draw(t, "range")] + }) +} + +func metadataGenerator() *rapid.Generator[*stakingtypes.Metadata] { + return rapid.Custom(func(t *rapid.T) *stakingtypes.Metadata { + return &stakingtypes.Metadata{ + ProfilePicUri: generateUri(t), + SocialHandleUris: []string{generateUri(t), generateUri(t)}, + } + }) +} + +func generateUri(t *rapid.T) string { + host := fmt.Sprintf("%s.com", rapid.StringN(5, 250, 255).Draw(t, "host")) + path := rapid.StringN(5, 250, 255).Draw(t, "path") + uri := url.URL{ + Scheme: "https", + Host: host, + Path: path, + } + return uri.String() +} + +// createValidator creates a validator with random values. +func createValidator(t *testing.T, rt *rapid.T, _ *deterministicFixture) stakingtypes.Validator { + t.Helper() + pubkey := pubKeyGenerator().Draw(rt, "pubkey") + pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey) + assert.NilError(t, err) + return stakingtypes.Validator{ + OperatorAddress: sdk.ValAddress(testdata.AddressGenerator(rt).Draw(rt, "address")).String(), + ConsensusPubkey: pubkeyAny, + Jailed: rapid.Bool().Draw(rt, "jailed"), + Status: bondTypeGenerator().Draw(rt, "bond-status"), + Tokens: math.NewInt(rapid.Int64Min(10000).Draw(rt, "tokens")), + DelegatorShares: math.LegacyNewDecWithPrec(rapid.Int64Range(1, 100).Draw(rt, "commission"), 2), + Description: stakingtypes.NewDescription( + rapid.StringN(5, 250, 255).Draw(rt, "moniker"), + rapid.StringN(5, 250, 255).Draw(rt, "identity"), + rapid.StringN(5, 250, 255).Draw(rt, "website"), + rapid.StringN(5, 250, 255).Draw(rt, "securityContact"), + rapid.StringN(5, 250, 255).Draw(rt, "details"), + metadataGenerator().Draw(rt, "metadata"), + ), + UnbondingHeight: rapid.Int64Min(1).Draw(rt, "unbonding-height"), + UnbondingTime: time.Now().Add(durationGenerator().Draw(rt, "duration")), + Commission: stakingtypes.NewCommission( + math.LegacyNewDecWithPrec(rapid.Int64Range(0, 100).Draw(rt, "rate"), 2), + math.LegacyNewDecWithPrec(rapid.Int64Range(0, 100).Draw(rt, "max-rate"), 2), + math.LegacyNewDecWithPrec(rapid.Int64Range(0, 100).Draw(rt, "max-change-rate"), 2), + ), + MinSelfDelegation: math.NewInt(rapid.Int64Min(1).Draw(rt, "tokens")), + } +} + +// createAndSetValidatorWithStatus creates a validator with random values but with given status and sets to the state +func createAndSetValidatorWithStatus( + t *testing.T, + rt *rapid.T, + f *deterministicFixture, + status stakingtypes.BondStatus, +) stakingtypes.Validator { + t.Helper() + val := createValidator(t, rt, f) + val.Status = status + setValidator(t, f, val) + return val +} + +// createAndSetValidator creates a validator with random values and sets to the state +func createAndSetValidator(t *testing.T, rt *rapid.T, f *deterministicFixture) stakingtypes.Validator { + t.Helper() + val := createValidator(t, rt, f) + setValidator(t, f, val) + return val +} + +func setValidator(t *testing.T, f *deterministicFixture, validator stakingtypes.Validator) { + t.Helper() + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, validator)) + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) + assert.NilError(t, err) + + assert.NilError(t, f.stakingKeeper.Hooks().AfterValidatorCreated(f.ctx, valbz)) + + delegatorAddress := sdk.AccAddress(valbz) + coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, validator.BondedTokens())) + assert.NilError(t, banktestutil.FundAccount(f.ctx, f.bankKeeper, delegatorAddress, coins)) + + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddress) + f.accountKeeper.SetAccount(f.ctx, acc) + + _, err = f.stakingKeeper.Delegate(f.ctx, delegatorAddress, validator.BondedTokens(), stakingtypes.Unbonded, validator, true) + assert.NilError(t, err) +} + +// getStaticValidator creates a validator with hard-coded values and sets to the state. +func getStaticValidator(t *testing.T, f *deterministicFixture) stakingtypes.Validator { + t.Helper() + pubkey := ed25519.PubKey{Key: []byte{24, 179, 242, 2, 151, 3, 34, 6, 1, 11, 0, 194, 202, 201, 77, 1, 167, 40, 249, 115, 32, 97, 18, 1, 1, 127, 255, 103, 13, 1, 34, 1}} + pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey) + assert.NilError(t, err) + + validator := stakingtypes.Validator{ + OperatorAddress: validator1, + ConsensusPubkey: pubkeyAny, + Jailed: false, + Status: stakingtypes.Bonded, + Tokens: math.NewInt(100), + DelegatorShares: math.LegacyNewDecWithPrec(5, 2), + Description: stakingtypes.NewDescription( + "moniker", + "identity", + "website", + "securityContact", + "details", + &stakingtypes.Metadata{}, + ), + UnbondingHeight: 10, + UnbondingTime: time.Date(2022, 10, 1, 0, 0, 0, 0, time.UTC), + Commission: stakingtypes.NewCommission( + math.LegacyNewDecWithPrec(5, 2), + math.LegacyNewDecWithPrec(5, 2), + math.LegacyNewDecWithPrec(5, 2), + ), + MinSelfDelegation: math.NewInt(10), + } + + setValidator(t, f, validator) + return validator +} + +// getStaticValidator2 creates a validator with hard-coded values and sets to the state. +func getStaticValidator2(t *testing.T, f *deterministicFixture) stakingtypes.Validator { + t.Helper() + pubkey := ed25519.PubKey{Key: []byte{40, 249, 115, 32, 97, 18, 1, 1, 127, 255, 103, 13, 1, 34, 1, 24, 179, 242, 2, 151, 3, 34, 6, 1, 11, 0, 194, 202, 201, 77, 1, 167}} + pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey) + assert.NilError(t, err) + + validator := stakingtypes.Validator{ + OperatorAddress: validator2, + ConsensusPubkey: pubkeyAny, + Jailed: true, + Status: stakingtypes.Bonded, + Tokens: math.NewInt(10012), + DelegatorShares: math.LegacyNewDecWithPrec(96, 2), + Description: stakingtypes.NewDescription( + "moniker", + "identity", + "website", + "securityContact", + "details", + &stakingtypes.Metadata{}, + ), + UnbondingHeight: 100132, + UnbondingTime: time.Date(2025, 10, 1, 0, 0, 0, 0, time.UTC), + Commission: stakingtypes.NewCommission( + math.LegacyNewDecWithPrec(15, 2), + math.LegacyNewDecWithPrec(59, 2), + math.LegacyNewDecWithPrec(51, 2), + ), + MinSelfDelegation: math.NewInt(1), + } + setValidator(t, f, validator) + + return validator +} + +// createDelegationAndDelegate funds the delegator account with a random delegation in range 100-1000 and delegates. +func createDelegationAndDelegate( + t *testing.T, + rt *rapid.T, + f *deterministicFixture, + delegator sdk.AccAddress, + validator stakingtypes.Validator, +) (newShares math.LegacyDec, err error) { + t.Helper() + amt := f.stakingKeeper.TokensFromConsensusPower(f.ctx, rapid.Int64Range(100, 1000).Draw(rt, "amount")) + return fundAccountAndDelegate(t, f, delegator, validator, amt) +} + +// fundAccountAndDelegate funds the delegator account with the specified delegation and delegates. +func fundAccountAndDelegate( + t *testing.T, + f *deterministicFixture, + delegator sdk.AccAddress, + validator stakingtypes.Validator, + amt math.Int, +) (newShares math.LegacyDec, err error) { + t.Helper() + coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amt)) + + assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, coins)) + assert.NilError(t, banktestutil.FundAccount(f.ctx, f.bankKeeper, delegator, coins)) + + shares, err := f.stakingKeeper.Delegate(f.ctx, delegator, amt, stakingtypes.Unbonded, validator, true) + return shares, err +} + +func TestGRPCValidator(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + val := createAndSetValidator(t, rt, f) + req := &stakingtypes.QueryValidatorRequest{ + ValidatorAddr: val.OperatorAddress, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validator, 0, true) + }) + + f = initDeterministicFixture(t) // reset + val := getStaticValidator(t, f) + req := &stakingtypes.QueryValidatorRequest{ + ValidatorAddr: val.OperatorAddress, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validator, 1921, false) +} + +func TestGRPCValidators(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + validatorStatus := []string{stakingtypes.BondStatusBonded, stakingtypes.BondStatusUnbonded, stakingtypes.BondStatusUnbonding} + rapid.Check(t, func(rt *rapid.T) { + valsCount := rapid.IntRange(1, 3).Draw(rt, "num-validators") + for i := 0; i < valsCount; i++ { + createAndSetValidator(t, rt, f) + } + + req := &stakingtypes.QueryValidatorsRequest{ + Status: validatorStatus[rapid.IntRange(0, 2).Draw(rt, "status")], + Pagination: testdata.PaginationGenerator(rt, uint64(valsCount)).Draw(rt, "pagination"), + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validators, 0, true) + }) + + f = initDeterministicFixture(t) // reset + getStaticValidator(t, f) + getStaticValidator2(t, f) + + testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryValidatorsRequest{}, f.queryClient.Validators, 2880, false) +} + +func TestGRPCValidatorDelegations(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + numDels := rapid.IntRange(1, 5).Draw(rt, "num-dels") + + for i := 0; i < numDels; i++ { + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + } + + req := &stakingtypes.QueryValidatorDelegationsRequest{ + ValidatorAddr: validator.OperatorAddress, + Pagination: testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination"), + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorDelegations, 0, true) + }) + + f = initDeterministicFixture(t) // reset + + validator := getStaticValidator(t, f) + + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + assert.NilError(t, err) + + acc = f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr2) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err = fundAccountAndDelegate(t, f, delegatorAddr2, validator, f.amt2) + assert.NilError(t, err) + + req := &stakingtypes.QueryValidatorDelegationsRequest{ + ValidatorAddr: validator.OperatorAddress, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorDelegations, 14628, false) +} + +func TestGRPCValidatorUnbondingDelegations(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + numDels := rapid.IntRange(1, 3).Draw(rt, "num-dels") + + for i := 0; i < numDels; i++ { + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + shares, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) + assert.NilError(t, err) + _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegator, valbz, shares) + assert.NilError(t, err) + } + + req := &stakingtypes.QueryValidatorUnbondingDelegationsRequest{ + ValidatorAddr: validator.OperatorAddress, + Pagination: testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination"), + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorUnbondingDelegations, 0, true) + }) + + f = initDeterministicFixture(t) // reset + + validator := getStaticValidator(t, f) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + shares1, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + assert.NilError(t, err) + + _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegatorAddr1, validatorAddr1, shares1) + assert.NilError(t, err) + + acc = f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr2) + f.accountKeeper.SetAccount(f.ctx, acc) + shares2, err := fundAccountAndDelegate(t, f, delegatorAddr2, validator, f.amt2) + assert.NilError(t, err) + + _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegatorAddr2, validatorAddr1, shares2) + assert.NilError(t, err) + + req := &stakingtypes.QueryValidatorUnbondingDelegationsRequest{ + ValidatorAddr: validator.OperatorAddress, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorUnbondingDelegations, 3719, false) +} + +func TestGRPCDelegation(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + + req := &stakingtypes.QueryDelegationRequest{ + ValidatorAddr: validator.OperatorAddress, + DelegatorAddr: delegator.String(), + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Delegation, 0, true) + }) + + f = initDeterministicFixture(t) // reset + + validator := getStaticValidator(t, f) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + assert.NilError(t, err) + + req := &stakingtypes.QueryDelegationRequest{ + ValidatorAddr: validator.OperatorAddress, + DelegatorAddr: delegator1, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Delegation, 4686, false) +} + +func TestGRPCUnbondingDelegation(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + shares, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) + assert.NilError(t, err) + _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegator, valbz, shares) + assert.NilError(t, err) + + req := &stakingtypes.QueryUnbondingDelegationRequest{ + ValidatorAddr: validator.OperatorAddress, + DelegatorAddr: delegator.String(), + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.UnbondingDelegation, 0, true) + }) + + f = initDeterministicFixture(t) // reset + validator := getStaticValidator(t, f) + + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + shares1, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + assert.NilError(t, err) + + _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegatorAddr1, validatorAddr1, shares1) + assert.NilError(t, err) + + req := &stakingtypes.QueryUnbondingDelegationRequest{ + ValidatorAddr: validator.OperatorAddress, + DelegatorAddr: delegator1, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.UnbondingDelegation, 1621, false) +} + +func TestGRPCDelegatorDelegations(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + numVals := rapid.IntRange(1, 3).Draw(rt, "num-dels") + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + + for i := 0; i < numVals; i++ { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + } + + req := &stakingtypes.QueryDelegatorDelegationsRequest{ + DelegatorAddr: delegator.String(), + Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorDelegations, 0, true) + }) + + f = initDeterministicFixture(t) // reset + + validator := getStaticValidator(t, f) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + assert.NilError(t, err) + + req := &stakingtypes.QueryDelegatorDelegationsRequest{ + DelegatorAddr: delegator1, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorDelegations, 4289, false) +} + +func TestGRPCDelegatorValidator(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + + req := &stakingtypes.QueryDelegatorValidatorRequest{ + DelegatorAddr: delegator.String(), + ValidatorAddr: validator.OperatorAddress, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidator, 0, true) + }) + + f = initDeterministicFixture(t) // reset + + validator := getStaticValidator(t, f) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + + assert.NilError(t, err) + + req := &stakingtypes.QueryDelegatorValidatorRequest{ + DelegatorAddr: delegator1, + ValidatorAddr: validator.OperatorAddress, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidator, 3569, false) +} + +func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + numVals := rapid.IntRange(1, 5).Draw(rt, "num-vals") + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + + for i := 0; i < numVals; i++ { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + shares, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) + assert.NilError(t, err) + _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegator, valbz, shares) + assert.NilError(t, err) + } + + req := &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{ + DelegatorAddr: delegator.String(), + Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorUnbondingDelegations, 0, true) + }) + + f = initDeterministicFixture(t) // reset + + validator := getStaticValidator(t, f) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + shares1, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + assert.NilError(t, err) + + _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegatorAddr1, validatorAddr1, shares1) + assert.NilError(t, err) + + req := &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{ + DelegatorAddr: delegator1, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorUnbondingDelegations, 1302, false) +} + +func TestGRPCDelegatorValidators(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + numVals := rapid.IntRange(1, 3).Draw(rt, "num-dels") + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + + for i := 0; i < numVals; i++ { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + } + + req := &stakingtypes.QueryDelegatorValidatorsRequest{ + DelegatorAddr: delegator.String(), + Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidators, 0, true) + }) + + f = initDeterministicFixture(t) // reset + + validator := getStaticValidator(t, f) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + assert.NilError(t, err) + + req := &stakingtypes.QueryDelegatorValidatorsRequest{DelegatorAddr: delegator1} + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidators, 3172, false) +} + +func TestGRPCPool(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + createAndSetValidator(t, rt, f) + + testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryPoolRequest{}, f.queryClient.Pool, 0, true) + }) + + f = initDeterministicFixture(t) // reset + getStaticValidator(t, f) + testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryPoolRequest{}, f.queryClient.Pool, 6287, false) +} + +func TestGRPCRedelegations(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + + rapid.Check(t, func(rt *rapid.T) { + validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + srcValAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) + assert.NilError(t, err) + + validator2 := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) + dstValAddr, err := sdk.ValAddressFromBech32(validator2.OperatorAddress) + assert.NilError(t, err) + + numDels := rapid.IntRange(1, 5).Draw(rt, "num-dels") + + delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) + f.accountKeeper.SetAccount(f.ctx, acc) + shares, err := createDelegationAndDelegate(t, rt, f, delegator, validator) + assert.NilError(t, err) + + _, err = f.stakingKeeper.BeginRedelegation(f.ctx, delegator, srcValAddr, dstValAddr, shares) + assert.NilError(t, err) + + var req *stakingtypes.QueryRedelegationsRequest + + reqType := rapid.IntRange(0, 2).Draw(rt, "req-type") + switch reqType { + case 0: // queries redelegation with delegator, source and destination validators combination. + req = &stakingtypes.QueryRedelegationsRequest{ + DelegatorAddr: delegator.String(), + SrcValidatorAddr: srcValAddr.String(), + DstValidatorAddr: dstValAddr.String(), + } + case 1: // queries redelegations of source validator. + req = &stakingtypes.QueryRedelegationsRequest{ + SrcValidatorAddr: srcValAddr.String(), + } + case 2: // queries all redelegations of a delegator. + req = &stakingtypes.QueryRedelegationsRequest{ + DelegatorAddr: delegator.String(), + } + } + + req.Pagination = testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination") + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Redelegations, 0, true) + }) + + f = initDeterministicFixture(t) // reset + validator := getStaticValidator(t, f) + _ = getStaticValidator2(t, f) + + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) + f.accountKeeper.SetAccount(f.ctx, acc) + shares, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) + assert.NilError(t, err) + + _, err = f.stakingKeeper.BeginRedelegation(f.ctx, delegatorAddr1, validatorAddr1, validatorAddr2, shares) + assert.NilError(t, err) + + req := &stakingtypes.QueryRedelegationsRequest{ + DelegatorAddr: delegator1, + SrcValidatorAddr: validator1, + DstValidatorAddr: validator2, + } + + testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Redelegations, 3926, false) +} + +func TestGRPCParams(t *testing.T) { + t.Parallel() + f := initDeterministicFixture(t) + coinDenomRegex := `[a-zA-Z][a-zA-Z0-9/:._-]{2,127}` + + rapid.Check(t, func(rt *rapid.T) { + bondDenom := rapid.StringMatching(coinDenomRegex).Draw(rt, "bond-denom") + params := stakingtypes.Params{ + BondDenom: bondDenom, + UnbondingTime: durationGenerator().Draw(rt, "duration"), + MaxValidators: rapid.Uint32Min(1).Draw(rt, "max-validators"), + MaxEntries: rapid.Uint32Min(1).Draw(rt, "max-entries"), + HistoricalEntries: rapid.Uint32Min(1).Draw(rt, "historical-entries"), + MinCommissionRate: math.LegacyNewDecWithPrec(rapid.Int64Range(0, 100).Draw(rt, "commission"), 2), + KeyRotationFee: sdk.NewInt64Coin(bondDenom, rapid.Int64Range(10000, 100000).Draw(rt, "amount")), + } + + err := f.stakingKeeper.Params.Set(f.ctx, params) + assert.NilError(t, err) + + testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryParamsRequest{}, f.queryClient.Params, 0, true) + }) + + params := stakingtypes.Params{ + BondDenom: "denom", + UnbondingTime: time.Hour, + MaxValidators: 85, + MaxEntries: 5, + HistoricalEntries: 5, + MinCommissionRate: math.LegacyNewDecWithPrec(5, 2), + KeyRotationFee: sdk.NewInt64Coin("denom", 10000), + } + + err := f.stakingKeeper.Params.Set(f.ctx, params) + assert.NilError(t, err) + + testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryParamsRequest{}, f.queryClient.Params, 1162, false) +} diff --git a/tests/integration/v2/staking/genesis_test.go b/tests/integration/v2/staking/genesis_test.go new file mode 100644 index 000000000000..6cbb593e3c4a --- /dev/null +++ b/tests/integration/v2/staking/genesis_test.go @@ -0,0 +1,238 @@ +package staking + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + "gotest.tools/v3/assert" + + "cosmossdk.io/core/appmodule" + "cosmossdk.io/math" + banktestutil "cosmossdk.io/x/bank/testutil" + "cosmossdk.io/x/staking" + "cosmossdk.io/x/staking/types" + + codectypes "github.com/cosmos/cosmos-sdk/codec/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" +) + +func bootstrapGenesisTest(t *testing.T, numAddrs int) (*fixture, []sdk.AccAddress) { + t.Helper() + t.Parallel() + f := initFixture(t) + + addrDels, _ := generateAddresses(f, numAddrs) + return f, addrDels +} + +func TestInitGenesis(t *testing.T) { + f, addrs := bootstrapGenesisTest(t, 10) + + valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) + + pk0, err := codectypes.NewAnyWithValue(PKs[0]) + assert.NilError(t, err) + + bondedVal := types.Validator{ + OperatorAddress: sdk.ValAddress(addrs[0]).String(), + ConsensusPubkey: pk0, + Status: types.Bonded, + Tokens: valTokens, + DelegatorShares: math.LegacyNewDecFromInt(valTokens), + Description: types.NewDescription("hoop", "", "", "", "", &types.Metadata{}), + } + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, bondedVal)) + + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + + validators, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) + assert.NilError(t, err) + + assert.Assert(t, len(validators) == 1) + var delegations []types.Delegation + + pk1, err := codectypes.NewAnyWithValue(PKs[1]) + assert.NilError(t, err) + + pk2, err := codectypes.NewAnyWithValue(PKs[2]) + assert.NilError(t, err) + + // initialize the validators + bondedVal1 := types.Validator{ + OperatorAddress: sdk.ValAddress(addrs[1]).String(), + ConsensusPubkey: pk1, + Status: types.Bonded, + Tokens: valTokens, + DelegatorShares: math.LegacyNewDecFromInt(valTokens), + Description: types.NewDescription("hoop", "", "", "", "", &types.Metadata{}), + } + bondedVal2 := types.Validator{ + OperatorAddress: sdk.ValAddress(addrs[2]).String(), + ConsensusPubkey: pk2, + Status: types.Bonded, + Tokens: valTokens, + DelegatorShares: math.LegacyNewDecFromInt(valTokens), + Description: types.NewDescription("bloop", "", "", "", "", &types.Metadata{}), + } + + // append new bonded validators to the list + validators = append(validators, bondedVal1, bondedVal2) + + // mint coins in the bonded pool representing the validators coins + i2 := len(validators) + assert.NilError(t, + banktestutil.FundModuleAccount( + f.sdkCtx, + f.bankKeeper, + types.BondedPoolName, + sdk.NewCoins( + sdk.NewCoin(params.BondDenom, valTokens.MulRaw((int64)(i2))), + ), + ), + ) + + genesisDelegations, err := f.stakingKeeper.GetAllDelegations(f.sdkCtx) + assert.NilError(t, err) + delegations = append(delegations, genesisDelegations...) + + genesisState := types.NewGenesisState(params, validators, delegations) + vals, err := (f.stakingKeeper.InitGenesis(f.sdkCtx, genesisState)) + assert.NilError(t, err) + + actualGenesis, err := (f.stakingKeeper.ExportGenesis(f.sdkCtx)) + assert.NilError(t, err) + assert.DeepEqual(t, genesisState.Params, actualGenesis.Params) + assert.DeepEqual(t, genesisState.Delegations, actualGenesis.Delegations) + + allvals, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) + assert.NilError(t, err) + assert.DeepEqual(t, allvals, actualGenesis.Validators) + + // Ensure validators have addresses. + vals2, err := staking.WriteValidators(f.sdkCtx, (f.stakingKeeper)) + assert.NilError(t, err) + + for _, val := range vals2 { + assert.Assert(t, val.Address.String() != "") + } + + // now make sure the validators are bonded and intra-tx counters are correct + resVal, found := (f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[1]))) + assert.Assert(t, found) + assert.Equal(t, types.Bonded, resVal.Status) + + resVal, found = (f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[2]))) + assert.Assert(t, found) + assert.Equal(t, types.Bonded, resVal.Status) + + validatorUpdates := make([]appmodule.ValidatorUpdate, len(vals)) + for i, val := range validators { + validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)) + } + assert.DeepEqual(t, validatorUpdates, vals) +} + +func TestInitGenesis_PoolsBalanceMismatch(t *testing.T) { + t.Parallel() + f := initFixture(t) + + consPub, err := codectypes.NewAnyWithValue(PKs[0]) + assert.NilError(t, err) + + validator := types.Validator{ + OperatorAddress: sdk.ValAddress("12345678901234567890").String(), + ConsensusPubkey: consPub, + Jailed: false, + Tokens: math.NewInt(10), + DelegatorShares: math.LegacyNewDecFromInt(math.NewInt(10)), + Description: types.NewDescription("bloop", "", "", "", "", &types.Metadata{}), + } + + params := types.Params{ + UnbondingTime: 10000, + MaxValidators: 1, + MaxEntries: 10, + BondDenom: "stake", + } + + // setting validator status to bonded so the balance counts towards bonded pool + validator.Status = types.Bonded + _, err = f.stakingKeeper.InitGenesis(f.sdkCtx, &types.GenesisState{ + Params: params, + Validators: []types.Validator{validator}, + }) + // "should error because bonded pool balance is different from bonded pool coins", + require.NotNil(t, err) + + // setting validator status to unbonded so the balance counts towards not bonded pool + validator.Status = types.Unbonded + _, err = f.stakingKeeper.InitGenesis(f.sdkCtx, &types.GenesisState{ + Params: params, + Validators: []types.Validator{validator}, + }) + // "should panic because not bonded pool balance is different from not bonded pool coins", + require.NotNil(t, err) +} + +func TestInitGenesisLargeValidatorSet(t *testing.T) { + size := 200 + assert.Assert(t, size > 100) + + f, addrs := bootstrapGenesisTest(t, 200) + genesisValidators, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) + assert.NilError(t, err) + + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + delegations := []types.Delegation{} + validators := make([]types.Validator, size) + + bondedPoolAmt := math.ZeroInt() + for i := range validators { + validators[i], err = types.NewValidator( + sdk.ValAddress(addrs[i]).String(), + PKs[i], + types.NewDescription(fmt.Sprintf("#%d", i), "", "", "", "", &types.Metadata{}), + ) + assert.NilError(t, err) + validators[i].Status = types.Bonded + + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) + if i < 100 { + tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 2) + } + + validators[i].Tokens = tokens + validators[i].DelegatorShares = math.LegacyNewDecFromInt(tokens) + + // add bonded coins + bondedPoolAmt = bondedPoolAmt.Add(tokens) + } + + validators = append(validators, genesisValidators...) + genesisState := types.NewGenesisState(params, validators, delegations) + + // mint coins in the bonded pool representing the validators coins + assert.NilError(t, + banktestutil.FundModuleAccount( + f.sdkCtx, + f.bankKeeper, + types.BondedPoolName, + sdk.NewCoins(sdk.NewCoin(params.BondDenom, bondedPoolAmt)), + ), + ) + + vals, err := f.stakingKeeper.InitGenesis(f.sdkCtx, genesisState) + assert.NilError(t, err) + + validatorUpdates := make([]module.ValidatorUpdate, 100) + for i, val := range validators[:100] { + validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)) + } + // remove genesis validator + vals = vals[:100] + assert.DeepEqual(t, validatorUpdates, vals) +} diff --git a/tests/integration/v2/staking/grpc_query_test.go b/tests/integration/v2/staking/grpc_query_test.go new file mode 100644 index 000000000000..dd3badb81feb --- /dev/null +++ b/tests/integration/v2/staking/grpc_query_test.go @@ -0,0 +1,915 @@ +package staking + +import ( + gocontext "context" + "fmt" + "testing" + + "gotest.tools/v3/assert" + + "cosmossdk.io/collections" + "cosmossdk.io/math" + "cosmossdk.io/x/staking/types" + + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/query" +) + +func createValidatorAccs(t *testing.T, f *fixture) ([]sdk.AccAddress, []types.Validator) { + t.Helper() + addrs, _, validators := createValidators(&testing.T{}, f, []int64{9, 8, 7}) + + // sort a copy of the validators, so that original validators does not + // have its order changed + sortedVals := make([]types.Validator, len(validators)) + copy(sortedVals, validators) + + return addrs, validators +} + +func TestGRPCQueryValidators(t *testing.T) { + t.Parallel() + f := initFixture(t) + + _, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + var req *types.QueryValidatorsRequest + testCases := []struct { + msg string + malleate func() + expPass bool + numVals int + hasNext bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryValidatorsRequest{} + }, + true, + len(vals), + false, + "", + }, + { + "empty status returns all the validators", + func() { + req = &types.QueryValidatorsRequest{Status: ""} + }, + true, + len(vals), + false, + "", + }, + { + "invalid request", + func() { + req = &types.QueryValidatorsRequest{Status: "test"} + }, + false, + 0, + false, + "invalid validator status test", + }, + { + "valid request", + func() { + req = &types.QueryValidatorsRequest{ + Status: types.Bonded.String(), + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + true, + 1, + true, + "", + }, + } + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + valsResp, err := queryClient.Validators(gocontext.Background(), req) + if tc.expPass { + assert.NilError(t, err) + assert.Assert(t, valsResp != nil) + assert.Equal(t, tc.numVals, len(valsResp.Validators)) + assert.Equal(t, uint64(len(vals)), valsResp.Pagination.Total) + + if tc.hasNext { + assert.Assert(t, valsResp.Pagination.NextKey != nil) + } else { + assert.Assert(t, valsResp.Pagination.NextKey == nil) + } + } else { + assert.ErrorContains(t, err, tc.expErrMsg) + } + }) + } +} + +func TestGRPCQueryDelegatorValidators(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + addrs, _ := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + params, err := f.stakingKeeper.Params.Get(ctx) + assert.NilError(t, err) + delValidators, err := f.stakingKeeper.GetDelegatorValidators(ctx, addrs[0], params.MaxValidators) + assert.NilError(t, err) + var req *types.QueryDelegatorValidatorsRequest + testCases := []struct { + msg string + malleate func() + expPass bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryDelegatorValidatorsRequest{} + }, + false, + "delegator address cannot be empty", + }, + { + "invalid delegator address", + func() { + req = &types.QueryDelegatorValidatorsRequest{ + DelegatorAddr: "invalid", + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + false, + "invalid bech32", + }, + { + "valid request", + func() { + req = &types.QueryDelegatorValidatorsRequest{ + DelegatorAddr: addrs[0].String(), + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + true, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.DelegatorValidators(gocontext.Background(), req) + if tc.expPass { + assert.NilError(t, err) + assert.Equal(t, 1, len(res.Validators)) + assert.Assert(t, res.Pagination.NextKey != nil) + assert.Equal(t, uint64(len(delValidators.Validators)), res.Pagination.Total) + } else { + assert.ErrorContains(t, err, tc.expErrMsg) + assert.Assert(t, res == nil) + } + }) + } +} + +func TestGRPCQueryDelegatorValidator(t *testing.T) { + t.Parallel() + f := initFixture(t) + + addrs, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + addr := addrs[1] + addrVal, addrVal1 := vals[0].OperatorAddress, vals[1].OperatorAddress + var req *types.QueryDelegatorValidatorRequest + testCases := []struct { + msg string + malleate func() + expPass bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryDelegatorValidatorRequest{} + }, + false, + "delegator address cannot be empty", + }, + { + "invalid delegator, validator pair", + func() { + req = &types.QueryDelegatorValidatorRequest{ + DelegatorAddr: addr.String(), + ValidatorAddr: addrVal, + } + }, + false, + "not found", + }, + { + "empty delegator address", + func() { + req = &types.QueryDelegatorValidatorRequest{ + DelegatorAddr: "", + ValidatorAddr: addrVal1, + } + }, + false, + "delegator address cannot be empty", + }, + { + "empty validator address", + func() { + req = &types.QueryDelegatorValidatorRequest{ + DelegatorAddr: addr.String(), + ValidatorAddr: "", + } + }, + false, + "validator address cannot be empty", + }, + { + "valid request", + func() { + req = &types.QueryDelegatorValidatorRequest{ + DelegatorAddr: addr.String(), + ValidatorAddr: addrVal1, + } + }, + true, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.DelegatorValidator(gocontext.Background(), req) + if tc.expPass { + assert.NilError(t, err) + assert.Equal(t, addrVal1, res.Validator.OperatorAddress) + } else { + assert.ErrorContains(t, err, tc.expErrMsg) + assert.Assert(t, res == nil) + } + }) + } +} + +func TestGRPCQueryDelegation(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + addrs, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + addrAcc, addrAcc1 := addrs[0], addrs[1] + addrVal := vals[0].OperatorAddress + valAddr, err := sdk.ValAddressFromBech32(addrVal) + assert.NilError(t, err) + delegation, found := f.stakingKeeper.Delegations.Get(ctx, collections.Join(addrAcc, valAddr)) + assert.Assert(t, found) + var req *types.QueryDelegationRequest + + testCases := []struct { + msg string + malleate func() + expPass bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryDelegationRequest{} + }, + false, + "delegator address cannot be empty", + }, + { + "invalid validator, delegator pair", + func() { + req = &types.QueryDelegationRequest{ + DelegatorAddr: addrAcc1.String(), + ValidatorAddr: addrVal, + } + }, + false, + fmt.Sprintf("delegation with delegator %s not found for validator %s", addrAcc1.String(), addrVal), + }, + { + "valid request", + func() { + req = &types.QueryDelegationRequest{DelegatorAddr: addrAcc.String(), ValidatorAddr: addrVal} + }, + true, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.Delegation(gocontext.Background(), req) + if tc.expPass { + assert.Equal(t, delegation.ValidatorAddress, res.DelegationResponse.Delegation.ValidatorAddress) + assert.Equal(t, delegation.DelegatorAddress, res.DelegationResponse.Delegation.DelegatorAddress) + assert.DeepEqual(t, sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponse.Balance) + } else { + assert.ErrorContains(t, err, tc.expErrMsg) + assert.Assert(t, res == nil) + } + }) + } +} + +func TestGRPCQueryDelegatorDelegations(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + addrs, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + addrAcc := addrs[0] + addrVal1 := vals[0].OperatorAddress + valAddr, err := sdk.ValAddressFromBech32(addrVal1) + assert.NilError(t, err) + delegation, found := f.stakingKeeper.Delegations.Get(ctx, collections.Join(addrAcc, valAddr)) + assert.Assert(t, found) + var req *types.QueryDelegatorDelegationsRequest + + testCases := []struct { + msg string + malleate func() + onSuccess func(response *types.QueryDelegatorDelegationsResponse) + expErr bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryDelegatorDelegationsRequest{} + }, + func(response *types.QueryDelegatorDelegationsResponse) {}, + true, + "delegator address cannot be empty", + }, + { + "valid request with no delegations", + func() { + req = &types.QueryDelegatorDelegationsRequest{DelegatorAddr: addrs[4].String()} + }, + func(response *types.QueryDelegatorDelegationsResponse) { + assert.Equal(t, uint64(0), response.Pagination.Total) + assert.Assert(t, len(response.DelegationResponses) == 0) + }, + false, + "", + }, + { + "valid request", + func() { + req = &types.QueryDelegatorDelegationsRequest{ + DelegatorAddr: addrAcc.String(), + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + func(response *types.QueryDelegatorDelegationsResponse) { + assert.Equal(t, uint64(2), response.Pagination.Total) + assert.Assert(t, len(response.DelegationResponses) == 1) + assert.DeepEqual(t, sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), response.DelegationResponses[0].Balance) + }, + false, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.DelegatorDelegations(gocontext.Background(), req) + if tc.expErr { + assert.ErrorContains(t, err, tc.expErrMsg) + } else { + assert.NilError(t, err) + tc.onSuccess(res) + } + }) + } +} + +func TestGRPCQueryValidatorDelegations(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + addrs, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + addrAcc := addrs[0] + addrVal1 := vals[1].OperatorAddress + valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) + addrVal2 := valAddrs[4] + valAddr, err := sdk.ValAddressFromBech32(addrVal1) + assert.NilError(t, err) + delegation, found := f.stakingKeeper.Delegations.Get(ctx, collections.Join(addrAcc, valAddr)) + assert.Assert(t, found) + + var req *types.QueryValidatorDelegationsRequest + testCases := []struct { + msg string + malleate func() + expPass bool + expErr bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryValidatorDelegationsRequest{} + }, + false, + true, + "validator address cannot be empty", + }, + { + "invalid validator address", + func() { + req = &types.QueryValidatorDelegationsRequest{ValidatorAddr: addrVal2.String()} + }, + false, + false, + "", + }, + { + "valid request", + func() { + req = &types.QueryValidatorDelegationsRequest{ + ValidatorAddr: addrVal1, + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + true, + false, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.ValidatorDelegations(gocontext.Background(), req) + switch { + case tc.expPass && !tc.expErr: + assert.NilError(t, err) + assert.Assert(t, len(res.DelegationResponses) == 1) + assert.Assert(t, res.Pagination.NextKey != nil) + assert.Equal(t, uint64(2), res.Pagination.Total) + assert.Equal(t, addrVal1, res.DelegationResponses[0].Delegation.ValidatorAddress) + assert.DeepEqual(t, sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponses[0].Balance) + case !tc.expPass && !tc.expErr: + assert.NilError(t, err) + assert.Assert(t, res.DelegationResponses == nil) + default: + assert.ErrorContains(t, err, tc.expErrMsg) + assert.Assert(t, res == nil) + } + }) + } +} + +func TestGRPCQueryUnbondingDelegation(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + addrs, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + addrAcc2 := addrs[1] + addrVal2 := vals[1].OperatorAddress + + unbondingTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 2) + valAddr, err1 := sdk.ValAddressFromBech32(addrVal2) + assert.NilError(t, err1) + _, _, err := f.stakingKeeper.Undelegate(ctx, addrAcc2, valAddr, math.LegacyNewDecFromInt(unbondingTokens)) + assert.NilError(t, err) + + unbond, found := f.stakingKeeper.GetUnbondingDelegation(ctx, addrAcc2, valAddr) + assert.Assert(t, found) + var req *types.QueryUnbondingDelegationRequest + testCases := []struct { + msg string + malleate func() + expPass bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryUnbondingDelegationRequest{} + }, + false, + "delegator address cannot be empty", + }, + { + "empty validator address", + func() { + req = &types.QueryUnbondingDelegationRequest{ + DelegatorAddr: addrAcc2.String(), + } + }, + false, + "validator address cannot be empty", + }, + { + "empty delegator address", + func() { + req = &types.QueryUnbondingDelegationRequest{ + ValidatorAddr: addrVal2, + } + }, + false, + "delegator address cannot be empty", + }, + { + "invalid validator address", + func() { + req = &types.QueryUnbondingDelegationRequest{ + DelegatorAddr: addrAcc2.String(), ValidatorAddr: sdk.AccAddress([]byte("invalid")).String(), + } + }, + false, + "hrp does not match bech32 prefix", + }, + { + "delegation not found for validator", + func() { + req = &types.QueryUnbondingDelegationRequest{ + DelegatorAddr: addrAcc2.String(), ValidatorAddr: sdk.ValAddress([]byte("invalid")).String(), + } + }, + false, + fmt.Sprintf("unbonding delegation with delegator %s not found for validator", addrAcc2.String()), + }, + { + "valid request", + func() { + req = &types.QueryUnbondingDelegationRequest{ + DelegatorAddr: addrAcc2.String(), ValidatorAddr: addrVal2, + } + }, + true, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.UnbondingDelegation(gocontext.Background(), req) + if tc.expPass { + assert.Assert(t, res != nil) + assert.DeepEqual(t, unbond, res.Unbond) + } else { + assert.ErrorContains(t, err, tc.expErrMsg) + assert.Assert(t, res == nil) + } + }) + } +} + +func TestGRPCQueryDelegatorUnbondingDelegations(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + addrs, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + addrAcc, addrAcc1 := addrs[0], addrs[1] + addrVal, addrVal2 := vals[0].OperatorAddress, vals[1].OperatorAddress + + unbondingTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 2) + valAddr1, err1 := sdk.ValAddressFromBech32(addrVal) + assert.NilError(t, err1) + _, _, err := f.stakingKeeper.Undelegate(ctx, addrAcc, valAddr1, math.LegacyNewDecFromInt(unbondingTokens)) + assert.NilError(t, err) + valAddr2, err1 := sdk.ValAddressFromBech32(addrVal2) + assert.NilError(t, err1) + _, _, err = f.stakingKeeper.Undelegate(ctx, addrAcc, valAddr2, math.LegacyNewDecFromInt(unbondingTokens)) + assert.NilError(t, err) + + unbond, found := f.stakingKeeper.GetUnbondingDelegation(ctx, addrAcc, valAddr1) + assert.Assert(t, found) + var req *types.QueryDelegatorUnbondingDelegationsRequest + testCases := []struct { + msg string + malleate func() + expPass bool + expErr bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryDelegatorUnbondingDelegationsRequest{} + }, + false, + true, + "delegator address cannot be empty", + }, + { + "invalid request", + func() { + req = &types.QueryDelegatorUnbondingDelegationsRequest{DelegatorAddr: addrAcc1.String()} + }, + false, + false, + "", + }, + { + "valid request", + func() { + req = &types.QueryDelegatorUnbondingDelegationsRequest{ + DelegatorAddr: addrAcc.String(), + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + true, + false, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.DelegatorUnbondingDelegations(gocontext.Background(), req) + switch { + case tc.expPass && !tc.expErr: + assert.NilError(t, err) + assert.Assert(t, res.Pagination.NextKey != nil) + assert.Equal(t, uint64(2), res.Pagination.Total) + assert.Assert(t, len(res.UnbondingResponses) == 1) + assert.DeepEqual(t, unbond, res.UnbondingResponses[0]) + case !tc.expPass && !tc.expErr: + assert.NilError(t, err) + assert.Assert(t, res.UnbondingResponses == nil) + default: + assert.ErrorContains(t, err, tc.expErrMsg) + assert.Assert(t, res == nil) + } + }) + } +} + +func TestGRPCQueryPoolParameters(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + bondDenom := sdk.DefaultBondDenom + + // Query pool + res, err := queryClient.Pool(gocontext.Background(), &types.QueryPoolRequest{}) + assert.NilError(t, err) + bondedPool := f.stakingKeeper.GetBondedPool(ctx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx) + assert.DeepEqual(t, f.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount, res.Pool.NotBondedTokens) + assert.DeepEqual(t, f.bankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount, res.Pool.BondedTokens) + + // Query Params + resp, err := queryClient.Params(gocontext.Background(), &types.QueryParamsRequest{}) + assert.NilError(t, err) + params, err := f.stakingKeeper.Params.Get(ctx) + assert.NilError(t, err) + assert.DeepEqual(t, params, resp.Params) +} + +func TestGRPCQueryRedelegations(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + addrs, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + addrAcc, addrAcc1 := addrs[0], addrs[1] + valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) + val1, val2, val3, val4 := vals[0], vals[1], valAddrs[3], valAddrs[4] + delAmount := f.stakingKeeper.TokensFromConsensusPower(ctx, 1) + _, err := f.stakingKeeper.Delegate(ctx, addrAcc1, delAmount, types.Unbonded, val1, true) + assert.NilError(t, err) + applyValidatorSetUpdates(t, ctx, f.stakingKeeper, -1) + + rdAmount := f.stakingKeeper.TokensFromConsensusPower(ctx, 1) + val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(val1.GetOperator()) + assert.NilError(t, err) + val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(val2.GetOperator()) + assert.NilError(t, err) + + _, err = f.stakingKeeper.BeginRedelegation(ctx, addrAcc1, val1bz, val2bz, math.LegacyNewDecFromInt(rdAmount)) + assert.NilError(t, err) + applyValidatorSetUpdates(t, ctx, f.stakingKeeper, -1) + + redel, found := f.stakingKeeper.Redelegations.Get(ctx, collections.Join3(addrAcc1.Bytes(), valAddrs[0].Bytes(), valAddrs[1].Bytes())) + assert.Assert(t, found) + + var req *types.QueryRedelegationsRequest + testCases := []struct { + msg string + malleate func() + expPass bool + expErr bool + expErrMsg string + }{ + { + "request redelegations for non existent addr", + func() { + req = &types.QueryRedelegationsRequest{DelegatorAddr: addrAcc.String()} + }, + false, + false, + fmt.Sprintf("redelegation not found for delegator address %s", addrAcc.String()), + }, + { + "request redelegations with non existent pairs", + func() { + req = &types.QueryRedelegationsRequest{ + DelegatorAddr: addrAcc.String(), SrcValidatorAddr: val3.String(), + DstValidatorAddr: val4.String(), + } + }, + false, + true, + fmt.Sprintf("redelegation not found for delegator address %s from validator address %s", + addrAcc.String(), val3.String()), + }, + { + "request redelegations with delegatoraddr, sourceValAddr, destValAddr", + func() { + req = &types.QueryRedelegationsRequest{ + DelegatorAddr: addrAcc1.String(), SrcValidatorAddr: val1.OperatorAddress, + DstValidatorAddr: val2.OperatorAddress, Pagination: &query.PageRequest{}, + } + }, + true, + false, + "", + }, + { + "request redelegations with delegatoraddr and sourceValAddr", + func() { + req = &types.QueryRedelegationsRequest{ + DelegatorAddr: addrAcc1.String(), SrcValidatorAddr: val1.OperatorAddress, + Pagination: &query.PageRequest{}, + } + }, + true, + false, + "", + }, + { + "query redelegations with sourceValAddr only", + func() { + req = &types.QueryRedelegationsRequest{ + SrcValidatorAddr: val1.GetOperator(), + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + true, + false, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.Redelegations(gocontext.Background(), req) + switch { + case tc.expPass && !tc.expErr: + assert.NilError(t, err) + assert.Assert(t, len(res.RedelegationResponses) == len(redel.Entries)) + assert.Equal(t, redel.DelegatorAddress, res.RedelegationResponses[0].Redelegation.DelegatorAddress) + assert.Equal(t, redel.ValidatorSrcAddress, res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress) + assert.Equal(t, redel.ValidatorDstAddress, res.RedelegationResponses[0].Redelegation.ValidatorDstAddress) + assert.Assert(t, len(redel.Entries) == len(res.RedelegationResponses[0].Entries)) + case !tc.expPass && !tc.expErr: + assert.NilError(t, err) + assert.Assert(t, res.RedelegationResponses == nil) + default: + assert.ErrorContains(t, err, tc.expErrMsg) + assert.Assert(t, res == nil) + } + }) + } +} + +func TestGRPCQueryValidatorUnbondingDelegations(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + addrs, vals := createValidatorAccs(t, f) + + qr := f.app.QueryHelper() + queryClient := types.NewQueryClient(qr) + + addrAcc1, _ := addrs[0], addrs[1] + val1 := vals[0] + + // undelegate + undelAmount := f.stakingKeeper.TokensFromConsensusPower(ctx, 2) + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(val1.GetOperator()) + assert.NilError(t, err) + _, _, err = f.stakingKeeper.Undelegate(ctx, addrAcc1, valbz, math.LegacyNewDecFromInt(undelAmount)) + assert.NilError(t, err) + applyValidatorSetUpdates(t, ctx, f.stakingKeeper, -1) + + var req *types.QueryValidatorUnbondingDelegationsRequest + testCases := []struct { + msg string + malleate func() + expPass bool + expErrMsg string + }{ + { + "empty request", + func() { + req = &types.QueryValidatorUnbondingDelegationsRequest{} + }, + false, + "validator address cannot be empty", + }, + { + "invalid validator address", + func() { + req = &types.QueryValidatorUnbondingDelegationsRequest{ + ValidatorAddr: "invalid", + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + false, + "invalid bech32", + }, + { + "valid request", + func() { + req = &types.QueryValidatorUnbondingDelegationsRequest{ + ValidatorAddr: val1.GetOperator(), + Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, + } + }, + true, + "", + }, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { + tc.malleate() + res, err := queryClient.ValidatorUnbondingDelegations(gocontext.Background(), req) + if tc.expPass { + assert.NilError(t, err) + assert.Equal(t, uint64(1), res.Pagination.Total) + assert.Equal(t, 1, len(res.UnbondingResponses)) + assert.Equal(t, res.UnbondingResponses[0].ValidatorAddress, val1.OperatorAddress) + } else { + assert.ErrorContains(t, err, tc.expErrMsg) + assert.Assert(t, res == nil) + } + }) + } +} diff --git a/tests/integration/v2/staking/msg_server_test.go b/tests/integration/v2/staking/msg_server_test.go new file mode 100644 index 000000000000..18546771f776 --- /dev/null +++ b/tests/integration/v2/staking/msg_server_test.go @@ -0,0 +1,390 @@ +package staking + +import ( + "testing" + "time" + + "gotest.tools/v3/assert" + + "cosmossdk.io/core/header" + "cosmossdk.io/math" + "cosmossdk.io/x/bank/testutil" + pooltypes "cosmossdk.io/x/protocolpool/types" + "cosmossdk.io/x/staking/keeper" + "cosmossdk.io/x/staking/types" + + "github.com/cosmos/cosmos-sdk/codec/address" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func TestCancelUnbondingDelegation(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + msgServer := keeper.NewMsgServerImpl(f.stakingKeeper) + bondDenom, err := f.stakingKeeper.BondDenom(ctx) + assert.NilError(t, err) + + // set the not bonded pool module account + notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx) + startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 5) + + assert.NilError(t, testutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + f.accountKeeper.SetModuleAccount(ctx, notBondedPool) + + moduleBalance := f.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom) + assert.DeepEqual(t, sdk.NewInt64Coin(bondDenom, startTokens.Int64()), moduleBalance) + + // accounts + addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, ctx, 2, math.NewInt(10000)) + valAddr := sdk.ValAddress(addrs[0]) + delegatorAddr := addrs[1] + + // setup a new validator with bonded status + validator, err := types.NewValidator(valAddr.String(), PKs[0], types.NewDescription("Validator", "", "", "", "", &types.Metadata{})) + validator.Status = types.Bonded + assert.NilError(t, err) + assert.NilError(t, f.stakingKeeper.SetValidator(ctx, validator)) + + validatorAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) + assert.NilError(t, err) + + // setting the ubd entry + unbondingAmount := sdk.NewInt64Coin(bondDenom, 5) + ubd := types.NewUnbondingDelegation( + delegatorAddr, validatorAddr, 10, + ctx.HeaderInfo().Time.Add(time.Minute*10), + unbondingAmount.Amount, + 0, + address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos"), + ) + + // set and retrieve a record + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(ctx, ubd)) + resUnbond, found := f.stakingKeeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) + assert.Assert(t, found) + assert.DeepEqual(t, ubd, resUnbond) + + testCases := []struct { + name string + exceptErr bool + req types.MsgCancelUnbondingDelegation + expErrMsg string + }{ + { + name: "entry not found at height", + exceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: sdk.NewCoin(bondDenom, math.NewInt(4)), + CreationHeight: 11, + }, + expErrMsg: "unbonding delegation entry is not found at block height", + }, + { + name: "invalid height", + exceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: sdk.NewCoin(bondDenom, math.NewInt(4)), + CreationHeight: 0, + }, + expErrMsg: "invalid height", + }, + { + name: "invalid coin", + exceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: sdk.NewCoin("dump_coin", math.NewInt(4)), + CreationHeight: 10, + }, + expErrMsg: "invalid coin denomination", + }, + { + name: "validator not exists", + exceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: sdk.ValAddress(sdk.AccAddress("asdsad")).String(), + Amount: unbondingAmount, + CreationHeight: 10, + }, + expErrMsg: "validator does not exist", + }, + { + name: "invalid delegator address", + exceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: "invalid_delegator_addrtess", + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: unbondingAmount, + CreationHeight: 0, + }, + expErrMsg: "decoding bech32 failed", + }, + { + name: "invalid amount", + exceptErr: true, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: unbondingAmount.Add(sdk.NewInt64Coin(bondDenom, 10)), + CreationHeight: 10, + }, + expErrMsg: "amount is greater than the unbonding delegation entry balance", + }, + { + name: "success", + exceptErr: false, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1)), + CreationHeight: 10, + }, + }, + { + name: "success", + exceptErr: false, + req: types.MsgCancelUnbondingDelegation{ + DelegatorAddress: resUnbond.DelegatorAddress, + ValidatorAddress: resUnbond.ValidatorAddress, + Amount: unbondingAmount.Sub(unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1))), + CreationHeight: 10, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + _, err := msgServer.CancelUnbondingDelegation(ctx, &tc.req) + if tc.exceptErr { + assert.ErrorContains(t, err, tc.expErrMsg) + } else { + assert.NilError(t, err) + balanceForNotBondedPool := f.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom) + assert.DeepEqual(t, balanceForNotBondedPool, moduleBalance.Sub(tc.req.Amount)) + moduleBalance = moduleBalance.Sub(tc.req.Amount) + } + }) + } +} + +func TestRotateConsPubKey(t *testing.T) { + t.Parallel() + f := initFixture(t) + + ctx := f.sdkCtx + stakingKeeper := f.stakingKeeper + bankKeeper := f.bankKeeper + accountKeeper := f.accountKeeper + + msgServer := keeper.NewMsgServerImpl(stakingKeeper) + bondDenom, err := stakingKeeper.BondDenom(ctx) + assert.NilError(t, err) + + params, err := stakingKeeper.Params.Get(ctx) + assert.NilError(t, err) + + params.KeyRotationFee = sdk.NewInt64Coin(bondDenom, 10) + err = stakingKeeper.Params.Set(ctx, params) + assert.NilError(t, err) + + addrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 5, stakingKeeper.TokensFromConsensusPower(ctx, 100)) + valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) + + // create 5 validators + for i := 0; i < 5; i++ { + comm := types.NewCommissionRates(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0)) + acc := f.accountKeeper.NewAccountWithAddress(ctx, sdk.AccAddress(valAddrs[i])) + f.accountKeeper.SetAccount(ctx, acc) + msg, err := types.NewMsgCreateValidator(valAddrs[i].String(), PKs[i], sdk.NewCoin(sdk.DefaultBondDenom, stakingKeeper.TokensFromConsensusPower(ctx, 30)), + types.Description{Moniker: "NewVal"}, comm, math.OneInt()) + assert.NilError(t, err) + _, err = msgServer.CreateValidator(ctx, msg) + assert.NilError(t, err) + } + + // call endblocker to update the validator state + _, err = stakingKeeper.EndBlocker(ctx.WithBlockHeight(ctx.BlockHeader().Height + 1)) + assert.NilError(t, err) + + params, err = stakingKeeper.Params.Get(ctx) + assert.NilError(t, err) + + validators, err := stakingKeeper.GetAllValidators(ctx) + assert.NilError(t, err) + assert.Equal(t, len(validators) >= 5, true) + + testCases := []struct { + name string + malleate func() sdk.Context + pass bool + validator string + newPubKey cryptotypes.PubKey + expErrMsg string + expHistoryObjs int + fees sdk.Coin + }{ + { + name: "successful consensus pubkey rotation", + malleate: func() sdk.Context { + return ctx + }, + validator: validators[0].GetOperator(), + newPubKey: PKs[499], + pass: true, + expHistoryObjs: 1, + fees: params.KeyRotationFee, + }, + { + name: "non existing validator check", + malleate: func() sdk.Context { + return ctx + }, + validator: sdk.ValAddress("non_existing_val").String(), + newPubKey: PKs[498], + pass: false, + expErrMsg: "validator does not exist", + }, + { + name: "pubkey already associated with another validator", + malleate: func() sdk.Context { + return ctx + }, + validator: validators[0].GetOperator(), + newPubKey: validators[1].ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey), + pass: false, + expErrMsg: "validator already exist for this pubkey; must use new validator pubkey", + }, + { + name: "consensus pubkey rotation limit check", + malleate: func() sdk.Context { + params, err := stakingKeeper.Params.Get(ctx) + assert.NilError(t, err) + + params.KeyRotationFee = sdk.NewInt64Coin(bondDenom, 10) + err = stakingKeeper.Params.Set(ctx, params) + assert.NilError(t, err) + + msg, err := types.NewMsgRotateConsPubKey( + validators[1].GetOperator(), + PKs[498], + ) + assert.NilError(t, err) + _, err = msgServer.RotateConsPubKey(ctx, msg) + assert.NilError(t, err) + + return ctx + }, + validator: validators[1].GetOperator(), + newPubKey: PKs[497], + pass: false, + expErrMsg: "exceeding maximum consensus pubkey rotations within unbonding period", + }, + { + name: "limit reached, but should rotate after the unbonding period", + malleate: func() sdk.Context { + params, err := stakingKeeper.Params.Get(ctx) + assert.NilError(t, err) + + params.KeyRotationFee = sdk.NewInt64Coin(bondDenom, 10) + err = stakingKeeper.Params.Set(ctx, params) + assert.NilError(t, err) + + msg, err := types.NewMsgRotateConsPubKey( + validators[3].GetOperator(), + PKs[495], + ) + + assert.NilError(t, err) + _, err = msgServer.RotateConsPubKey(ctx, msg) + assert.NilError(t, err) + ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) + + // this shouldn't remove the existing keys from waiting queue since unbonding time isn't reached + _, err = stakingKeeper.EndBlocker(ctx) + assert.NilError(t, err) + + msg, err = types.NewMsgRotateConsPubKey( + validators[3].GetOperator(), + PKs[494], + ) + + assert.NilError(t, err) + _, err = msgServer.RotateConsPubKey(ctx, msg) + assert.Error(t, err, "exceeding maximum consensus pubkey rotations within unbonding period") + + ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) + + newCtx := ctx.WithHeaderInfo(header.Info{Height: ctx.BlockHeight() + 1, Time: ctx.HeaderInfo().Time.Add(params.UnbondingTime)}).WithBlockHeight(ctx.BlockHeight() + 1) + // this should remove keys from waiting queue since unbonding time is reached + _, err = stakingKeeper.EndBlocker(newCtx) + assert.NilError(t, err) + + return newCtx + }, + validator: validators[3].GetOperator(), + newPubKey: PKs[494], + pass: true, + expErrMsg: "", + expHistoryObjs: 2, + fees: params.KeyRotationFee, + }, + } + + for _, testCase := range testCases { + t.Run(testCase.name, func(t *testing.T) { + newCtx := testCase.malleate() + oldDistrBalance := bankKeeper.GetBalance(newCtx, accountKeeper.GetModuleAddress(pooltypes.ModuleName), bondDenom) + msg, err := types.NewMsgRotateConsPubKey( + testCase.validator, + testCase.newPubKey, + ) + assert.NilError(t, err) + + _, err = msgServer.RotateConsPubKey(newCtx, msg) + + if testCase.pass { + assert.NilError(t, err) + + _, err = stakingKeeper.EndBlocker(newCtx) + assert.NilError(t, err) + + // rotation fee payment from sender to distrtypes + newDistrBalance := bankKeeper.GetBalance(newCtx, accountKeeper.GetModuleAddress(pooltypes.ModuleName), bondDenom) + assert.DeepEqual(t, newDistrBalance, oldDistrBalance.Add(testCase.fees)) + + valBytes, err := stakingKeeper.ValidatorAddressCodec().StringToBytes(testCase.validator) + assert.NilError(t, err) + + // validator consensus pubkey update check + validator, err := stakingKeeper.GetValidator(newCtx, valBytes) + assert.NilError(t, err) + + consAddr, err := validator.GetConsAddr() + assert.NilError(t, err) + assert.DeepEqual(t, consAddr, testCase.newPubKey.Address().Bytes()) + + // consensus rotation history set check + historyObjects, err := stakingKeeper.GetValidatorConsPubKeyRotationHistory(newCtx, valBytes) + assert.NilError(t, err) + assert.Equal(t, len(historyObjects), testCase.expHistoryObjs) + + historyObjects, err = stakingKeeper.GetBlockConsPubKeyRotationHistory(newCtx) + assert.NilError(t, err) + assert.Equal(t, len(historyObjects), 1) + + } else { + assert.ErrorContains(t, err, testCase.expErrMsg) + } + }) + } +} diff --git a/tests/integration/v2/staking/slash_test.go b/tests/integration/v2/staking/slash_test.go new file mode 100644 index 000000000000..88f533ea2619 --- /dev/null +++ b/tests/integration/v2/staking/slash_test.go @@ -0,0 +1,767 @@ +package staking + +import ( + "context" + "testing" + "time" + + "github.com/stretchr/testify/require" + "gotest.tools/v3/assert" + + "cosmossdk.io/collections" + "cosmossdk.io/core/header" + "cosmossdk.io/depinject" + "cosmossdk.io/log" + "cosmossdk.io/math" + _ "cosmossdk.io/x/accounts" + bankkeeper "cosmossdk.io/x/bank/keeper" + banktestutil "cosmossdk.io/x/bank/testutil" + _ "cosmossdk.io/x/consensus" + _ "cosmossdk.io/x/distribution" + distributionkeeper "cosmossdk.io/x/distribution/keeper" + _ "cosmossdk.io/x/protocolpool" + _ "cosmossdk.io/x/slashing" + slashingkeeper "cosmossdk.io/x/slashing/keeper" + "cosmossdk.io/x/staking/keeper" + "cosmossdk.io/x/staking/testutil" + "cosmossdk.io/x/staking/types" + + "github.com/cosmos/cosmos-sdk/codec/address" + "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" + "github.com/cosmos/cosmos-sdk/testutil/configurator" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" +) + +// bootstrapSlashTest creates 3 validators and bootstrap the app. +func bootstrapSlashTest(t *testing.T, power int64) (*fixture, []sdk.AccAddress, []sdk.ValAddress) { + t.Helper() + t.Parallel() + f := initFixture(t) + + addrDels, addrVals := generateAddresses(f, 100) + + amt := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + require.NoError(t, err) + totalSupply := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(int64(len(addrDels))))) + + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), totalSupply)) + + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + + numVals := int64(3) + bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(numVals))) + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + + // set bonded pool balance + f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), bondedCoins)) + + for i := int64(0); i < numVals; i++ { + validator := testutil.NewValidator(t, addrVals[i], PKs[i]) + validator, _ = validator.AddTokensFromDel(amt) + validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator, true) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, validator)) + } + + return f, addrDels, addrVals +} + +// tests slashUnbondingDelegation +func TestSlashUnbondingDelegation(t *testing.T) { + f, addrDels, addrVals := bootstrapSlashTest(t, 10) + + fraction := math.LegacyNewDecWithPrec(5, 1) + + // set an unbonding delegation with expiration timestamp (beyond which the + // unbonding delegation shouldn't be slashed) + ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 0, + time.Unix(5, 0), math.NewInt(10), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) + + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) + + // unbonding started prior to the infraction height, stakw didn't contribute + slashAmount, err := f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 1, fraction) + assert.NilError(t, err) + assert.Assert(t, slashAmount.Equal(math.NewInt(0))) + + // after the expiration time, no longer eligible for slashing + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(10, 0)}) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) + slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction) + assert.NilError(t, err) + assert.Assert(t, slashAmount.Equal(math.NewInt(0))) + + // test valid slash, before expiration timestamp and to which stake contributed + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + oldUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, notBondedPool.GetAddress()) + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(0, 0)}) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) + slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction) + assert.NilError(t, err) + assert.Assert(t, slashAmount.Equal(math.NewInt(5))) + ubd, found := f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + assert.Assert(t, found) + assert.Assert(t, len(ubd.Entries) == 1) + + // initial balance unchanged + assert.DeepEqual(t, math.NewInt(10), ubd.Entries[0].InitialBalance) + + // balance decreased + assert.DeepEqual(t, math.NewInt(5), ubd.Entries[0].Balance) + newUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, notBondedPool.GetAddress()) + diffTokens := oldUnbondedPoolBalances.Sub(newUnbondedPoolBalances...) + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + assert.Assert(t, diffTokens.AmountOf(bondDenom).Equal(math.NewInt(5))) +} + +// tests slashRedelegation +func TestSlashRedelegation(t *testing.T) { + f, addrDels, addrVals := bootstrapSlashTest(t, 10) + fraction := math.LegacyNewDecWithPrec(5, 1) + + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + + // add bonded tokens to pool for (re)delegations + startCoins := sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 15)) + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + _ = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), startCoins)) + f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + + // set a redelegation with an expiration timestamp beyond which the + // redelegation shouldn't be slashed + rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, + time.Unix(5, 0), math.NewInt(10), math.LegacyNewDec(10), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) + + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) + + // set the associated delegation + del := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDec(10)) + assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, del)) + + // started redelegating prior to the current height, stake didn't contribute to infraction + validator, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + assert.Assert(t, found) + slashAmount, err := f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 1, fraction) + assert.NilError(t, err) + assert.Assert(t, slashAmount.Equal(math.NewInt(0))) + + // after the expiration time, no longer eligible for slashing + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(10, 0)}) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) + validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + assert.Assert(t, found) + slashAmount, err = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction) + assert.NilError(t, err) + assert.Assert(t, slashAmount.Equal(math.NewInt(0))) + + balances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + + // test valid slash, before expiration timestamp and to which stake contributed + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(0, 0)}) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) + validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + assert.Assert(t, found) + slashAmount, err = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction) + assert.NilError(t, err) + assert.Assert(t, slashAmount.Equal(math.NewInt(5))) + rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + assert.Assert(t, found) + assert.Assert(t, len(rd.Entries) == 1) + + // end block + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + + // initialbalance unchanged + assert.DeepEqual(t, math.NewInt(10), rd.Entries[0].InitialBalance) + + // shares decreased + del, found = f.stakingKeeper.Delegations.Get(f.sdkCtx, collections.Join(addrDels[0], addrVals[1])) + assert.Assert(t, found) + assert.Equal(t, int64(5), del.Shares.RoundInt64()) + + // pool bonded tokens should decrease + burnedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, slashAmount)) + assert.DeepEqual(t, balances.Sub(burnedCoins...), f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())) +} + +// test slash at a negative height +// this just represents pre-genesis and should have the same effect as slashing at height 0 +func TestSlashAtNegativeHeight(t *testing.T) { + f, _, _ := bootstrapSlashTest(t, 10) + consAddr := sdk.ConsAddress(PKs[0].Address()) + fraction := math.LegacyNewDecWithPrec(5, 1) + + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + _, err := f.stakingKeeper.Slash(f.sdkCtx, consAddr, -2, 10, fraction) + assert.NilError(t, err) + + // read updated state + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + + // end block + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) + assert.NilError(t, err) + + validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + assert.Assert(t, found) + // power decreased + assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + + // pool bonded shares decreased + newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 5).String(), diffTokens.String()) +} + +// tests Slash at the current height +func TestSlashValidatorAtCurrentHeight(t *testing.T) { + f, _, _ := bootstrapSlashTest(t, 10) + consAddr := sdk.ConsAddress(PKs[0].Address()) + fraction := math.LegacyNewDecWithPrec(5, 1) + + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction) + assert.NilError(t, err) + + // read updated state + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + + // end block + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) + assert.NilError(t, err) + + validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + assert.Assert(t, found) + // power decreased + assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + + // pool bonded shares decreased + newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 5).String(), diffTokens.String()) +} + +// TestSlashWithUnbondingDelegation tests the slashing of a validator with an unbonding delegation. +// It sets up an environment with a validator and an unbonding delegation, and then performs slashing +// operations on the validator. The test verifies that the slashing correctly affects the unbonding +// delegation and the validator's power. +func TestSlashWithUnbondingDelegation(t *testing.T) { + f, addrDels, addrVals := bootstrapSlashTest(t, 10) + + consAddr := sdk.ConsAddress(PKs[0].Address()) + fraction := math.LegacyNewDecWithPrec(5, 1) + + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + + // set an unbonding delegation with expiration timestamp beyond which the + // unbonding delegation shouldn't be slashed + ubdTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 4) + ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, time.Unix(0, 0), ubdTokens, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) + + // slash validator for the first time + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Height: 12}) + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction) + assert.NilError(t, err) + + // end block + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + + // read updating unbonding delegation + ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + assert.Assert(t, found) + assert.Assert(t, len(ubd.Entries) == 1) + + // balance decreased + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 2), ubd.Entries[0].Balance) + + // bonded tokens burned + newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 3), diffTokens) + + // read updated validator + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + + // power decreased by 3 - 6 stake originally bonded at the time of infraction + // was still bonded at the time of discovery and was slashed by half, 4 stake + // bonded at the time of discovery hadn't been bonded at the time of infraction + // and wasn't slashed + assert.Equal(t, int64(7), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + + // slash validator again + f.sdkCtx = f.sdkCtx.WithBlockHeight(13) + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) + assert.NilError(t, err) + + ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + assert.Assert(t, found) + assert.Assert(t, len(ubd.Entries) == 1) + + // balance decreased again + assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) + + // bonded tokens burned again + newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6), diffTokens) + + // read updated validator + validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + + // power decreased by 3 again + assert.Equal(t, int64(4), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + + // slash validator again + // all originally bonded stake has been slashed, so this will have no effect + // on the unbonding delegation, but it will slash stake bonded since the infraction + // this may not be the desirable behavior, ref https://github.com/cosmos/cosmos-sdk/issues/1440 + f.sdkCtx = f.sdkCtx.WithBlockHeight(13) + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) + assert.NilError(t, err) + + ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + assert.Assert(t, found) + assert.Assert(t, len(ubd.Entries) == 1) + + // balance unchanged + assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) + + // bonded tokens burned again + newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 9), diffTokens) + + // read updated validator + validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + + // power decreased by 3 again + assert.Equal(t, int64(1), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + + // slash validator again + // all originally bonded stake has been slashed, so this will have no effect + // on the unbonding delegation, but it will slash stake bonded since the infraction + // this may not be the desirable behavior, ref https://github.com/cosmos/cosmos-sdk/issues/1440 + f.sdkCtx = f.sdkCtx.WithBlockHeight(13) + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) + assert.NilError(t, err) + + ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + assert.Assert(t, found) + assert.Assert(t, len(ubd.Entries) == 1) + + // balance unchanged + assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) + + // just 1 bonded token burned again since that's all the validator now has + newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10), diffTokens) + + // apply TM updates + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) + + // read updated validator + // power decreased by 1 again, validator is out of stake + // validator should be in unbonding period + validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Equal(t, validator.GetStatus(), sdk.Unbonding) +} + +// tests Slash at a previous height with a redelegation +func TestSlashWithRedelegation(t *testing.T) { + f, addrDels, addrVals := bootstrapSlashTest(t, 10) + consAddr := sdk.ConsAddress(PKs[0].Address()) + fraction := math.LegacyNewDecWithPrec(5, 1) + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + + // set a redelegation + rdTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6) + rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdTokens, math.LegacyNewDecFromInt(rdTokens), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) + + // set the associated delegation + del := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDecFromInt(rdTokens)) + assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, del)) + + // update bonded tokens + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + rdCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdTokens.MulRaw(2))) + + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), rdCoins)) + + f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + + oldBonded := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + oldNotBonded := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + + // slash validator + f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction) + assert.NilError(t, err) + + burnAmount := math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(fraction).TruncateInt() + + bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + // burn bonded tokens from only from delegations + bondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) + + notBondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) + oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + + // read updating redelegation + rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + assert.Assert(t, found) + assert.Assert(t, len(rd.Entries) == 1) + // read updated validator + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + // power decreased by 2 - 4 stake originally bonded at the time of infraction + // was still bonded at the time of discovery and was slashed by half, 4 stake + // bonded at the time of discovery hadn't been bonded at the time of infraction + // and wasn't slashed + assert.Equal(t, int64(8), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + + // slash the validator again + _, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) + assert.NilError(t, err) + burnAmount = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 7) + + // read updated pool + bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + // seven bonded tokens burned + bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) + assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) + + bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) + + notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) + oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + + // read updating redelegation + rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + assert.Assert(t, found) + assert.Assert(t, len(rd.Entries) == 1) + // read updated validator + validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + // power decreased by 4 + assert.Equal(t, int64(4), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + + // slash the validator again, by 100% + f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) + _, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Assert(t, found) + + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) + assert.NilError(t, err) + + burnAmount = math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(math.LegacyOneDec()).TruncateInt() + burnAmount = burnAmount.Sub(math.LegacyOneDec().MulInt(rdTokens).TruncateInt()) + + // read updated pool + bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) + notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) + oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + + // read updating redelegation + rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + assert.Assert(t, found) + assert.Assert(t, len(rd.Entries) == 1) + // apply TM updates + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) + // read updated validator + // validator decreased to zero power, should be in unbonding period + validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Equal(t, validator.GetStatus(), sdk.Unbonding) + + // slash the validator again, by 100% + // no stake remains to be slashed + f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) + // validator still in unbonding period + validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Equal(t, validator.GetStatus(), sdk.Unbonding) + + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) + assert.NilError(t, err) + + // read updated pool + bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldBonded, bondedPoolBalance)) + notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) + + // read updating redelegation + rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + assert.Assert(t, found) + assert.Assert(t, len(rd.Entries) == 1) + // read updated validator + // power still zero, still in unbonding period + validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + assert.Equal(t, validator.GetStatus(), sdk.Unbonding) +} + +// tests Slash at a previous height with both an unbonding delegation and a redelegation +func TestSlashBoth(t *testing.T) { + f, addrDels, addrVals := bootstrapSlashTest(t, 10) + fraction := math.LegacyNewDecWithPrec(5, 1) + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + + // set a redelegation with expiration timestamp beyond which the + // redelegation shouldn't be slashed + rdATokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6) + rdA := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdATokens, math.LegacyNewDecFromInt(rdATokens), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rdA)) + + // set the associated delegation + delA := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDecFromInt(rdATokens)) + assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, delA)) + + // set an unbonding delegation with expiration timestamp (beyond which the + // unbonding delegation shouldn't be slashed) + ubdATokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 4) + ubdA := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, + time.Unix(0, 0), ubdATokens, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubdA)) + + bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdATokens.MulRaw(2))) + notBondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, ubdATokens)) + + // update bonded tokens + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), bondedCoins)) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), notBondedCoins)) + + f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + + oldBonded := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + oldNotBonded := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + // slash validator + f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, sdk.GetConsAddress(PKs[0])) + assert.Assert(t, found) + consAddr0 := sdk.ConsAddress(PKs[0].Address()) + _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr0, 10, 10, fraction) + assert.NilError(t, err) + + burnedNotBondedAmount := fraction.MulInt(ubdATokens).TruncateInt() + burnedBondAmount := math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(fraction).TruncateInt() + burnedBondAmount = burnedBondAmount.Sub(burnedNotBondedAmount) + + // read updated pool + bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + bondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldBonded.Sub(burnedBondAmount), bondedPoolBalance)) + + notBondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + assert.Assert(math.IntEq(t, oldNotBonded.Sub(burnedNotBondedAmount), notBondedPoolBalance)) + + // read updating redelegation + rdA, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + assert.Assert(t, found) + assert.Assert(t, len(rdA.Entries) == 1) + // read updated validator + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, sdk.GetConsAddress(PKs[0])) + assert.Assert(t, found) + // power not decreased, all stake was bonded since + assert.Equal(t, int64(10), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) +} + +func TestSlashAmount(t *testing.T) { + f, _, _ := bootstrapSlashTest(t, 10) + consAddr := sdk.ConsAddress(PKs[0].Address()) + fraction := math.LegacyNewDecWithPrec(5, 1) + burnedCoins, err := f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction) + assert.NilError(t, err) + assert.Assert(t, burnedCoins.GT(math.ZeroInt())) + + // test the case where the validator was not found, which should return no coins + _, addrVals := generateAddresses(f, 100) + noBurned, err := f.stakingKeeper.Slash(f.sdkCtx, sdk.ConsAddress(addrVals[0]), f.sdkCtx.BlockHeight(), 10, fraction) + assert.NilError(t, err) + assert.Assert(t, math.NewInt(0).Equal(noBurned)) +} + +// TestFixAvoidFullSlashPenalty fixes the following issue: https://github.com/cosmos/cosmos-sdk/issues/20641 +func TestFixAvoidFullSlashPenalty(t *testing.T) { + // setup + var authKeeper authkeeper.AccountKeeperI + var stakingKeeper *keeper.Keeper + var bankKeeper bankkeeper.Keeper + var slashKeeper slashingkeeper.Keeper + var distrKeeper distributionkeeper.Keeper + app, err := simtestutil.Setup(depinject.Configs( + depinject.Supply(log.NewNopLogger()), + configurator.NewAppConfig( + configurator.AccountsModule(), + configurator.AuthModule(), + configurator.BankModule(), + configurator.ConsensusModule(), + configurator.StakingModule(), + configurator.SlashingModule(), + configurator.ProtocolPoolModule(), + configurator.DistributionModule(), + ), + ), &authKeeper, &stakingKeeper, &bankKeeper, &slashKeeper, &distrKeeper) + require.NoError(t, err) + ctx := app.BaseApp.NewContext(false) + stakingMsgServer := keeper.NewMsgServerImpl(stakingKeeper) + bondDenom, err := stakingKeeper.BondDenom(ctx) + require.NoError(t, err) + // create 2 evil validators, controlled by attacker + evilValPubKey := secp256k1.GenPrivKey().PubKey() + evilValPubKey2 := secp256k1.GenPrivKey().PubKey() + // attacker user account + badtestAcc := sdk.AccAddress("addr1_______________") + // normal users who stakes on evilValAddr1 + testAcc1 := sdk.AccAddress("addr2_______________") + testAcc2 := sdk.AccAddress("addr3_______________") + createAccount(t, ctx, authKeeper, badtestAcc) + createAccount(t, ctx, authKeeper, testAcc1) + createAccount(t, ctx, authKeeper, testAcc2) + // fund all accounts + testCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, stakingKeeper.TokensFromConsensusPower(ctx, 1))) + require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, badtestAcc, testCoins)) + require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, testAcc1, testCoins)) + require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, testAcc2, testCoins)) + // create evilValAddr1 for normal staking operations + evilValAddr1 := sdk.ValAddress(evilValPubKey.Address()) + createAccount(t, ctx, authKeeper, evilValAddr1.Bytes()) + require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, sdk.AccAddress(evilValAddr1), testCoins)) + createValMsg1, _ := types.NewMsgCreateValidator( + evilValAddr1.String(), evilValPubKey, testCoins[0], types.Description{Details: "test"}, types.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) + _, err = stakingMsgServer.CreateValidator(ctx, createValMsg1) + require.NoError(t, err) + // very small amount coin for evilValAddr2 + smallCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, math.NewInt(1))) + // create evilValAddr2 to circumvent slashing + evilValAddr2 := sdk.ValAddress(evilValPubKey2.Address()) + require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, sdk.AccAddress(evilValAddr2), smallCoins)) + createValMsg3, _ := types.NewMsgCreateValidator( + evilValAddr2.String(), evilValPubKey2, smallCoins[0], types.Description{Details: "test"}, types.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) + createAccount(t, ctx, authKeeper, evilValAddr2.Bytes()) + _, err = stakingMsgServer.CreateValidator(ctx, createValMsg3) + 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)) + require.NoError(t, err) + // all accs delegate to evilValAddr1 + delMsg := types.NewMsgDelegate(badtestAcc.String(), evilValAddr1.String(), testCoins[0]) + _, err = stakingMsgServer.Delegate(ctx, delMsg) + require.NoError(t, err) + delMsg = types.NewMsgDelegate(testAcc1.String(), evilValAddr1.String(), testCoins[0]) + _, err = stakingMsgServer.Delegate(ctx, delMsg) + require.NoError(t, err) + delMsg = types.NewMsgDelegate(testAcc2.String(), evilValAddr1.String(), testCoins[0]) + _, err = stakingMsgServer.Delegate(ctx, delMsg) + require.NoError(t, err) + // next block + ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + require.NoError(t, err) + // 1. badtestAcc redelegates from evilValAddr1 to evilValAddr2 + redelMsg := types.NewMsgBeginRedelegate(badtestAcc.String(), evilValAddr1.String(), evilValAddr2.String(), smallCoins[0]) + _, err = stakingMsgServer.BeginRedelegate(ctx, redelMsg) + require.NoError(t, err) + // 2. evilValAddr2 undelegates its self-delegation and jail themselves + undelMsg := types.NewMsgUndelegate(sdk.AccAddress(evilValAddr2).String(), evilValAddr2.String(), smallCoins[0]) + _, err = stakingMsgServer.Undelegate(ctx, undelMsg) + require.NoError(t, err) + // assert evilValAddr2 is jailed + evilVal2, err := stakingKeeper.GetValidator(ctx, evilValAddr2) + require.NoError(t, err) + require.True(t, evilVal2.Jailed) + // next block + ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) + require.NoError(t, err) + // assert invariants + _, stop := keeper.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) + // evilValAddr1 is bad! + // lets slash evilValAddr1 with a 100% penalty + evilVal, err := stakingKeeper.GetValidator(ctx, evilValAddr1) + require.NoError(t, err) + evilValConsAddr, err := evilVal.GetConsAddr() + require.NoError(t, err) + evilPower := stakingKeeper.TokensToConsensusPower(ctx, evilVal.Tokens) + err = slashKeeper.Slash(ctx, evilValConsAddr, math.LegacyMustNewDecFromStr("1.0"), evilPower, 3) + require.NoError(t, err) +} + +func createAccount(t *testing.T, ctx context.Context, k authkeeper.AccountKeeperI, addr sdk.AccAddress) { + t.Helper() + acc := k.NewAccountWithAddress(ctx, addr) + k.SetAccount(ctx, acc) +} diff --git a/tests/integration/v2/staking/unbonding_test.go b/tests/integration/v2/staking/unbonding_test.go new file mode 100644 index 000000000000..6ad0f385c0e1 --- /dev/null +++ b/tests/integration/v2/staking/unbonding_test.go @@ -0,0 +1,460 @@ +package staking + +import ( + "testing" + "time" + + "go.uber.org/mock/gomock" + "gotest.tools/v3/assert" + + "cosmossdk.io/core/header" + "cosmossdk.io/math" + banktestutil "cosmossdk.io/x/bank/testutil" + stakingkeeper "cosmossdk.io/x/staking/keeper" + "cosmossdk.io/x/staking/testutil" + "cosmossdk.io/x/staking/types" + + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +// SetupUnbondingTests creates two validators and setup mocked staking hooks for testing unbonding +func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uint64) (bondDenom string, addrDels []sdk.AccAddress, addrVals []sdk.ValAddress) { + t.Helper() + // setup hooks + mockCtrl := gomock.NewController(t) + mockStackingHooks := testutil.NewMockStakingHooks(mockCtrl) + mockStackingHooks.EXPECT().AfterDelegationModified(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().AfterUnbondingInitiated(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx sdk.Context, id uint64) error { + *hookCalled = true + // save id + *ubdeID = id + // call back to stop unbonding + err := f.stakingKeeper.PutUnbondingOnHold(f.sdkCtx, id) + assert.NilError(t, err) + + return nil + }).AnyTimes() + mockStackingHooks.EXPECT().AfterValidatorBeginUnbonding(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().AfterValidatorBonded(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().AfterValidatorCreated(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().AfterValidatorRemoved(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().BeforeDelegationCreated(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().BeforeDelegationRemoved(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().BeforeDelegationSharesModified(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().BeforeValidatorModified(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().BeforeValidatorSlashed(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockStackingHooks.EXPECT().AfterConsensusPubKeyUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + f.stakingKeeper.SetHooks(types.NewMultiStakingHooks(mockStackingHooks)) + + addrDels = simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, 2, math.NewInt(10000)) + addrVals = simtestutil.ConvertAddrsToValAddrs(addrDels) + + valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10) + startTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 20) + + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + + // Create a validator + validator1 := testutil.NewValidator(t, addrVals[0], PKs[0]) + validator1, issuedShares1 := validator1.AddTokensFromDel(valTokens) + assert.DeepEqual(t, valTokens, issuedShares1.RoundInt()) + + validator1 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator1, true) + assert.Assert(math.IntEq(t, valTokens, validator1.BondedTokens())) + assert.Assert(t, validator1.IsBonded()) + + // Create a delegator + delegation := types.NewDelegation(addrDels[0].String(), addrVals[0].String(), issuedShares1) + assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, delegation)) + + // Create a validator to redelegate to + validator2 := testutil.NewValidator(t, addrVals[1], PKs[1]) + validator2, issuedShares2 := validator2.AddTokensFromDel(valTokens) + assert.DeepEqual(t, valTokens, issuedShares2.RoundInt()) + + validator2 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator2, true) + assert.Equal(t, types.Bonded, validator2.Status) + assert.Assert(t, validator2.IsBonded()) + + return bondDenom, addrDels, addrVals +} + +func doUnbondingDelegation( + t *testing.T, + stakingKeeper *stakingkeeper.Keeper, + bankKeeper types.BankKeeper, + ctx sdk.Context, + bondDenom string, + addrDels []sdk.AccAddress, + addrVals []sdk.ValAddress, + hookCalled *bool, +) (completionTime time.Time, bondedAmt, notBondedAmt math.Int) { + t.Helper() + // UNDELEGATE + // Save original bonded and unbonded amounts + bondedAmt1 := bankKeeper.GetBalance(ctx, stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + notBondedAmt1 := bankKeeper.GetBalance(ctx, stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + + var err error + undelegateAmount := math.LegacyNewDec(1) + completionTime, undelegatedAmount, err := stakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], undelegateAmount) + assert.NilError(t, err) + assert.Assert(t, undelegateAmount.Equal(math.LegacyNewDecFromInt(undelegatedAmount))) + // check that the unbonding actually happened + bondedAmt2 := bankKeeper.GetBalance(ctx, stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount + notBondedAmt2 := bankKeeper.GetBalance(ctx, stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount + // Bonded amount is less + assert.Assert(math.IntEq(t, bondedAmt1.SubRaw(1), bondedAmt2)) + // Unbonded amount is more + assert.Assert(math.IntEq(t, notBondedAmt1.AddRaw(1), notBondedAmt2)) + + // Check that the unbonding happened- we look up the entry and see that it has the correct number of shares + unbondingDelegations, err := stakingKeeper.GetUnbondingDelegationsFromValidator(ctx, addrVals[0]) + assert.NilError(t, err) + assert.DeepEqual(t, math.NewInt(1), unbondingDelegations[0].Entries[0].Balance) + + // check that our hook was called + assert.Assert(t, *hookCalled) + + return completionTime, bondedAmt2, notBondedAmt2 +} + +func doRedelegation( + t *testing.T, + stakingKeeper *stakingkeeper.Keeper, + ctx sdk.Context, + addrDels []sdk.AccAddress, + addrVals []sdk.ValAddress, + hookCalled *bool, +) (completionTime time.Time) { + t.Helper() + var err error + completionTime, err = stakingKeeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], math.LegacyNewDec(1)) + assert.NilError(t, err) + + // Check that the redelegation happened- we look up the entry and see that it has the correct number of shares + redelegations, err := stakingKeeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) + assert.NilError(t, err) + assert.Equal(t, 1, len(redelegations)) + assert.DeepEqual(t, math.LegacyNewDec(1), redelegations[0].Entries[0].SharesDst) + + // check that our hook was called + assert.Assert(t, *hookCalled) + + return completionTime +} + +func doValidatorUnbonding( + t *testing.T, + stakingKeeper *stakingkeeper.Keeper, + ctx sdk.Context, + addrVal sdk.ValAddress, + hookCalled *bool, +) (validator types.Validator) { + t.Helper() + validator, found := stakingKeeper.GetValidator(ctx, addrVal) + assert.Assert(t, found) + // Check that status is bonded + assert.Equal(t, types.BondStatus(3), validator.Status) + + validator, err := stakingKeeper.BeginUnbondingValidator(ctx, validator) + assert.NilError(t, err) + + // Check that status is unbonding + assert.Equal(t, types.BondStatus(2), validator.Status) + + // check that our hook was called + assert.Assert(t, *hookCalled) + + return validator +} + +func TestValidatorUnbondingOnHold1(t *testing.T) { + t.Parallel() + f := initFixture(t) + + var ( + hookCalled bool + ubdeID uint64 + ) + + _, _, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) + + // Start unbonding first validator + validator := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[0], &hookCalled) + + completionTime := validator.UnbondingTime + completionHeight := validator.UnbondingHeight + + // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE + err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + assert.NilError(t, err) + + // Try to unbond validator + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + + // Check that validator unbonding is not complete (is not mature yet) + validator, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + assert.Assert(t, found) + assert.Equal(t, types.Unbonding, validator.Status) + unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + assert.NilError(t, err) + assert.Equal(t, 1, len(unbondingVals)) + assert.Equal(t, validator.OperatorAddress, unbondingVals[0]) + + // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime.Add(time.Duration(1))}) + f.sdkCtx = f.sdkCtx.WithBlockHeight(completionHeight + 1) + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + + // Check that validator unbonding is complete + validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + assert.Assert(t, found) + assert.Equal(t, types.Unbonded, validator.Status) + unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + assert.NilError(t, err) + assert.Equal(t, 0, len(unbondingVals)) +} + +func TestValidatorUnbondingOnHold2(t *testing.T) { + t.Parallel() + f := initFixture(t) + + var ( + hookCalled bool + ubdeID uint64 + ubdeIDs []uint64 + ) + + _, _, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) + + // Start unbonding first validator + validator1 := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[0], &hookCalled) + ubdeIDs = append(ubdeIDs, ubdeID) + + // Reset hookCalled flag + hookCalled = false + + // Start unbonding second validator + validator2 := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[1], &hookCalled) + ubdeIDs = append(ubdeIDs, ubdeID) + + // Check that there are two unbonding operations + assert.Equal(t, 2, len(ubdeIDs)) + + // Check that both validators have same unbonding time + assert.Equal(t, validator1.UnbondingTime, validator2.UnbondingTime) + + completionTime := validator1.UnbondingTime + completionHeight := validator1.UnbondingHeight + + // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime.Add(time.Duration(1))}) + f.sdkCtx = f.sdkCtx.WithBlockHeight(completionHeight + 1) + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + + // Check that unbonding is not complete for both validators + validator1, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + assert.Assert(t, found) + assert.Equal(t, types.Unbonding, validator1.Status) + validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + assert.Assert(t, found) + assert.Equal(t, types.Unbonding, validator2.Status) + unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + assert.NilError(t, err) + assert.Equal(t, 2, len(unbondingVals)) + assert.Equal(t, validator1.OperatorAddress, unbondingVals[0]) + assert.Equal(t, validator2.OperatorAddress, unbondingVals[1]) + + // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE + err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeIDs[0]) + assert.NilError(t, err) + + // Try again to unbond validators + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + + // Check that unbonding is complete for validator1, but not for validator2 + validator1, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + assert.Assert(t, found) + assert.Equal(t, types.Unbonded, validator1.Status) + validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + assert.Assert(t, found) + assert.Equal(t, types.Unbonding, validator2.Status) + unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + assert.NilError(t, err) + assert.Equal(t, 1, len(unbondingVals)) + assert.Equal(t, validator2.OperatorAddress, unbondingVals[0]) + + // Unbonding for validator2 can complete + err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeIDs[1]) + assert.NilError(t, err) + + // Try again to unbond validators + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + + // Check that unbonding is complete for validator2 + validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + assert.Assert(t, found) + assert.Equal(t, types.Unbonded, validator2.Status) + unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + assert.NilError(t, err) + assert.Equal(t, 0, len(unbondingVals)) +} + +func TestRedelegationOnHold1(t *testing.T) { + t.Parallel() + f := initFixture(t) + + var ( + hookCalled bool + ubdeID uint64 + ) + + // _, app, ctx := createTestInput(t) + _, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) + completionTime := doRedelegation(t, f.stakingKeeper, f.sdkCtx, addrDels, addrVals, &hookCalled) + + // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE + err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + assert.NilError(t, err) + + // Redelegation is not complete - still exists + redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) + assert.NilError(t, err) + assert.Equal(t, 1, len(redelegations)) + + // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) + _, err = f.stakingKeeper.CompleteRedelegation(f.sdkCtx, addrDels[0], addrVals[0], addrVals[1]) + assert.NilError(t, err) + + // Redelegation is complete and record is gone + redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) + assert.NilError(t, err) + assert.Equal(t, 0, len(redelegations)) +} + +func TestRedelegationOnHold2(t *testing.T) { + t.Parallel() + f := initFixture(t) + + var ( + hookCalled bool + ubdeID uint64 + ) + + // _, app, ctx := createTestInput(t) + _, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) + completionTime := doRedelegation(t, f.stakingKeeper, f.sdkCtx, addrDels, addrVals, &hookCalled) + + // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) + _, err := f.stakingKeeper.CompleteRedelegation(f.sdkCtx, addrDels[0], addrVals[0], addrVals[1]) + assert.NilError(t, err) + + // Redelegation is not complete - still exists + redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) + assert.NilError(t, err) + assert.Equal(t, 1, len(redelegations)) + + // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE + err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + assert.NilError(t, err) + + // Redelegation is complete and record is gone + redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) + assert.NilError(t, err) + assert.Equal(t, 0, len(redelegations)) +} + +func TestUnbondingDelegationOnHold1(t *testing.T) { + t.Parallel() + f := initFixture(t) + + var ( + hookCalled bool + ubdeID uint64 + ) + + // _, app, ctx := createTestInput(t) + bondDenom, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) + for _, addr := range addrDels { + acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) + f.accountKeeper.SetAccount(f.sdkCtx, acc) + } + completionTime, bondedAmt1, notBondedAmt1 := doUnbondingDelegation(t, f.stakingKeeper, f.bankKeeper, f.sdkCtx, bondDenom, addrDels, addrVals, &hookCalled) + + // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE + err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + assert.NilError(t, err) + + bondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + notBondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + + // Bonded and unbonded amounts are the same as before because the completionTime has not yet passed and so the + // unbondingDelegation has not completed + assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt3)) + assert.Assert(math.IntEq(t, notBondedAmt1, notBondedAmt3)) + + // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) + _, err = f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0]) + assert.NilError(t, err) + + // Check that the unbonding was finally completed + bondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + notBondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + + assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt5)) + // Not bonded amount back to what it was originally + assert.Assert(math.IntEq(t, notBondedAmt1.SubRaw(1), notBondedAmt5)) +} + +func TestUnbondingDelegationOnHold2(t *testing.T) { + t.Parallel() + f := initFixture(t) + + var ( + hookCalled bool + ubdeID uint64 + ) + + // _, app, ctx := createTestInput(t) + bondDenom, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) + for _, addr := range addrDels { + acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) + f.accountKeeper.SetAccount(f.sdkCtx, acc) + } + completionTime, bondedAmt1, notBondedAmt1 := doUnbondingDelegation(t, f.stakingKeeper, f.bankKeeper, f.sdkCtx, bondDenom, addrDels, addrVals, &hookCalled) + + // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE + f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) + _, err := f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0]) + assert.NilError(t, err) + + bondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + notBondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + + // Bonded and unbonded amounts are the same as before because the completionTime has not yet passed and so the + // unbondingDelegation has not completed + assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt3)) + assert.Assert(math.IntEq(t, notBondedAmt1, notBondedAmt3)) + + // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE + err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + assert.NilError(t, err) + + // Check that the unbonding was finally completed + bondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + notBondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + + assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt5)) + // Not bonded amount back to what it was originally + assert.Assert(math.IntEq(t, notBondedAmt1.SubRaw(1), notBondedAmt5)) +} diff --git a/tests/integration/v2/staking/validator_bench_test.go b/tests/integration/v2/staking/validator_bench_test.go new file mode 100644 index 000000000000..c9b7de3867a8 --- /dev/null +++ b/tests/integration/v2/staking/validator_bench_test.go @@ -0,0 +1,181 @@ +package staking + +import ( + "bytes" + "fmt" + "testing" + + "cosmossdk.io/collections" + "cosmossdk.io/math" + storetypes "cosmossdk.io/store/types" + banktestutil "cosmossdk.io/x/bank/testutil" + "cosmossdk.io/x/staking/types" + + sdk "github.com/cosmos/cosmos-sdk/types" +) + +func BenchmarkGetValidator(b *testing.B) { + // 900 is the max number we are allowed to use in order to avoid simtestutil.CreateTestPubKeys + // panic: encoding/hex: odd length hex string + powersNumber := 900 + + var totalPower int64 + powers := make([]int64, powersNumber) + for i := range powers { + powers[i] = int64(i) + totalPower += int64(i) + } + + f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) + + for _, validator := range vals { + if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { + panic(err) + } + } + + b.ResetTimer() + for n := 0; n < b.N; n++ { + for _, addr := range valAddrs { + _, _ = f.stakingKeeper.GetValidator(f.sdkCtx, addr) + } + } +} + +func BenchmarkGetValidatorDelegations(b *testing.B) { + var totalPower int64 + powersNumber := 10 + + powers := make([]int64, powersNumber) + for i := range powers { + powers[i] = int64(i) + totalPower += int64(i) + } + + f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) + for _, validator := range vals { + if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { + panic(err) + } + } + + delegationsNum := 1000 + for _, val := range valAddrs { + for i := 0; i < delegationsNum; i++ { + delegator := sdk.AccAddress(fmt.Sprintf("address%d", i)) + err := banktestutil.FundAccount(f.sdkCtx, f.bankKeeper, delegator, + sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(int64(i))))) + if err != nil { + panic(err) + } + NewDel := types.NewDelegation(delegator.String(), val.String(), math.LegacyNewDec(int64(i))) + + if err := f.stakingKeeper.SetDelegation(f.sdkCtx, NewDel); err != nil { + panic(err) + } + } + } + + b.ResetTimer() + for n := 0; n < b.N; n++ { + updateValidatorDelegations(f, valAddrs[0], sdk.ValAddress("val")) + } +} + +func BenchmarkGetValidatorDelegationsLegacy(b *testing.B) { + var totalPower int64 + powersNumber := 10 + + powers := make([]int64, powersNumber) + for i := range powers { + powers[i] = int64(i) + totalPower += int64(i) + } + + f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) + + for _, validator := range vals { + if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { + panic(err) + } + } + + delegationsNum := 1000 + for _, val := range valAddrs { + for i := 0; i < delegationsNum; i++ { + delegator := sdk.AccAddress(fmt.Sprintf("address%d", i)) + err := banktestutil.FundAccount(f.sdkCtx, f.bankKeeper, delegator, + sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(int64(i))))) + if err != nil { + panic(err) + } + NewDel := types.NewDelegation(delegator.String(), val.String(), math.LegacyNewDec(int64(i))) + if err := f.stakingKeeper.SetDelegation(f.sdkCtx, NewDel); err != nil { + panic(err) + } + } + } + + b.ResetTimer() + for n := 0; n < b.N; n++ { + updateValidatorDelegationsLegacy(f, valAddrs[0], sdk.ValAddress("val")) + } +} + +func updateValidatorDelegationsLegacy(f *fixture, existingValAddr, newValAddr sdk.ValAddress) { + storeKey := f.keys[types.StoreKey] + cdc, k := f.cdc, f.stakingKeeper + + store := f.sdkCtx.KVStore(storeKey) + + iterator := storetypes.KVStorePrefixIterator(store, types.DelegationKey) + defer iterator.Close() + + for ; iterator.Valid(); iterator.Next() { + delegation := types.MustUnmarshalDelegation(cdc, iterator.Value()) + valAddr, err := k.ValidatorAddressCodec().StringToBytes(delegation.GetValidatorAddr()) + if err != nil { + panic(err) + } + + if bytes.EqualFold(valAddr, existingValAddr) { + if err := k.RemoveDelegation(f.sdkCtx, delegation); err != nil { + panic(err) + } + delegation.ValidatorAddress = newValAddr.String() + if err := k.SetDelegation(f.sdkCtx, delegation); err != nil { + panic(err) + } + } + } +} + +func updateValidatorDelegations(f *fixture, existingValAddr, newValAddr sdk.ValAddress) { + k := f.stakingKeeper + + rng := collections.NewPrefixedPairRange[sdk.ValAddress, sdk.AccAddress](existingValAddr) + err := k.DelegationsByValidator.Walk(f.sdkCtx, rng, func(key collections.Pair[sdk.ValAddress, sdk.AccAddress], _ []byte) (stop bool, err error) { + valAddr, delAddr := key.K1(), key.K2() + + delegation, err := k.Delegations.Get(f.sdkCtx, collections.Join(delAddr, valAddr)) + if err != nil { + return true, err + } + + // remove old operator addr from delegation + if err := k.RemoveDelegation(f.sdkCtx, delegation); err != nil { + return true, err + } + + delegation.ValidatorAddress = newValAddr.String() + // add with new operator addr + if err := k.SetDelegation(f.sdkCtx, delegation); err != nil { + return true, err + } + + return false, nil + }) + if err != nil { + panic(err) + } +} diff --git a/tests/integration/v2/staking/validator_test.go b/tests/integration/v2/staking/validator_test.go new file mode 100644 index 000000000000..53462a96f440 --- /dev/null +++ b/tests/integration/v2/staking/validator_test.go @@ -0,0 +1,887 @@ +package staking + +import ( + "fmt" + "testing" + + "gotest.tools/v3/assert" + + "cosmossdk.io/math" + banktestutil "cosmossdk.io/x/bank/testutil" + "cosmossdk.io/x/staking/keeper" + "cosmossdk.io/x/staking/testutil" + "cosmossdk.io/x/staking/types" + + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" +) + +func newMonikerValidator(tb testing.TB, operator sdk.ValAddress, pubKey cryptotypes.PubKey, moniker string) types.Validator { + tb.Helper() + v, err := types.NewValidator(operator.String(), pubKey, types.Description{Moniker: moniker}) + assert.NilError(tb, err) + return v +} + +func bootstrapValidatorTest(tb testing.TB, power int64, numAddrs int) (*fixture, []sdk.AccAddress, []sdk.ValAddress) { + tb.Helper() + f := initFixture(tb) + + addrDels, addrVals := generateAddresses(f, numAddrs) + + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(tb, err) + + amt := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + totalSupply := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(int64(len(addrDels))))) + + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + // set bonded pool supply + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + + assert.NilError(tb, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), totalSupply)) + + return f, addrDels, addrVals +} + +func initValidators(tb testing.TB, power int64, numAddrs int, powers []int64) (*fixture, []sdk.AccAddress, []sdk.ValAddress, []types.Validator) { + tb.Helper() + f, addrs, valAddrs := bootstrapValidatorTest(tb, power, numAddrs) + pks := simtestutil.CreateTestPubKeys(numAddrs) + + vs := make([]types.Validator, len(powers)) + for i, power := range powers { + vs[i] = testutil.NewValidator(tb, sdk.ValAddress(addrs[i]), pks[i]) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + vs[i], _ = vs[i].AddTokensFromDel(tokens) + } + return f, addrs, valAddrs, vs +} + +func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { + numVals := 10 + maxVals := 5 + + // create context, keeper, and pool for tests + f, _, valAddrs := bootstrapValidatorTest(t, 1, 100) + + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + // create keeper parameters + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + params.MaxValidators = uint32(maxVals) + assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + + // create a random pool + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1234))))) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10000))))) + + f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + + validators := make([]types.Validator, numVals) + for i := 0; i < len(validators); i++ { + moniker := fmt.Sprintf("val#%d", int64(i)) + val := newMonikerValidator(t, valAddrs[i], PKs[i], moniker) + delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, int64((i+1)*10)) + val, _ = val.AddTokensFromDel(delTokens) + + val = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, val, true) + validators[i] = val + } + + nextCliffVal := validators[numVals-maxVals+1] + + // remove enough tokens to kick out the validator below the current cliff + // validator and next in line cliff validator + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, nextCliffVal)) + shares := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 21) + nextCliffVal, _ = nextCliffVal.RemoveDelShares(math.LegacyNewDecFromInt(shares)) + _ = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, nextCliffVal, true) + + expectedValStatus := map[int]sdk.BondStatus{ + 9: sdk.Bonded, 8: sdk.Bonded, 7: sdk.Bonded, 5: sdk.Bonded, 4: sdk.Bonded, + 0: sdk.Unbonding, 1: sdk.Unbonding, 2: sdk.Unbonding, 3: sdk.Unbonding, 6: sdk.Unbonding, + } + + // require all the validators have their respective statuses + for valIdx, status := range expectedValStatus { + valAddr := validators[valIdx].OperatorAddress + addr, err := sdk.ValAddressFromBech32(valAddr) + assert.NilError(t, err) + val, _ := f.stakingKeeper.GetValidator(f.sdkCtx, addr) + + assert.Equal( + t, status, val.GetStatus(), + fmt.Sprintf("expected validator at index %v to have status: %x", valIdx, status), + ) + } +} + +func TestSlashToZeroPowerRemoved(t *testing.T) { + // initialize setup + f, _, addrVals := bootstrapValidatorTest(t, 100, 20) + + // add a validator + validator := testutil.NewValidator(t, addrVals[0], PKs[0]) + valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) + + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, valTokens)))) + + f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + + validator, _ = validator.AddTokensFromDel(valTokens) + assert.Equal(t, types.Unbonded, validator.Status) + assert.DeepEqual(t, valTokens, validator.Tokens) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, validator)) + validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator, true) + assert.DeepEqual(t, valTokens, validator.Tokens) + + // slash the validator by 100% + _, err = f.stakingKeeper.Slash(f.sdkCtx, sdk.ConsAddress(PKs[0].Address()), 0, 100, math.LegacyOneDec()) + assert.NilError(t, err) + // apply TM updates + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) + // validator should be unbonding + validator, _ = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + assert.Equal(t, validator.GetStatus(), sdk.Unbonding) +} + +// test how the validators are sorted, tests GetBondedValidatorsByPower +func TestGetValidatorSortingUnmixed(t *testing.T) { + f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) + + // initialize some validators into the state + amts := []math.Int{ + math.NewIntFromUint64(0), + f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(100), + f.stakingKeeper.PowerReduction(f.sdkCtx), + f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(400), + f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(200), + } + n := len(amts) + var validators [5]types.Validator + for i, amt := range amts { + validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) + validators[i].Status = types.Bonded + validators[i].Tokens = amt + validators[i].DelegatorShares = math.LegacyNewDecFromInt(amt) + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) + } + + // first make sure everything made it in to the gotValidator group + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, n, len(resValidators)) + assert.DeepEqual(t, math.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[0].BondedTokens()) + assert.DeepEqual(t, math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[1].BondedTokens()) + assert.DeepEqual(t, math.NewInt(100).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[2].BondedTokens()) + assert.DeepEqual(t, math.NewInt(1).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[3].BondedTokens()) + assert.DeepEqual(t, math.NewInt(0), resValidators[4].BondedTokens()) + assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators) + assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators) + assert.Equal(t, validators[1].OperatorAddress, resValidators[2].OperatorAddress, "%v", resValidators) + assert.Equal(t, validators[2].OperatorAddress, resValidators[3].OperatorAddress, "%v", resValidators) + assert.Equal(t, validators[0].OperatorAddress, resValidators[4].OperatorAddress, "%v", resValidators) + + // test a basic increase in voting power + validators[3].Tokens = math.NewInt(500).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, len(resValidators), n) + assert.Assert(ValEq(t, validators[3], resValidators[0])) + + // test a decrease in voting power + validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, len(resValidators), n) + assert.Assert(ValEq(t, validators[3], resValidators[0])) + assert.Assert(ValEq(t, validators[4], resValidators[1])) + + // test equal voting power, different age + validators[3].Tokens = math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) + f.sdkCtx = f.sdkCtx.WithBlockHeight(10) + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, len(resValidators), n) + assert.Assert(ValEq(t, validators[3], resValidators[0])) + assert.Assert(ValEq(t, validators[4], resValidators[1])) + + // no change in voting power - no change in sort + f.sdkCtx = f.sdkCtx.WithBlockHeight(20) + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[4], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, len(resValidators), n) + assert.Assert(ValEq(t, validators[3], resValidators[0])) + assert.Assert(ValEq(t, validators[4], resValidators[1])) + + // change in voting power of both validators, both still in v-set, no age change + validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) + validators[4].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, len(resValidators), n) + f.sdkCtx = f.sdkCtx.WithBlockHeight(30) + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[4], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, len(resValidators), n, "%v", resValidators) + assert.Assert(ValEq(t, validators[3], resValidators[0])) + assert.Assert(ValEq(t, validators[4], resValidators[1])) +} + +func TestGetValidatorSortingMixed(t *testing.T) { + f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + assert.NilError(t, err) + + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 501))))) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 0))))) + + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + + // now 2 max resValidators + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + params.MaxValidators = 2 + assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + + // initialize some validators into the state + amts := []math.Int{ + math.NewIntFromUint64(0), + f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(100), + f.stakingKeeper.PowerReduction(f.sdkCtx), + f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(400), + f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(200), + } + + var validators [5]types.Validator + for i, amt := range amts { + validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) + validators[i].DelegatorShares = math.LegacyNewDecFromInt(amt) + validators[i].Status = types.Bonded + validators[i].Tokens = amt + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) + } + + val0, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[0])) + assert.Assert(t, found) + val1, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[1])) + assert.Assert(t, found) + val2, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[2])) + assert.Assert(t, found) + val3, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[3])) + assert.Assert(t, found) + val4, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[4])) + assert.Assert(t, found) + assert.Equal(t, types.Bonded, val0.Status) + assert.Equal(t, types.Unbonding, val1.Status) + assert.Equal(t, types.Unbonding, val2.Status) + assert.Equal(t, types.Bonded, val3.Status) + assert.Equal(t, types.Bonded, val4.Status) + + // first make sure everything made it in to the gotValidator group + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + // The validators returned should match the max validators + assert.Equal(t, 2, len(resValidators)) + assert.DeepEqual(t, math.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[0].BondedTokens()) + assert.DeepEqual(t, math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[1].BondedTokens()) + assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators) + assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators) +} + +// TODO separate out into multiple tests +func TestGetValidatorsEdgeCases(t *testing.T) { + f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) + + // set max validators to 2 + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + nMax := uint32(2) + params.MaxValidators = nMax + assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + // initialize some validators into the state + powers := []int64{0, 100, 400, 400} + var validators [4]types.Validator + for i, power := range powers { + moniker := fmt.Sprintf("val#%d", int64(i)) + validators[i] = newMonikerValidator(t, sdk.ValAddress(addrs[i]), PKs[i], moniker) + + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + validators[i] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) + } + + // ensure that the first two bonded validators are the largest validators + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, nMax, uint32(len(resValidators))) + assert.Assert(ValEq(t, validators[2], resValidators[0])) + assert.Assert(ValEq(t, validators[3], resValidators[1])) + + // delegate 500 tokens to validator 0 + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) + delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 500) + validators[0], _ = validators[0].AddTokensFromDel(delTokens) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + + newTokens := sdk.NewCoins() + + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), newTokens)) + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + + // test that the two largest validators are + // a) validator 0 with 500 tokens + // b) validator 2 with 400 tokens (delegated before validator 3) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, nMax, uint32(len(resValidators))) + assert.Assert(ValEq(t, validators[0], resValidators[0])) + assert.Assert(ValEq(t, validators[2], resValidators[1])) + + // A validator which leaves the bonded validator set due to a decrease in voting power, + // then increases to the original voting power, does not get its spot back in the + // case of a tie. + // + // Order of operations for this test: + // - validator 3 enter validator set with 1 new token + // - validator 3 removed validator set by removing 201 tokens (validator 2 enters) + // - validator 3 adds 200 tokens (equal to validator 2 now) and does not get its spot back + + // validator 3 enters bonded validator set + f.sdkCtx = f.sdkCtx.WithBlockHeight(40) + + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[3].GetOperator()) + assert.NilError(t, err) + + validators[3], err = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + assert.NilError(t, err) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) + validators[3], _ = validators[3].AddTokensFromDel(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1)) + + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + newTokens = sdk.NewCoins(sdk.NewCoin(params.BondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1))) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), newTokens)) + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + + validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, nMax, uint32(len(resValidators))) + assert.Assert(ValEq(t, validators[0], resValidators[0])) + assert.Assert(ValEq(t, validators[3], resValidators[1])) + + // validator 3 kicked out temporarily + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) + rmTokens := validators[3].TokensFromShares(math.LegacyNewDec(201)).TruncateInt() + validators[3], _ = validators[3].RemoveDelShares(math.LegacyNewDec(201)) + + bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) + f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + + validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, nMax, uint32(len(resValidators))) + assert.Assert(ValEq(t, validators[0], resValidators[0])) + assert.Assert(ValEq(t, validators[2], resValidators[1])) + + // validator 3 does not get spot back + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) + validators[3], _ = validators[3].AddTokensFromDel(math.NewInt(200)) + + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, math.NewInt(200))))) + f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + + validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, nMax, uint32(len(resValidators))) + assert.Assert(ValEq(t, validators[0], resValidators[0])) + assert.Assert(ValEq(t, validators[2], resValidators[1])) + _, exists := f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + assert.Assert(t, exists) +} + +func TestValidatorBondHeight(t *testing.T) { + f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) + + // now 2 max resValidators + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + params.MaxValidators = 2 + assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + // initialize some validators into the state + var validators [3]types.Validator + validators[0] = testutil.NewValidator(t, sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0]) + validators[1] = testutil.NewValidator(t, sdk.ValAddress(addrs[1]), PKs[1]) + validators[2] = testutil.NewValidator(t, sdk.ValAddress(addrs[2]), PKs[2]) + + tokens0 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 200) + tokens1 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) + tokens2 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) + validators[0], _ = validators[0].AddTokensFromDel(tokens0) + validators[1], _ = validators[1].AddTokensFromDel(tokens1) + validators[2], _ = validators[2].AddTokensFromDel(tokens2) + + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) + + //////////////////////////////////////// + // If two validators both increase to the same voting power in the same block, + // the one with the first transaction should become bonded + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], true) + validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], true) + + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, uint32(len(resValidators)), params.MaxValidators) + + assert.Assert(ValEq(t, validators[0], resValidators[0])) + assert.Assert(ValEq(t, validators[1], resValidators[1])) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[1])) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[2])) + delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 50) + validators[1], _ = validators[1].AddTokensFromDel(delTokens) + validators[2], _ = validators[2].AddTokensFromDel(delTokens) + validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, params.MaxValidators, uint32(len(resValidators))) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], true) + assert.Assert(ValEq(t, validators[0], resValidators[0])) + assert.Assert(ValEq(t, validators[2], resValidators[1])) +} + +func TestFullValidatorSetPowerChange(t *testing.T) { + f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + max := 2 + params.MaxValidators = uint32(2) + assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + + // initialize some validators into the state + powers := []int64{0, 100, 400, 400, 200} + var validators [5]types.Validator + for i, power := range powers { + validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) + } + for i := range powers { + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[i].GetOperator()) + assert.NilError(t, err) + + validators[i], err = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + assert.NilError(t, err) + } + assert.Equal(t, types.Unbonded, validators[0].Status) + assert.Equal(t, types.Unbonding, validators[1].Status) + assert.Equal(t, types.Bonded, validators[2].Status) + assert.Equal(t, types.Bonded, validators[3].Status) + assert.Equal(t, types.Unbonded, validators[4].Status) + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, max, len(resValidators)) + assert.Assert(ValEq(t, validators[2], resValidators[0])) // in the order of txs + assert.Assert(ValEq(t, validators[3], resValidators[1])) + + // test a swap in voting power + + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 600) + validators[0], _ = validators[0].AddTokensFromDel(tokens) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + assert.NilError(t, err) + assert.Equal(t, max, len(resValidators)) + assert.Assert(ValEq(t, validators[0], resValidators[0])) + assert.Assert(ValEq(t, validators[2], resValidators[1])) +} + +func TestApplyAndReturnValidatorSetUpdatesAllNone(t *testing.T) { + f, _, _ := bootstrapValidatorTest(t, 1000, 20) + + powers := []int64{10, 20} + var validators [2]types.Validator + for i, power := range powers { + valPubKey := PKs[i+1] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + + validators[i] = testutil.NewValidator(t, valAddr, valPubKey) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + } + + // test from nothing to something + // tendermintUpdate set: {} -> {c1, c3} + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[1])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[1])) + + updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) + assert.NilError(t, err) + val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) + assert.NilError(t, err) + validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) + validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) +} + +func TestApplyAndReturnValidatorSetUpdatesIdentical(t *testing.T) { + f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) + + powers := []int64{10, 20} + var validators [2]types.Validator + for i, power := range powers { + validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) + + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + + } + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + + // test identical, + // tendermintUpdate set: {} -> {} + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) +} + +func TestApplyAndReturnValidatorSetUpdatesSingleValueChange(t *testing.T) { + f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) + + powers := []int64{10, 20} + var validators [2]types.Validator + for i, power := range powers { + validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) + + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + + } + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + + // test single value change + // tendermintUpdate set: {} -> {c1'} + validators[0].Status = types.Bonded + validators[0].Tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 600) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + + updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) +} + +func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) { + powers := []int64{10, 20} + // TODO: use it in other places + f, _, _, validators := initValidators(t, 1000, 20, powers) + + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + + // test multiple value change + // tendermintUpdate set: {c1, c3} -> {c1', c3'} + delTokens1 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 190) + delTokens2 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 80) + validators[0], _ = validators[0].AddTokensFromDel(delTokens1) + validators[1], _ = validators[1].AddTokensFromDel(delTokens2) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) + + updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) +} + +func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) { + powers := []int64{10, 20, 5, 15, 25} + f, _, _, validators := initValidators(t, 1000, 20, powers) + + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + + // test validator added at the beginning + // tendermintUpdate set: {} -> {c0} + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[2])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[2])) + updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) + assert.NilError(t, err) + validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) + assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + + // test validator added at the beginning + // tendermintUpdate set: {} -> {c0} + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[3])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[3])) + updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + val3bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[3].GetOperator()) + assert.NilError(t, err) + validators[3], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val3bz) + assert.DeepEqual(t, validators[3].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + + // test validator added at the end + // tendermintUpdate set: {} -> {c0} + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[4])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[4])) + updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + val4bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[4].GetOperator()) + assert.NilError(t, err) + validators[4], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val4bz) + assert.DeepEqual(t, validators[4].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) +} + +func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) { + f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) + params := types.DefaultParams() + params.MaxValidators = 2 + err := f.stakingKeeper.Params.Set(f.sdkCtx, params) + assert.NilError(t, err) + powers := []int64{10, 20, 5} + var validators [5]types.Validator + for i, power := range powers { + validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + } + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + + // test validator added at the end but not inserted in the valset + // tendermintUpdate set: {} -> {} + keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], false) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + + // test validator change its power and become a gotValidator (pushing out an existing) + // tendermintUpdate set: {} -> {c0, c4} + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10) + validators[2], _ = validators[2].AddTokensFromDel(tokens) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[2])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[2])) + updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) + assert.NilError(t, err) + validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdateZero(), updates[1]) + assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) +} + +func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) { + f, _, _ := bootstrapValidatorTest(t, 1000, 20) + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + params.MaxValidators = uint32(3) + + assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + + powers := []int64{100, 100} + var validators [2]types.Validator + + // initialize some validators into the state + for i, power := range powers { + valPubKey := PKs[i+1] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + + validators[i] = testutil.NewValidator(t, valAddr, valPubKey) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) + } + + // verify initial CometBFT updates are correct + updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, len(validators)) + + val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) + assert.NilError(t, err) + val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) + assert.NilError(t, err) + validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) + validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) + + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + + // update initial validator set + for i, power := range powers { + + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[i])) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) + } + + // add a new validator that goes from zero power, to non-zero power, back to + // zero power + valPubKey := PKs[len(validators)+1] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + amt := math.NewInt(100) + + validator := testutil.NewValidator(t, valAddr, valPubKey) + validator, _ = validator.AddTokensFromDel(amt) + + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) + + validator, _ = validator.RemoveDelShares(math.LegacyNewDecFromInt(amt)) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validator)) + + // add a new validator that increases in power + valPubKey = PKs[len(validators)+2] + valAddr = sdk.ValAddress(valPubKey.Address().Bytes()) + + validator = testutil.NewValidator(t, valAddr, valPubKey) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 500) + validator, _ = validator.AddTokensFromDel(tokens) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validator)) + + // verify initial CometBFT updates are correct + updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, len(validators)+1) + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) + assert.NilError(t, err) + validator, _ = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) + validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) + assert.DeepEqual(t, validator.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[2]) +} + +func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) { + f, _, _ := bootstrapValidatorTest(t, 1000, 20) + params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + assert.NilError(t, err) + params.MaxValidators = uint32(2) + + assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + + powers := []int64{100, 200, 300} + var validators [3]types.Validator + + // initialize some validators into the state + for i, power := range powers { + moniker := fmt.Sprintf("%d", i) + valPubKey := PKs[i+1] + valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) + + validators[i] = newMonikerValidator(t, valAddr, valPubKey, moniker) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + validators[i], _ = validators[i].AddTokensFromDel(tokens) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) + } + + // verify initial CometBFT updates are correct + updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) + assert.NilError(t, err) + val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) + assert.NilError(t, err) + validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) + validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) + assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) + + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + + // delegate to validator with lowest power but not enough to bond + f.sdkCtx = f.sdkCtx.WithBlockHeight(1) + + val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) + assert.NilError(t, err) + validators[0], err = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) + assert.NilError(t, err) + + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) + validators[0], _ = validators[0].AddTokensFromDel(tokens) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) + + // verify initial CometBFT updates are correct + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + + // create a series of events that will bond and unbond the validator with + // lowest power in a single block context (height) + f.sdkCtx = f.sdkCtx.WithBlockHeight(2) + + validators[1], err = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) + assert.NilError(t, err) + + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) + validators[0], _ = validators[0].RemoveDelShares(validators[0].DelegatorShares) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[1])) + tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 250) + validators[1], _ = validators[1].AddTokensFromDel(tokens) + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[1])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[1])) + + // verify initial CometBFT updates are correct + updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + + applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) +} + +func applyValidatorSetUpdates(t *testing.T, ctx sdk.Context, k *keeper.Keeper, expectedUpdatesLen int) []module.ValidatorUpdate { + t.Helper() + updates, err := k.ApplyAndReturnValidatorSetUpdates(ctx) + assert.NilError(t, err) + if expectedUpdatesLen >= 0 { + assert.Equal(t, expectedUpdatesLen, len(updates), "%v", updates) + } + return updates +} diff --git a/tests/integration/v2/staking/vote_extensions_test.go b/tests/integration/v2/staking/vote_extensions_test.go new file mode 100644 index 000000000000..362dfbdea48f --- /dev/null +++ b/tests/integration/v2/staking/vote_extensions_test.go @@ -0,0 +1,153 @@ +package staking + +import ( + "bytes" + "sort" + "testing" + + abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" + cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" + protoio "github.com/cosmos/gogoproto/io" + "github.com/cosmos/gogoproto/proto" + gogotypes "github.com/cosmos/gogoproto/types" + "gotest.tools/v3/assert" + + "cosmossdk.io/core/comet" + "cosmossdk.io/core/header" + "cosmossdk.io/math" + "cosmossdk.io/x/staking/testutil" + stakingtypes "cosmossdk.io/x/staking/types" + + "github.com/cosmos/cosmos-sdk/baseapp" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" + sdk "github.com/cosmos/cosmos-sdk/types" +) + +const chainID = "chain-id-123" + +// TestValidateVoteExtensions is a unit test function that tests the validation of vote extensions. +// It sets up the necessary fixtures and validators, generates vote extensions for each validator, +// and validates the vote extensions using the baseapp.ValidateVoteExtensions function. +func TestValidateVoteExtensions(t *testing.T) { + t.Parallel() + f := initFixture(t) + + // enable vote extensions + cp := simtestutil.DefaultConsensusParams + cp.Feature = &cmtproto.FeatureParams{VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 1}} + f.sdkCtx = f.sdkCtx.WithConsensusParams(*cp).WithHeaderInfo(header.Info{Height: 2, ChainID: chainID}) + + // setup the validators + numVals := 1 + privKeys := []cryptotypes.PrivKey{} + for i := 0; i < numVals; i++ { + privKeys = append(privKeys, ed25519.GenPrivKey()) + } + + vals := []stakingtypes.Validator{} + for _, v := range privKeys { + valAddr := sdk.ValAddress(v.PubKey().Address()) + acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, sdk.AccAddress(v.PubKey().Address())) + f.accountKeeper.SetAccount(f.sdkCtx, acc) + simtestutil.AddTestAddrsFromPubKeys(f.bankKeeper, f.stakingKeeper, f.sdkCtx, []cryptotypes.PubKey{v.PubKey()}, math.NewInt(100000000000)) + vals = append(vals, testutil.NewValidator(t, valAddr, v.PubKey())) + } + + votes := []abci.ExtendedVoteInfo{} + + for i, v := range vals { + v.Tokens = math.NewInt(1000000) + v.Status = stakingtypes.Bonded + assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, v)) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, v)) + assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, v)) + _, err := f.stakingKeeper.Delegate(f.sdkCtx, sdk.AccAddress(privKeys[i].PubKey().Address()), v.Tokens, stakingtypes.Unbonded, v, true) + assert.NilError(t, err) + + // each val produces a vote + voteExt := []byte("something" + v.OperatorAddress) + cve := cmtproto.CanonicalVoteExtension{ + Extension: voteExt, + Height: f.sdkCtx.HeaderInfo().Height - 1, // the vote extension was signed in the previous height + Round: 0, + ChainId: chainID, + } + + extSignBytes, err := mashalVoteExt(&cve) + assert.NilError(t, err) + + sig, err := privKeys[i].Sign(extSignBytes) + assert.NilError(t, err) + + valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(v.GetOperator()) + assert.NilError(t, err) + ve := abci.ExtendedVoteInfo{ + Validator: abci.Validator{ + Address: valbz, + Power: 1000, + }, + VoteExtension: voteExt, + ExtensionSignature: sig, + BlockIdFlag: cmtproto.BlockIDFlagCommit, + } + votes = append(votes, ve) + } + + eci, ci := extendedCommitToLastCommit(abci.ExtendedCommitInfo{Round: 0, Votes: votes}) + f.sdkCtx = f.sdkCtx.WithCometInfo(ci) + + err := baseapp.ValidateVoteExtensions(f.sdkCtx, f.stakingKeeper, eci) + assert.NilError(t, err) +} + +func mashalVoteExt(msg proto.Message) ([]byte, error) { + var buf bytes.Buffer + if err := protoio.NewDelimitedWriter(&buf).WriteMsg(msg); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +func extendedCommitToLastCommit(ec abci.ExtendedCommitInfo) (abci.ExtendedCommitInfo, comet.Info) { + // sort the extended commit info + sort.Sort(extendedVoteInfos(ec.Votes)) + + // convert the extended commit info to last commit info + lastCommit := comet.CommitInfo{ + Round: ec.Round, + Votes: make([]comet.VoteInfo, len(ec.Votes)), + } + + for i, vote := range ec.Votes { + lastCommit.Votes[i] = comet.VoteInfo{ + Validator: comet.Validator{ + Address: vote.Validator.Address, + Power: vote.Validator.Power, + }, + } + } + + return ec, comet.Info{ + LastCommit: lastCommit, + } +} + +type extendedVoteInfos []abci.ExtendedVoteInfo + +func (v extendedVoteInfos) Len() int { + return len(v) +} + +func (v extendedVoteInfos) Less(i, j int) bool { + if v[i].Validator.Power == v[j].Validator.Power { + return bytes.Compare(v[i].Validator.Address, v[j].Validator.Address) == -1 + } + return v[i].Validator.Power > v[j].Validator.Power +} + +func (v extendedVoteInfos) Swap(i, j int) { + v[i], v[j] = v[j], v[i] +} From 504039cc9a19caf291d9f9ebd71cb71422c2c2f9 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Tue, 10 Dec 2024 13:23:40 +0530 Subject: [PATCH 02/13] WIP: tests --- tests/integration/v2/app.go | 8 +- tests/integration/v2/staking/common_test.go | 210 +++---- .../integration/v2/staking/delegation_test.go | 7 +- tests/integration/v2/staking/genesis_test.go | 47 +- .../integration/v2/staking/grpc_query_test.go | 51 +- tests/integration/v2/staking/module_test.go | 20 + .../integration/v2/staking/msg_server_test.go | 30 +- tests/integration/v2/staking/slash_test.go | 453 +++++++-------- .../integration/v2/staking/unbonding_test.go | 152 ++--- .../v2/staking/validator_bench_test.go | 36 +- .../integration/v2/staking/validator_test.go | 549 +++++++++--------- .../v2/staking/vote_extensions_test.go | 34 +- x/staking/keeper/cons_pubkey.go | 2 +- x/staking/keeper/test_common.go | 9 +- 14 files changed, 778 insertions(+), 830 deletions(-) create mode 100644 tests/integration/v2/staking/module_test.go diff --git a/tests/integration/v2/app.go b/tests/integration/v2/app.go index 8eba29665cf3..9da3d2c79732 100644 --- a/tests/integration/v2/app.go +++ b/tests/integration/v2/app.go @@ -101,7 +101,7 @@ type StartupConfig struct { HeaderService header.Service } -func DefaultStartUpConfig(t *testing.T) StartupConfig { +func DefaultStartUpConfig(t testing.TB) StartupConfig { t.Helper() priv := secp256k1.GenPrivKey() @@ -345,10 +345,10 @@ func (a *App) Deliver( } // StateLatestContext creates returns a new context from context.Background() with the latest state. -func (a *App) StateLatestContext(t *testing.T) context.Context { - t.Helper() +func (a *App) StateLatestContext(tb testing.TB) context.Context { + tb.Helper() _, state, err := a.Store.StateLatest() - require.NoError(t, err) + require.NoError(tb, err) writeableState := branch.DefaultNewWriterMap(state) iCtx := &integrationContext{state: writeableState} return context.WithValue(context.Background(), contextKey, iCtx) diff --git a/tests/integration/v2/staking/common_test.go b/tests/integration/v2/staking/common_test.go index 4832f98074d6..2bd4621d82da 100644 --- a/tests/integration/v2/staking/common_test.go +++ b/tests/integration/v2/staking/common_test.go @@ -5,40 +5,38 @@ import ( "math/big" "testing" - "go.uber.org/mock/gomock" "gotest.tools/v3/assert" - "cosmossdk.io/core/appmodule" + "cosmossdk.io/depinject" "cosmossdk.io/log" "cosmossdk.io/math" 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" - pooltypes "cosmossdk.io/x/protocolpool/types" - "cosmossdk.io/x/staking" + consensuskeeper "cosmossdk.io/x/consensus/keeper" + slashingkeeper "cosmossdk.io/x/slashing/keeper" stakingkeeper "cosmossdk.io/x/staking/keeper" "cosmossdk.io/x/staking/testutil" "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" + "github.com/cosmos/cosmos-sdk/testutil/configurator" 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" - authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" - authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + + _ "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/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 PKs = simtestutil.CreateTestPubKeys(500) @@ -46,13 +44,17 @@ var PKs = simtestutil.CreateTestPubKeys(500) type fixture struct { app *integration.App - sdkCtx sdk.Context - cdc codec.Codec - keys map[string]*storetypes.KVStoreKey + ctx context.Context + cdc codec.Codec + keys map[string]*storetypes.KVStoreKey + + queryClient stakingkeeper.Querier - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper + accountKeeper authkeeper.AccountKeeper + bankKeeper bankkeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + slashKeeper slashingkeeper.Keeper + consensusKeeper consensuskeeper.Keeper } func init() { @@ -67,7 +69,7 @@ func ValEq(t *testing.T, exp, got types.Validator) (*testing.T, bool, string, ty // generateAddresses generates numAddrs of normal AccAddrs and ValAddrs func generateAddresses(f *fixture, numAddrs int) ([]sdk.AccAddress, []sdk.ValAddress) { - addrDels := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, numAddrs, math.NewInt(10000)) + addrDels := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.ctx, numAddrs, math.NewInt(10000)) addrVals := simtestutil.ConvertAddrsToValAddrs(addrDels) return addrDels, addrVals @@ -79,7 +81,7 @@ func createValidators( powers []int64, ) ([]sdk.AccAddress, []sdk.ValAddress, []types.Validator) { t.Helper() - addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, 5, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 300)) + addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.ctx, 5, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 300)) valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) pks := simtestutil.CreateTestPubKeys(5) @@ -87,128 +89,68 @@ func createValidators( val2 := testutil.NewValidator(t, valAddrs[1], pks[1]) vals := []types.Validator{val1, val2} - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, val1)) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, val2)) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val1)) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val2)) - assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val1)) - assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val2)) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, val1)) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, val2)) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, val1)) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, val2)) + assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.ctx, val1)) + assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.ctx, val2)) for _, addr := range addrs { - acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) - f.accountKeeper.SetAccount(f.sdkCtx, acc) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, addr) + f.accountKeeper.SetAccount(f.ctx, acc) } - _, err := f.stakingKeeper.Delegate(f.sdkCtx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[0]), types.Unbonded, val1, true) + _, err := f.stakingKeeper.Delegate(f.ctx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.ctx, powers[0]), types.Unbonded, val1, true) assert.NilError(t, err) - _, err = f.stakingKeeper.Delegate(f.sdkCtx, addrs[1], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[1]), types.Unbonded, val2, true) + _, err = f.stakingKeeper.Delegate(f.ctx, addrs[1], f.stakingKeeper.TokensFromConsensusPower(f.ctx, powers[1]), types.Unbonded, val2, true) assert.NilError(t, err) - _, err = f.stakingKeeper.Delegate(f.sdkCtx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[2]), types.Unbonded, val2, true) + _, err = f.stakingKeeper.Delegate(f.ctx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.ctx, powers[2]), types.Unbonded, val2, true) assert.NilError(t, err) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, -1) return addrs, valAddrs, vals } func initFixture(tb testing.TB) *fixture { tb.Helper() - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, types.StoreKey, consensustypes.StoreKey, - ) - encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, staking.AppModule{}) - cdc := encodingCfg.Codec - - msgRouter := baseapp.NewMsgServiceRouter() - queryRouter := baseapp.NewGRPCQueryRouter() - - logger := log.NewTestLogger(tb) - authority := authtypes.NewModuleAddress("gov") - - maccPerms := map[string][]string{ - pooltypes.ModuleName: {}, - minttypes.ModuleName: {authtypes.Minter}, - types.ModuleName: {authtypes.Minter}, - types.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - types.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - } - // gomock initializations - ctrl := gomock.NewController(tb) - acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl) - var lastAccNum uint64 - acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) { - lastAccNum++ - return lastAccNum, 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, + 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(), } - bankKeeper := bankkeeper.NewBaseKeeper( - runtime.NewEnvironment(runtime.NewKVStoreService(keys[banktypes.StoreKey]), log.NewNopLogger()), - cdc, - accountKeeper, - blockedAddresses, - authority.String(), - ) - - consensusParamsKeeper := consensusparamkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensustypes.StoreKey]), log.NewNopLogger()), authtypes.NewModuleAddress("gov").String()) - - stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[types.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), accountKeeper, bankKeeper, consensusParamsKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr), runtime.NewContextAwareCometInfoService()) - - authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) - bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper) - consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) - - integrationApp := integration.NewIntegrationApp(logger, keys, cdc, - encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), - encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), - map[string]appmodule.AppModule{ - authtypes.ModuleName: authModule, - banktypes.ModuleName: bankModule, - types.ModuleName: stakingModule, - consensustypes.ModuleName: consensusModule, - }, - msgRouter, - queryRouter, - ) - - sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) - - // Register MsgServer and QueryServer - types.RegisterMsgServer(integrationApp.MsgServiceRouter(), stakingkeeper.NewMsgServerImpl(stakingKeeper)) - types.RegisterQueryServer(integrationApp.QueryHelper(), stakingkeeper.NewQuerier(stakingKeeper)) + + var err error + startupCfg := integration.DefaultStartUpConfig(tb) + + 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.slashKeeper, &res.consensusKeeper, &res.cdc) + assert.NilError(tb, err) + + res.ctx = res.app.StateLatestContext(tb) // set default staking params - assert.NilError(tb, stakingKeeper.Params.Set(sdkCtx, types.DefaultParams())) - accNum := uint64(0) - acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) { - currentNum := accNum - accNum++ - return currentNum, nil - }) - - f := fixture{ - app: integrationApp, - sdkCtx: sdkCtx, - cdc: cdc, - keys: keys, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - stakingKeeper: stakingKeeper, - } + assert.NilError(tb, res.stakingKeeper.Params.Set(res.ctx, types.DefaultParams())) + + res.queryClient = stakingkeeper.NewQuerier(res.stakingKeeper) - return &f + return &res } diff --git a/tests/integration/v2/staking/delegation_test.go b/tests/integration/v2/staking/delegation_test.go index c061680ac7ef..ea8e90ef4264 100644 --- a/tests/integration/v2/staking/delegation_test.go +++ b/tests/integration/v2/staking/delegation_test.go @@ -13,6 +13,7 @@ import ( "cosmossdk.io/x/staking/testutil" "cosmossdk.io/x/staking/types" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -20,7 +21,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx initTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, int64(1000)) assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)))) @@ -66,7 +67,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) { totalUnbonded := math.NewInt(0) for i := int64(0); i < int64(maxEntries); i++ { var err error - ctx = ctx.WithHeaderInfo(header.Info{Height: i}) + ctx = integration.SetHeaderInfo(ctx, header.Info{Height: i}) var amount math.Int completionTime, amount, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1)) assert.NilError(t, err) @@ -94,7 +95,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) { assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded)) // mature unbonding delegations - ctx = ctx.WithHeaderInfo(header.Info{Time: completionTime}) + ctx = integration.SetHeaderInfo(ctx, header.Info{Time: completionTime}) acc := f.accountKeeper.NewAccountWithAddress(ctx, addrDel) f.accountKeeper.SetAccount(ctx, acc) _, err = f.stakingKeeper.CompleteUnbonding(ctx, addrDel, addrVal) diff --git a/tests/integration/v2/staking/genesis_test.go b/tests/integration/v2/staking/genesis_test.go index 6cbb593e3c4a..977abe8abe61 100644 --- a/tests/integration/v2/staking/genesis_test.go +++ b/tests/integration/v2/staking/genesis_test.go @@ -30,7 +30,7 @@ func bootstrapGenesisTest(t *testing.T, numAddrs int) (*fixture, []sdk.AccAddres func TestInitGenesis(t *testing.T) { f, addrs := bootstrapGenesisTest(t, 10) - valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) + valTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 1) pk0, err := codectypes.NewAnyWithValue(PKs[0]) assert.NilError(t, err) @@ -43,15 +43,16 @@ func TestInitGenesis(t *testing.T) { DelegatorShares: math.LegacyNewDecFromInt(valTokens), Description: types.NewDescription("hoop", "", "", "", "", &types.Metadata{}), } - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, bondedVal)) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, bondedVal)) - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) - validators, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) + validators, err := f.stakingKeeper.GetAllValidators(f.ctx) assert.NilError(t, err) - assert.Assert(t, len(validators) == 1) + // check validators count including init validator + assert.Assert(t, len(validators) == 2) var delegations []types.Delegation pk1, err := codectypes.NewAnyWithValue(PKs[1]) @@ -85,7 +86,7 @@ func TestInitGenesis(t *testing.T) { i2 := len(validators) assert.NilError(t, banktestutil.FundModuleAccount( - f.sdkCtx, + f.ctx, f.bankKeeper, types.BondedPoolName, sdk.NewCoins( @@ -94,25 +95,25 @@ func TestInitGenesis(t *testing.T) { ), ) - genesisDelegations, err := f.stakingKeeper.GetAllDelegations(f.sdkCtx) + genesisDelegations, err := f.stakingKeeper.GetAllDelegations(f.ctx) assert.NilError(t, err) delegations = append(delegations, genesisDelegations...) genesisState := types.NewGenesisState(params, validators, delegations) - vals, err := (f.stakingKeeper.InitGenesis(f.sdkCtx, genesisState)) + vals, err := (f.stakingKeeper.InitGenesis(f.ctx, genesisState)) assert.NilError(t, err) - actualGenesis, err := (f.stakingKeeper.ExportGenesis(f.sdkCtx)) + actualGenesis, err := (f.stakingKeeper.ExportGenesis(f.ctx)) assert.NilError(t, err) assert.DeepEqual(t, genesisState.Params, actualGenesis.Params) assert.DeepEqual(t, genesisState.Delegations, actualGenesis.Delegations) - allvals, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) + allvals, err := f.stakingKeeper.GetAllValidators(f.ctx) assert.NilError(t, err) assert.DeepEqual(t, allvals, actualGenesis.Validators) // Ensure validators have addresses. - vals2, err := staking.WriteValidators(f.sdkCtx, (f.stakingKeeper)) + vals2, err := staking.WriteValidators(f.ctx, (f.stakingKeeper)) assert.NilError(t, err) for _, val := range vals2 { @@ -120,17 +121,17 @@ func TestInitGenesis(t *testing.T) { } // now make sure the validators are bonded and intra-tx counters are correct - resVal, found := (f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[1]))) + resVal, found := (f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addrs[1]))) assert.Assert(t, found) assert.Equal(t, types.Bonded, resVal.Status) - resVal, found = (f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[2]))) + resVal, found = (f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addrs[2]))) assert.Assert(t, found) assert.Equal(t, types.Bonded, resVal.Status) validatorUpdates := make([]appmodule.ValidatorUpdate, len(vals)) for i, val := range validators { - validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)) + validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)) } assert.DeepEqual(t, validatorUpdates, vals) } @@ -160,7 +161,7 @@ func TestInitGenesis_PoolsBalanceMismatch(t *testing.T) { // setting validator status to bonded so the balance counts towards bonded pool validator.Status = types.Bonded - _, err = f.stakingKeeper.InitGenesis(f.sdkCtx, &types.GenesisState{ + _, err = f.stakingKeeper.InitGenesis(f.ctx, &types.GenesisState{ Params: params, Validators: []types.Validator{validator}, }) @@ -169,7 +170,7 @@ func TestInitGenesis_PoolsBalanceMismatch(t *testing.T) { // setting validator status to unbonded so the balance counts towards not bonded pool validator.Status = types.Unbonded - _, err = f.stakingKeeper.InitGenesis(f.sdkCtx, &types.GenesisState{ + _, err = f.stakingKeeper.InitGenesis(f.ctx, &types.GenesisState{ Params: params, Validators: []types.Validator{validator}, }) @@ -182,10 +183,10 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { assert.Assert(t, size > 100) f, addrs := bootstrapGenesisTest(t, 200) - genesisValidators, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) + genesisValidators, err := f.stakingKeeper.GetAllValidators(f.ctx) assert.NilError(t, err) - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) delegations := []types.Delegation{} validators := make([]types.Validator, size) @@ -200,9 +201,9 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { assert.NilError(t, err) validators[i].Status = types.Bonded - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 1) if i < 100 { - tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 2) + tokens = f.stakingKeeper.TokensFromConsensusPower(f.ctx, 2) } validators[i].Tokens = tokens @@ -218,19 +219,19 @@ func TestInitGenesisLargeValidatorSet(t *testing.T) { // mint coins in the bonded pool representing the validators coins assert.NilError(t, banktestutil.FundModuleAccount( - f.sdkCtx, + f.ctx, f.bankKeeper, types.BondedPoolName, sdk.NewCoins(sdk.NewCoin(params.BondDenom, bondedPoolAmt)), ), ) - vals, err := f.stakingKeeper.InitGenesis(f.sdkCtx, genesisState) + vals, err := f.stakingKeeper.InitGenesis(f.ctx, genesisState) assert.NilError(t, err) validatorUpdates := make([]module.ValidatorUpdate, 100) for i, val := range validators[:100] { - validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)) + validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)) } // remove genesis validator vals = vals[:100] diff --git a/tests/integration/v2/staking/grpc_query_test.go b/tests/integration/v2/staking/grpc_query_test.go index dd3badb81feb..03170808742b 100644 --- a/tests/integration/v2/staking/grpc_query_test.go +++ b/tests/integration/v2/staking/grpc_query_test.go @@ -34,8 +34,7 @@ func TestGRPCQueryValidators(t *testing.T) { _, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient var req *types.QueryValidatorsRequest testCases := []struct { @@ -116,11 +115,10 @@ func TestGRPCQueryDelegatorValidators(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx addrs, _ := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient params, err := f.stakingKeeper.Params.Get(ctx) assert.NilError(t, err) @@ -188,8 +186,7 @@ func TestGRPCQueryDelegatorValidator(t *testing.T) { addrs, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient addr := addrs[1] addrVal, addrVal1 := vals[0].OperatorAddress, vals[1].OperatorAddress @@ -273,11 +270,10 @@ func TestGRPCQueryDelegation(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx addrs, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient addrAcc, addrAcc1 := addrs[0], addrs[1] addrVal := vals[0].OperatorAddress @@ -342,11 +338,10 @@ func TestGRPCQueryDelegatorDelegations(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx addrs, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient addrAcc := addrs[0] addrVal1 := vals[0].OperatorAddress @@ -420,11 +415,10 @@ func TestGRPCQueryValidatorDelegations(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx addrs, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient addrAcc := addrs[0] addrVal1 := vals[1].OperatorAddress @@ -502,11 +496,10 @@ func TestGRPCQueryUnbondingDelegation(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx addrs, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient addrAcc2 := addrs[1] addrVal2 := vals[1].OperatorAddress @@ -605,11 +598,10 @@ func TestGRPCQueryDelegatorUnbondingDelegations(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx addrs, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient addrAcc, addrAcc1 := addrs[0], addrs[1] addrVal, addrVal2 := vals[0].OperatorAddress, vals[1].OperatorAddress @@ -692,10 +684,9 @@ func TestGRPCQueryPoolParameters(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient bondDenom := sdk.DefaultBondDenom @@ -719,11 +710,10 @@ func TestGRPCQueryRedelegations(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx addrs, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient addrAcc, addrAcc1 := addrs[0], addrs[1] valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) @@ -841,11 +831,10 @@ func TestGRPCQueryValidatorUnbondingDelegations(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx addrs, vals := createValidatorAccs(t, f) - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) + queryClient := f.queryClient addrAcc1, _ := addrs[0], addrs[1] val1 := vals[0] diff --git a/tests/integration/v2/staking/module_test.go b/tests/integration/v2/staking/module_test.go new file mode 100644 index 000000000000..cfbcf58700dd --- /dev/null +++ b/tests/integration/v2/staking/module_test.go @@ -0,0 +1,20 @@ +package staking + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "cosmossdk.io/x/staking/types" + + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func TestItCreatesModuleAccountOnInitBlock(t *testing.T) { + f := initFixture(t) + acc := f.accountKeeper.GetAccount(f.ctx, authtypes.NewModuleAddress(types.BondedPoolName)) + require.NotNil(t, acc) + + acc = f.accountKeeper.GetAccount(f.ctx, authtypes.NewModuleAddress(types.NotBondedPoolName)) + require.NotNil(t, acc) +} diff --git a/tests/integration/v2/staking/msg_server_test.go b/tests/integration/v2/staking/msg_server_test.go index 18546771f776..ccc4c9055382 100644 --- a/tests/integration/v2/staking/msg_server_test.go +++ b/tests/integration/v2/staking/msg_server_test.go @@ -1,6 +1,7 @@ package staking import ( + "context" "testing" "time" @@ -15,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/codec/address" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -23,7 +25,7 @@ func TestCancelUnbondingDelegation(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx msgServer := keeper.NewMsgServerImpl(f.stakingKeeper) bondDenom, err := f.stakingKeeper.BondDenom(ctx) assert.NilError(t, err) @@ -56,7 +58,7 @@ func TestCancelUnbondingDelegation(t *testing.T) { unbondingAmount := sdk.NewInt64Coin(bondDenom, 5) ubd := types.NewUnbondingDelegation( delegatorAddr, validatorAddr, 10, - ctx.HeaderInfo().Time.Add(time.Minute*10), + integration.HeaderInfoFromContext(ctx).Time.Add(time.Minute*10), unbondingAmount.Amount, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos"), @@ -181,7 +183,7 @@ func TestRotateConsPubKey(t *testing.T) { t.Parallel() f := initFixture(t) - ctx := f.sdkCtx + ctx := f.ctx stakingKeeper := f.stakingKeeper bankKeeper := f.bankKeeper accountKeeper := f.accountKeeper @@ -213,7 +215,8 @@ func TestRotateConsPubKey(t *testing.T) { } // call endblocker to update the validator state - _, err = stakingKeeper.EndBlocker(ctx.WithBlockHeight(ctx.BlockHeader().Height + 1)) + ctx = integration.SetHeaderInfo(ctx, header.Info{Height: int64(f.app.LastBlockHeight()) + 1}) + _, err = stakingKeeper.EndBlocker(ctx) assert.NilError(t, err) params, err = stakingKeeper.Params.Get(ctx) @@ -225,7 +228,7 @@ func TestRotateConsPubKey(t *testing.T) { testCases := []struct { name string - malleate func() sdk.Context + malleate func() context.Context pass bool validator string newPubKey cryptotypes.PubKey @@ -235,7 +238,7 @@ func TestRotateConsPubKey(t *testing.T) { }{ { name: "successful consensus pubkey rotation", - malleate: func() sdk.Context { + malleate: func() context.Context { return ctx }, validator: validators[0].GetOperator(), @@ -246,7 +249,7 @@ func TestRotateConsPubKey(t *testing.T) { }, { name: "non existing validator check", - malleate: func() sdk.Context { + malleate: func() context.Context { return ctx }, validator: sdk.ValAddress("non_existing_val").String(), @@ -256,7 +259,7 @@ func TestRotateConsPubKey(t *testing.T) { }, { name: "pubkey already associated with another validator", - malleate: func() sdk.Context { + malleate: func() context.Context { return ctx }, validator: validators[0].GetOperator(), @@ -266,7 +269,7 @@ func TestRotateConsPubKey(t *testing.T) { }, { name: "consensus pubkey rotation limit check", - malleate: func() sdk.Context { + malleate: func() context.Context { params, err := stakingKeeper.Params.Get(ctx) assert.NilError(t, err) @@ -291,7 +294,7 @@ func TestRotateConsPubKey(t *testing.T) { }, { name: "limit reached, but should rotate after the unbonding period", - malleate: func() sdk.Context { + malleate: func() context.Context { params, err := stakingKeeper.Params.Get(ctx) assert.NilError(t, err) @@ -307,7 +310,8 @@ func TestRotateConsPubKey(t *testing.T) { assert.NilError(t, err) _, err = msgServer.RotateConsPubKey(ctx, msg) assert.NilError(t, err) - ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) + newHeight := integration.HeaderInfoFromContext(ctx).Height + 1 + ctx = integration.SetHeaderInfo(ctx, header.Info{Height: newHeight}) // this shouldn't remove the existing keys from waiting queue since unbonding time isn't reached _, err = stakingKeeper.EndBlocker(ctx) @@ -322,9 +326,9 @@ func TestRotateConsPubKey(t *testing.T) { _, err = msgServer.RotateConsPubKey(ctx, msg) assert.Error(t, err, "exceeding maximum consensus pubkey rotations within unbonding period") - ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) + newHeight = integration.HeaderInfoFromContext(ctx).Height + 1 + newCtx := integration.SetHeaderInfo(ctx, header.Info{Height: newHeight + 1}) - newCtx := ctx.WithHeaderInfo(header.Info{Height: ctx.BlockHeight() + 1, Time: ctx.HeaderInfo().Time.Add(params.UnbondingTime)}).WithBlockHeight(ctx.BlockHeight() + 1) // this should remove keys from waiting queue since unbonding time is reached _, err = stakingKeeper.EndBlocker(newCtx) assert.NilError(t, err) diff --git a/tests/integration/v2/staking/slash_test.go b/tests/integration/v2/staking/slash_test.go index 88f533ea2619..11d63937e69d 100644 --- a/tests/integration/v2/staking/slash_test.go +++ b/tests/integration/v2/staking/slash_test.go @@ -10,26 +10,20 @@ import ( "cosmossdk.io/collections" "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" "cosmossdk.io/math" _ "cosmossdk.io/x/accounts" - bankkeeper "cosmossdk.io/x/bank/keeper" banktestutil "cosmossdk.io/x/bank/testutil" _ "cosmossdk.io/x/consensus" _ "cosmossdk.io/x/distribution" - distributionkeeper "cosmossdk.io/x/distribution/keeper" _ "cosmossdk.io/x/protocolpool" _ "cosmossdk.io/x/slashing" - slashingkeeper "cosmossdk.io/x/slashing/keeper" "cosmossdk.io/x/staking/keeper" "cosmossdk.io/x/staking/testutil" "cosmossdk.io/x/staking/types" "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - 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" ) @@ -42,29 +36,29 @@ func bootstrapSlashTest(t *testing.T, power int64) (*fixture, []sdk.AccAddress, addrDels, addrVals := generateAddresses(f, 100) - amt := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + amt := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) require.NoError(t, err) totalSupply := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(int64(len(addrDels))))) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), totalSupply)) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), totalSupply)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) numVals := int64(3) bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(numVals))) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) // set bonded pool balance - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), bondedCoins)) + f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), bondedCoins)) for i := int64(0); i < numVals; i++ { validator := testutil.NewValidator(t, addrVals[i], PKs[i]) validator, _ = validator.AddTokensFromDel(amt) - validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator, true) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, validator)) + validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validator, true) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, validator)) } return f, addrDels, addrVals @@ -81,29 +75,29 @@ func TestSlashUnbondingDelegation(t *testing.T) { ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 0, time.Unix(5, 0), math.NewInt(10), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.ctx, ubd)) // unbonding started prior to the infraction height, stakw didn't contribute - slashAmount, err := f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 1, fraction) + slashAmount, err := f.stakingKeeper.SlashUnbondingDelegation(f.ctx, ubd, 1, fraction) assert.NilError(t, err) assert.Assert(t, slashAmount.Equal(math.NewInt(0))) // after the expiration time, no longer eligible for slashing - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(10, 0)}) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) - slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Time: time.Unix(10, 0)}) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.ctx, ubd)) + slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.ctx, ubd, 0, fraction) assert.NilError(t, err) assert.Assert(t, slashAmount.Equal(math.NewInt(0))) // test valid slash, before expiration timestamp and to which stake contributed - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - oldUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, notBondedPool.GetAddress()) - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(0, 0)}) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) - slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) + oldUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.ctx, notBondedPool.GetAddress()) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Time: time.Unix(0, 0)}) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.ctx, ubd)) + slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.ctx, ubd, 0, fraction) assert.NilError(t, err) assert.Assert(t, slashAmount.Equal(math.NewInt(5))) - ubd, found := f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + ubd, found := f.stakingKeeper.GetUnbondingDelegation(f.ctx, addrDels[0], addrVals[0]) assert.Assert(t, found) assert.Assert(t, len(ubd.Entries) == 1) @@ -112,9 +106,9 @@ func TestSlashUnbondingDelegation(t *testing.T) { // balance decreased assert.DeepEqual(t, math.NewInt(5), ubd.Entries[0].Balance) - newUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, notBondedPool.GetAddress()) + newUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.ctx, notBondedPool.GetAddress()) diffTokens := oldUnbondedPoolBalances.Sub(newUnbondedPoolBalances...) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) assert.Assert(t, diffTokens.AmountOf(bondDenom).Equal(math.NewInt(5))) } @@ -124,72 +118,72 @@ func TestSlashRedelegation(t *testing.T) { f, addrDels, addrVals := bootstrapSlashTest(t, 10) fraction := math.LegacyNewDecWithPrec(5, 1) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) // add bonded tokens to pool for (re)delegations startCoins := sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 15)) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - _ = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + _ = f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), startCoins)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), startCoins)) + f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) // set a redelegation with an expiration timestamp beyond which the // redelegation shouldn't be slashed rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, time.Unix(5, 0), math.NewInt(10), math.LegacyNewDec(10), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.ctx, rd)) // set the associated delegation del := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDec(10)) - assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, del)) + assert.NilError(t, f.stakingKeeper.SetDelegation(f.ctx, del)) // started redelegating prior to the current height, stake didn't contribute to infraction - validator, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + validator, found := f.stakingKeeper.GetValidator(f.ctx, addrVals[1]) assert.Assert(t, found) - slashAmount, err := f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 1, fraction) + slashAmount, err := f.stakingKeeper.SlashRedelegation(f.ctx, validator, rd, 1, fraction) assert.NilError(t, err) assert.Assert(t, slashAmount.Equal(math.NewInt(0))) // after the expiration time, no longer eligible for slashing - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(10, 0)}) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Time: time.Unix(10, 0)}) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.ctx, rd)) + validator, found = f.stakingKeeper.GetValidator(f.ctx, addrVals[1]) assert.Assert(t, found) - slashAmount, err = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction) + slashAmount, err = f.stakingKeeper.SlashRedelegation(f.ctx, validator, rd, 0, fraction) assert.NilError(t, err) assert.Assert(t, slashAmount.Equal(math.NewInt(0))) - balances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + balances := f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) // test valid slash, before expiration timestamp and to which stake contributed - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(0, 0)}) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Time: time.Unix(0, 0)}) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.ctx, rd)) + validator, found = f.stakingKeeper.GetValidator(f.ctx, addrVals[1]) assert.Assert(t, found) - slashAmount, err = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction) + slashAmount, err = f.stakingKeeper.SlashRedelegation(f.ctx, validator, rd, 0, fraction) assert.NilError(t, err) assert.Assert(t, slashAmount.Equal(math.NewInt(5))) - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + rd, found = f.stakingKeeper.Redelegations.Get(f.ctx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) assert.Assert(t, found) assert.Assert(t, len(rd.Entries) == 1) // end block - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) // initialbalance unchanged assert.DeepEqual(t, math.NewInt(10), rd.Entries[0].InitialBalance) // shares decreased - del, found = f.stakingKeeper.Delegations.Get(f.sdkCtx, collections.Join(addrDels[0], addrVals[1])) + del, found = f.stakingKeeper.Delegations.Get(f.ctx, collections.Join(addrDels[0], addrVals[1])) assert.Assert(t, found) assert.Equal(t, int64(5), del.Shares.RoundInt64()) // pool bonded tokens should decrease burnedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, slashAmount)) - assert.DeepEqual(t, balances.Sub(burnedCoins...), f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())) + assert.DeepEqual(t, balances.Sub(burnedCoins...), f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress())) } // test slash at a negative height @@ -199,36 +193,36 @@ func TestSlashAtNegativeHeight(t *testing.T) { consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := math.LegacyNewDecWithPrec(5, 1) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) - _, err := f.stakingKeeper.Slash(f.sdkCtx, consAddr, -2, 10, fraction) + _, err := f.stakingKeeper.Slash(f.ctx, consAddr, -2, 10, fraction) assert.NilError(t, err) // read updated state - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) // end block - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) assert.NilError(t, err) - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + validator, found = f.stakingKeeper.GetValidator(f.ctx, valbz) assert.Assert(t, found) // power decreased - assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.ctx))) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) // pool bonded shares decreased - newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 5).String(), diffTokens.String()) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 5).String(), diffTokens.String()) } // tests Slash at the current height @@ -237,36 +231,36 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) { consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := math.LegacyNewDecWithPrec(5, 1) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, int64(f.app.LastBlockHeight())+1, 10, fraction) assert.NilError(t, err) // read updated state - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) // end block - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) assert.NilError(t, err) - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + validator, found = f.stakingKeeper.GetValidator(f.ctx, valbz) assert.Assert(t, found) // power decreased - assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.ctx))) // pool bonded shares decreased - newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 5).String(), diffTokens.String()) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 5).String(), diffTokens.String()) } // TestSlashWithUnbondingDelegation tests the slashing of a validator with an unbonding delegation. @@ -279,57 +273,57 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := math.LegacyNewDecWithPrec(5, 1) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) // set an unbonding delegation with expiration timestamp beyond which the // unbonding delegation shouldn't be slashed - ubdTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 4) + ubdTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 4) ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, time.Unix(0, 0), ubdTokens, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.ctx, ubd)) // slash validator for the first time - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Height: 12}) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 12}) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, 10, 10, fraction) assert.NilError(t, err) // end block - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) // read updating unbonding delegation - ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.ctx, addrDels[0], addrVals[0]) assert.Assert(t, found) assert.Assert(t, len(ubd.Entries) == 1) // balance decreased - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 2), ubd.Entries[0].Balance) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 2), ubd.Entries[0].Balance) // bonded tokens burned - newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 3), diffTokens) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 3), diffTokens) // read updated validator - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) // power decreased by 3 - 6 stake originally bonded at the time of infraction // was still bonded at the time of discovery and was slashed by half, 4 stake // bonded at the time of discovery hadn't been bonded at the time of infraction // and wasn't slashed - assert.Equal(t, int64(7), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + assert.Equal(t, int64(7), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.ctx))) // slash validator again - f.sdkCtx = f.sdkCtx.WithBlockHeight(13) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 13}) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, 9, 10, fraction) assert.NilError(t, err) - ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.ctx, addrDels[0], addrVals[0]) assert.Assert(t, found) assert.Assert(t, len(ubd.Entries) == 1) @@ -337,26 +331,26 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) // bonded tokens burned again - newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6), diffTokens) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 6), diffTokens) // read updated validator - validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) // power decreased by 3 again - assert.Equal(t, int64(4), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + assert.Equal(t, int64(4), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.ctx))) // slash validator again // all originally bonded stake has been slashed, so this will have no effect // on the unbonding delegation, but it will slash stake bonded since the infraction // this may not be the desirable behavior, ref https://github.com/cosmos/cosmos-sdk/issues/1440 - f.sdkCtx = f.sdkCtx.WithBlockHeight(13) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 13}) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, 9, 10, fraction) assert.NilError(t, err) - ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.ctx, addrDels[0], addrVals[0]) assert.Assert(t, found) assert.Assert(t, len(ubd.Entries) == 1) @@ -364,26 +358,26 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) // bonded tokens burned again - newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 9), diffTokens) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 9), diffTokens) // read updated validator - validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) // power decreased by 3 again - assert.Equal(t, int64(1), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + assert.Equal(t, int64(1), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.ctx))) // slash validator again // all originally bonded stake has been slashed, so this will have no effect // on the unbonding delegation, but it will slash stake bonded since the infraction // this may not be the desirable behavior, ref https://github.com/cosmos/cosmos-sdk/issues/1440 - f.sdkCtx = f.sdkCtx.WithBlockHeight(13) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 13}) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, 9, 10, fraction) assert.NilError(t, err) - ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) + ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.ctx, addrDels[0], addrVals[0]) assert.Assert(t, found) assert.Assert(t, len(ubd.Entries) == 1) @@ -391,17 +385,17 @@ func TestSlashWithUnbondingDelegation(t *testing.T) { assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) // just 1 bonded token burned again since that's all the validator now has - newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) + newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.ctx, bondedPool.GetAddress()) diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10), diffTokens) + assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 10), diffTokens) // apply TM updates - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, -1) // read updated validator // power decreased by 1 again, validator is out of stake // validator should be in unbonding period - validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Equal(t, validator.GetStatus(), sdk.Unbonding) } @@ -410,156 +404,156 @@ func TestSlashWithRedelegation(t *testing.T) { f, addrDels, addrVals := bootstrapSlashTest(t, 10) consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := math.LegacyNewDecWithPrec(5, 1) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) // set a redelegation - rdTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6) + rdTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 6) rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdTokens, math.LegacyNewDecFromInt(rdTokens), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.ctx, rd)) // set the associated delegation del := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDecFromInt(rdTokens)) - assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, del)) + assert.NilError(t, f.stakingKeeper.SetDelegation(f.ctx, del)) // update bonded tokens - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) rdCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdTokens.MulRaw(2))) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), rdCoins)) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), rdCoins)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) - oldBonded := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - oldNotBonded := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + oldBonded := f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount + oldNotBonded := f.bankKeeper.GetBalance(f.ctx, notBondedPool.GetAddress(), bondDenom).Amount // slash validator - f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 12}) + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, 10, 10, fraction) assert.NilError(t, err) - burnAmount := math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(fraction).TruncateInt() + burnAmount := math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.ctx, 10)).Mul(fraction).TruncateInt() - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool = f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.ctx) // burn bonded tokens from only from delegations - bondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + bondedPoolBalance := f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) - notBondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + notBondedPoolBalance := f.bankKeeper.GetBalance(f.ctx, notBondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + oldBonded = f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount // read updating redelegation - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + rd, found = f.stakingKeeper.Redelegations.Get(f.ctx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) assert.Assert(t, found) assert.Assert(t, len(rd.Entries) == 1) // read updated validator - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) // power decreased by 2 - 4 stake originally bonded at the time of infraction // was still bonded at the time of discovery and was slashed by half, 4 stake // bonded at the time of discovery hadn't been bonded at the time of infraction // and wasn't slashed - assert.Equal(t, int64(8), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + assert.Equal(t, int64(8), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.ctx))) // slash the validator again - _, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + _, found = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, 10, 10, math.LegacyOneDec()) assert.NilError(t, err) - burnAmount = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 7) + burnAmount = f.stakingKeeper.TokensFromConsensusPower(f.ctx, 7) // read updated pool - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool = f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.ctx) // seven bonded tokens burned - bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + bondedPoolBalance = f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + bondedPoolBalance = f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) - notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + notBondedPoolBalance = f.bankKeeper.GetBalance(f.ctx, notBondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + oldBonded = f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount // read updating redelegation - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + rd, found = f.stakingKeeper.Redelegations.Get(f.ctx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) assert.Assert(t, found) assert.Assert(t, len(rd.Entries) == 1) // read updated validator - validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) // power decreased by 4 - assert.Equal(t, int64(4), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + assert.Equal(t, int64(4), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.ctx))) // slash the validator again, by 100% - f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) - _, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 12}) + _, found = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, 10, 10, math.LegacyOneDec()) assert.NilError(t, err) - burnAmount = math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(math.LegacyOneDec()).TruncateInt() + burnAmount = math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.ctx, 10)).Mul(math.LegacyOneDec()).TruncateInt() burnAmount = burnAmount.Sub(math.LegacyOneDec().MulInt(rdTokens).TruncateInt()) // read updated pool - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool = f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.ctx) - bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + bondedPoolBalance = f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) - notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + notBondedPoolBalance = f.bankKeeper.GetBalance(f.ctx, notBondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + oldBonded = f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount // read updating redelegation - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + rd, found = f.stakingKeeper.Redelegations.Get(f.ctx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) assert.Assert(t, found) assert.Assert(t, len(rd.Entries) == 1) // apply TM updates - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, -1) // read updated validator // validator decreased to zero power, should be in unbonding period - validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Equal(t, validator.GetStatus(), sdk.Unbonding) // slash the validator again, by 100% // no stake remains to be slashed - f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 12}) // validator still in unbonding period - validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Equal(t, validator.GetStatus(), sdk.Unbonding) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, 10, 10, math.LegacyOneDec()) assert.NilError(t, err) // read updated pool - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool = f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.ctx) - bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + bondedPoolBalance = f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldBonded, bondedPoolBalance)) - notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + notBondedPoolBalance = f.bankKeeper.GetBalance(f.ctx, notBondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) // read updating redelegation - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + rd, found = f.stakingKeeper.Redelegations.Get(f.ctx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) assert.Assert(t, found) assert.Assert(t, len(rd.Entries) == 1) // read updated validator // power still zero, still in unbonding period - validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) + validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Equal(t, validator.GetStatus(), sdk.Unbonding) } @@ -567,85 +561,85 @@ func TestSlashWithRedelegation(t *testing.T) { func TestSlashBoth(t *testing.T) { f, addrDels, addrVals := bootstrapSlashTest(t, 10) fraction := math.LegacyNewDecWithPrec(5, 1) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) // set a redelegation with expiration timestamp beyond which the // redelegation shouldn't be slashed - rdATokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6) + rdATokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 6) rdA := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdATokens, math.LegacyNewDecFromInt(rdATokens), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rdA)) + assert.NilError(t, f.stakingKeeper.SetRedelegation(f.ctx, rdA)) // set the associated delegation delA := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDecFromInt(rdATokens)) - assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, delA)) + assert.NilError(t, f.stakingKeeper.SetDelegation(f.ctx, delA)) // set an unbonding delegation with expiration timestamp (beyond which the // unbonding delegation shouldn't be slashed) - ubdATokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 4) + ubdATokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 4) ubdA := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, time.Unix(0, 0), ubdATokens, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubdA)) + assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.ctx, ubdA)) bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdATokens.MulRaw(2))) notBondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, ubdATokens)) // update bonded tokens - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), bondedCoins)) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), notBondedCoins)) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), bondedCoins)) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), notBondedCoins)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) - oldBonded := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - oldNotBonded := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + oldBonded := f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount + oldNotBonded := f.bankKeeper.GetBalance(f.ctx, notBondedPool.GetAddress(), bondDenom).Amount // slash validator - f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, sdk.GetConsAddress(PKs[0])) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 12}) + _, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, sdk.GetConsAddress(PKs[0])) assert.Assert(t, found) consAddr0 := sdk.ConsAddress(PKs[0].Address()) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr0, 10, 10, fraction) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr0, 10, 10, fraction) assert.NilError(t, err) burnedNotBondedAmount := fraction.MulInt(ubdATokens).TruncateInt() - burnedBondAmount := math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(fraction).TruncateInt() + burnedBondAmount := math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.ctx, 10)).Mul(fraction).TruncateInt() burnedBondAmount = burnedBondAmount.Sub(burnedNotBondedAmount) // read updated pool - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool = f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.ctx) - bondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount + bondedPoolBalance := f.bankKeeper.GetBalance(f.ctx, bondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldBonded.Sub(burnedBondAmount), bondedPoolBalance)) - notBondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount + notBondedPoolBalance := f.bankKeeper.GetBalance(f.ctx, notBondedPool.GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, oldNotBonded.Sub(burnedNotBondedAmount), notBondedPoolBalance)) // read updating redelegation - rdA, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) + rdA, found = f.stakingKeeper.Redelegations.Get(f.ctx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) assert.Assert(t, found) assert.Assert(t, len(rdA.Entries) == 1) // read updated validator - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, sdk.GetConsAddress(PKs[0])) + validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, sdk.GetConsAddress(PKs[0])) assert.Assert(t, found) // power not decreased, all stake was bonded since - assert.Equal(t, int64(10), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) + assert.Equal(t, int64(10), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.ctx))) } func TestSlashAmount(t *testing.T) { f, _, _ := bootstrapSlashTest(t, 10) consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := math.LegacyNewDecWithPrec(5, 1) - burnedCoins, err := f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction) + burnedCoins, err := f.stakingKeeper.Slash(f.ctx, consAddr, int64(f.app.LastBlockHeight())+1, 10, fraction) assert.NilError(t, err) assert.Assert(t, burnedCoins.GT(math.ZeroInt())) // test the case where the validator was not found, which should return no coins _, addrVals := generateAddresses(f, 100) - noBurned, err := f.stakingKeeper.Slash(f.sdkCtx, sdk.ConsAddress(addrVals[0]), f.sdkCtx.BlockHeight(), 10, fraction) + noBurned, err := f.stakingKeeper.Slash(f.ctx, sdk.ConsAddress(addrVals[0]), int64(f.app.LastBlockHeight())+1, 10, fraction) assert.NilError(t, err) assert.Assert(t, math.NewInt(0).Equal(noBurned)) } @@ -653,28 +647,11 @@ func TestSlashAmount(t *testing.T) { // TestFixAvoidFullSlashPenalty fixes the following issue: https://github.com/cosmos/cosmos-sdk/issues/20641 func TestFixAvoidFullSlashPenalty(t *testing.T) { // setup - var authKeeper authkeeper.AccountKeeperI - var stakingKeeper *keeper.Keeper - var bankKeeper bankkeeper.Keeper - var slashKeeper slashingkeeper.Keeper - var distrKeeper distributionkeeper.Keeper - app, err := simtestutil.Setup(depinject.Configs( - depinject.Supply(log.NewNopLogger()), - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.ConsensusModule(), - configurator.StakingModule(), - configurator.SlashingModule(), - configurator.ProtocolPoolModule(), - configurator.DistributionModule(), - ), - ), &authKeeper, &stakingKeeper, &bankKeeper, &slashKeeper, &distrKeeper) - require.NoError(t, err) - ctx := app.BaseApp.NewContext(false) - stakingMsgServer := keeper.NewMsgServerImpl(stakingKeeper) - bondDenom, err := stakingKeeper.BondDenom(ctx) + f := initFixture(t) + ctx := f.ctx + + stakingMsgServer := keeper.NewMsgServerImpl(f.stakingKeeper) + bondDenom, err := f.stakingKeeper.BondDenom(ctx) require.NoError(t, err) // create 2 evil validators, controlled by attacker evilValPubKey := secp256k1.GenPrivKey().PubKey() @@ -684,18 +661,18 @@ func TestFixAvoidFullSlashPenalty(t *testing.T) { // normal users who stakes on evilValAddr1 testAcc1 := sdk.AccAddress("addr2_______________") testAcc2 := sdk.AccAddress("addr3_______________") - createAccount(t, ctx, authKeeper, badtestAcc) - createAccount(t, ctx, authKeeper, testAcc1) - createAccount(t, ctx, authKeeper, testAcc2) + createAccount(t, ctx, f.accountKeeper, badtestAcc) + createAccount(t, ctx, f.accountKeeper, testAcc1) + createAccount(t, ctx, f.accountKeeper, testAcc2) // fund all accounts - testCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, stakingKeeper.TokensFromConsensusPower(ctx, 1))) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, badtestAcc, testCoins)) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, testAcc1, testCoins)) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, testAcc2, testCoins)) + testCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(ctx, 1))) + require.NoError(t, banktestutil.FundAccount(ctx, f.bankKeeper, badtestAcc, testCoins)) + require.NoError(t, banktestutil.FundAccount(ctx, f.bankKeeper, testAcc1, testCoins)) + require.NoError(t, banktestutil.FundAccount(ctx, f.bankKeeper, testAcc2, testCoins)) // create evilValAddr1 for normal staking operations evilValAddr1 := sdk.ValAddress(evilValPubKey.Address()) - createAccount(t, ctx, authKeeper, evilValAddr1.Bytes()) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, sdk.AccAddress(evilValAddr1), testCoins)) + createAccount(t, ctx, f.accountKeeper, evilValAddr1.Bytes()) + require.NoError(t, banktestutil.FundAccount(ctx, f.bankKeeper, sdk.AccAddress(evilValAddr1), testCoins)) createValMsg1, _ := types.NewMsgCreateValidator( evilValAddr1.String(), evilValPubKey, testCoins[0], types.Description{Details: "test"}, types.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) _, err = stakingMsgServer.CreateValidator(ctx, createValMsg1) @@ -704,15 +681,16 @@ func TestFixAvoidFullSlashPenalty(t *testing.T) { smallCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, math.NewInt(1))) // create evilValAddr2 to circumvent slashing evilValAddr2 := sdk.ValAddress(evilValPubKey2.Address()) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, sdk.AccAddress(evilValAddr2), smallCoins)) + require.NoError(t, banktestutil.FundAccount(ctx, f.bankKeeper, sdk.AccAddress(evilValAddr2), smallCoins)) createValMsg3, _ := types.NewMsgCreateValidator( evilValAddr2.String(), evilValPubKey2, smallCoins[0], types.Description{Details: "test"}, types.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) - createAccount(t, ctx, authKeeper, evilValAddr2.Bytes()) + createAccount(t, ctx, f.accountKeeper, evilValAddr2.Bytes()) _, err = stakingMsgServer.CreateValidator(ctx, createValMsg3) 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) // all accs delegate to evilValAddr1 delMsg := types.NewMsgDelegate(badtestAcc.String(), evilValAddr1.String(), testCoins[0]) @@ -725,7 +703,8 @@ func TestFixAvoidFullSlashPenalty(t *testing.T) { _, err = stakingMsgServer.Delegate(ctx, delMsg) 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) // 1. badtestAcc redelegates from evilValAddr1 to evilValAddr2 redelMsg := types.NewMsgBeginRedelegate(badtestAcc.String(), evilValAddr1.String(), evilValAddr2.String(), smallCoins[0]) @@ -736,27 +715,21 @@ func TestFixAvoidFullSlashPenalty(t *testing.T) { _, err = stakingMsgServer.Undelegate(ctx, undelMsg) require.NoError(t, err) // assert evilValAddr2 is jailed - evilVal2, err := stakingKeeper.GetValidator(ctx, evilValAddr2) + evilVal2, err := f.stakingKeeper.GetValidator(ctx, evilValAddr2) require.NoError(t, err) require.True(t, evilVal2.Jailed) // 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) - // assert invariants - _, stop := keeper.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) // evilValAddr1 is bad! // lets slash evilValAddr1 with a 100% penalty - evilVal, err := stakingKeeper.GetValidator(ctx, evilValAddr1) + evilVal, err := f.stakingKeeper.GetValidator(ctx, evilValAddr1) require.NoError(t, err) evilValConsAddr, err := evilVal.GetConsAddr() require.NoError(t, err) - evilPower := stakingKeeper.TokensToConsensusPower(ctx, evilVal.Tokens) - err = slashKeeper.Slash(ctx, evilValConsAddr, math.LegacyMustNewDecFromStr("1.0"), evilPower, 3) + evilPower := f.stakingKeeper.TokensToConsensusPower(ctx, evilVal.Tokens) + err = f.slashKeeper.Slash(ctx, evilValConsAddr, math.LegacyMustNewDecFromStr("1.0"), evilPower, 3) require.NoError(t, err) } diff --git a/tests/integration/v2/staking/unbonding_test.go b/tests/integration/v2/staking/unbonding_test.go index 6ad0f385c0e1..7f94da34e0fc 100644 --- a/tests/integration/v2/staking/unbonding_test.go +++ b/tests/integration/v2/staking/unbonding_test.go @@ -1,6 +1,7 @@ package staking import ( + "context" "testing" "time" @@ -14,6 +15,7 @@ import ( "cosmossdk.io/x/staking/testutil" "cosmossdk.io/x/staking/types" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -30,7 +32,7 @@ func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uin // save id *ubdeID = id // call back to stop unbonding - err := f.stakingKeeper.PutUnbondingOnHold(f.sdkCtx, id) + err := f.stakingKeeper.PutUnbondingOnHold(f.ctx, id) assert.NilError(t, err) return nil @@ -47,38 +49,38 @@ func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uin mockStackingHooks.EXPECT().AfterConsensusPubKeyUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() f.stakingKeeper.SetHooks(types.NewMultiStakingHooks(mockStackingHooks)) - addrDels = simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, 2, math.NewInt(10000)) + addrDels = simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.ctx, 2, math.NewInt(10000)) addrVals = simtestutil.ConvertAddrsToValAddrs(addrDels) - valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10) - startTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 20) + valTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 10) + startTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 20) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) // Create a validator validator1 := testutil.NewValidator(t, addrVals[0], PKs[0]) validator1, issuedShares1 := validator1.AddTokensFromDel(valTokens) assert.DeepEqual(t, valTokens, issuedShares1.RoundInt()) - validator1 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator1, true) + validator1 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validator1, true) assert.Assert(math.IntEq(t, valTokens, validator1.BondedTokens())) assert.Assert(t, validator1.IsBonded()) // Create a delegator delegation := types.NewDelegation(addrDels[0].String(), addrVals[0].String(), issuedShares1) - assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, delegation)) + assert.NilError(t, f.stakingKeeper.SetDelegation(f.ctx, delegation)) // Create a validator to redelegate to validator2 := testutil.NewValidator(t, addrVals[1], PKs[1]) validator2, issuedShares2 := validator2.AddTokensFromDel(valTokens) assert.DeepEqual(t, valTokens, issuedShares2.RoundInt()) - validator2 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator2, true) + validator2 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validator2, true) assert.Equal(t, types.Bonded, validator2.Status) assert.Assert(t, validator2.IsBonded()) @@ -89,7 +91,7 @@ func doUnbondingDelegation( t *testing.T, stakingKeeper *stakingkeeper.Keeper, bankKeeper types.BankKeeper, - ctx sdk.Context, + ctx context.Context, bondDenom string, addrDels []sdk.AccAddress, addrVals []sdk.ValAddress, @@ -128,7 +130,7 @@ func doUnbondingDelegation( func doRedelegation( t *testing.T, stakingKeeper *stakingkeeper.Keeper, - ctx sdk.Context, + ctx context.Context, addrDels []sdk.AccAddress, addrVals []sdk.ValAddress, hookCalled *bool, @@ -153,7 +155,7 @@ func doRedelegation( func doValidatorUnbonding( t *testing.T, stakingKeeper *stakingkeeper.Keeper, - ctx sdk.Context, + ctx context.Context, addrVal sdk.ValAddress, hookCalled *bool, ) (validator types.Validator) { @@ -187,37 +189,39 @@ func TestValidatorUnbondingOnHold1(t *testing.T) { _, _, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) // Start unbonding first validator - validator := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[0], &hookCalled) + validator := doValidatorUnbonding(t, f.stakingKeeper, f.ctx, addrVals[0], &hookCalled) completionTime := validator.UnbondingTime completionHeight := validator.UnbondingHeight // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + err := f.stakingKeeper.UnbondingCanComplete(f.ctx, ubdeID) assert.NilError(t, err) // Try to unbond validator - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.ctx)) // Check that validator unbonding is not complete (is not mature yet) - validator, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + validator, found := f.stakingKeeper.GetValidator(f.ctx, addrVals[0]) assert.Assert(t, found) assert.Equal(t, types.Unbonding, validator.Status) - unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.ctx, completionTime, completionHeight) assert.NilError(t, err) assert.Equal(t, 1, len(unbondingVals)) assert.Equal(t, validator.OperatorAddress, unbondingVals[0]) // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime.Add(time.Duration(1))}) - f.sdkCtx = f.sdkCtx.WithBlockHeight(completionHeight + 1) - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{ + Time: completionTime.Add(time.Duration(1)), + Height: completionHeight + 1, + }) + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.ctx)) // Check that validator unbonding is complete - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + validator, found = f.stakingKeeper.GetValidator(f.ctx, addrVals[0]) assert.Assert(t, found) assert.Equal(t, types.Unbonded, validator.Status) - unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.ctx, completionTime, completionHeight) assert.NilError(t, err) assert.Equal(t, 0, len(unbondingVals)) } @@ -235,14 +239,14 @@ func TestValidatorUnbondingOnHold2(t *testing.T) { _, _, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) // Start unbonding first validator - validator1 := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[0], &hookCalled) + validator1 := doValidatorUnbonding(t, f.stakingKeeper, f.ctx, addrVals[0], &hookCalled) ubdeIDs = append(ubdeIDs, ubdeID) // Reset hookCalled flag hookCalled = false // Start unbonding second validator - validator2 := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[1], &hookCalled) + validator2 := doValidatorUnbonding(t, f.stakingKeeper, f.ctx, addrVals[1], &hookCalled) ubdeIDs = append(ubdeIDs, ubdeID) // Check that there are two unbonding operations @@ -255,54 +259,56 @@ func TestValidatorUnbondingOnHold2(t *testing.T) { completionHeight := validator1.UnbondingHeight // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime.Add(time.Duration(1))}) - f.sdkCtx = f.sdkCtx.WithBlockHeight(completionHeight + 1) - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{ + Time: completionTime.Add(time.Duration(1)), + Height: completionHeight + 1, + }) + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.ctx)) // Check that unbonding is not complete for both validators - validator1, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + validator1, found := f.stakingKeeper.GetValidator(f.ctx, addrVals[0]) assert.Assert(t, found) assert.Equal(t, types.Unbonding, validator1.Status) - validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + validator2, found = f.stakingKeeper.GetValidator(f.ctx, addrVals[1]) assert.Assert(t, found) assert.Equal(t, types.Unbonding, validator2.Status) - unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.ctx, completionTime, completionHeight) assert.NilError(t, err) assert.Equal(t, 2, len(unbondingVals)) assert.Equal(t, validator1.OperatorAddress, unbondingVals[0]) assert.Equal(t, validator2.OperatorAddress, unbondingVals[1]) // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeIDs[0]) + err = f.stakingKeeper.UnbondingCanComplete(f.ctx, ubdeIDs[0]) assert.NilError(t, err) // Try again to unbond validators - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.ctx)) // Check that unbonding is complete for validator1, but not for validator2 - validator1, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + validator1, found = f.stakingKeeper.GetValidator(f.ctx, addrVals[0]) assert.Assert(t, found) assert.Equal(t, types.Unbonded, validator1.Status) - validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + validator2, found = f.stakingKeeper.GetValidator(f.ctx, addrVals[1]) assert.Assert(t, found) assert.Equal(t, types.Unbonding, validator2.Status) - unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.ctx, completionTime, completionHeight) assert.NilError(t, err) assert.Equal(t, 1, len(unbondingVals)) assert.Equal(t, validator2.OperatorAddress, unbondingVals[0]) // Unbonding for validator2 can complete - err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeIDs[1]) + err = f.stakingKeeper.UnbondingCanComplete(f.ctx, ubdeIDs[1]) assert.NilError(t, err) // Try again to unbond validators - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) + assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.ctx)) // Check that unbonding is complete for validator2 - validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) + validator2, found = f.stakingKeeper.GetValidator(f.ctx, addrVals[1]) assert.Assert(t, found) assert.Equal(t, types.Unbonded, validator2.Status) - unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) + unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.ctx, completionTime, completionHeight) assert.NilError(t, err) assert.Equal(t, 0, len(unbondingVals)) } @@ -318,24 +324,24 @@ func TestRedelegationOnHold1(t *testing.T) { // _, app, ctx := createTestInput(t) _, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) - completionTime := doRedelegation(t, f.stakingKeeper, f.sdkCtx, addrDels, addrVals, &hookCalled) + completionTime := doRedelegation(t, f.stakingKeeper, f.ctx, addrDels, addrVals, &hookCalled) // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + err := f.stakingKeeper.UnbondingCanComplete(f.ctx, ubdeID) assert.NilError(t, err) // Redelegation is not complete - still exists - redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) + redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.ctx, addrVals[0]) assert.NilError(t, err) assert.Equal(t, 1, len(redelegations)) // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) - _, err = f.stakingKeeper.CompleteRedelegation(f.sdkCtx, addrDels[0], addrVals[0], addrVals[1]) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Time: completionTime}) + _, err = f.stakingKeeper.CompleteRedelegation(f.ctx, addrDels[0], addrVals[0], addrVals[1]) assert.NilError(t, err) // Redelegation is complete and record is gone - redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) + redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.ctx, addrVals[0]) assert.NilError(t, err) assert.Equal(t, 0, len(redelegations)) } @@ -351,24 +357,24 @@ func TestRedelegationOnHold2(t *testing.T) { // _, app, ctx := createTestInput(t) _, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) - completionTime := doRedelegation(t, f.stakingKeeper, f.sdkCtx, addrDels, addrVals, &hookCalled) + completionTime := doRedelegation(t, f.stakingKeeper, f.ctx, addrDels, addrVals, &hookCalled) // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) - _, err := f.stakingKeeper.CompleteRedelegation(f.sdkCtx, addrDels[0], addrVals[0], addrVals[1]) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Time: completionTime}) + _, err := f.stakingKeeper.CompleteRedelegation(f.ctx, addrDels[0], addrVals[0], addrVals[1]) assert.NilError(t, err) // Redelegation is not complete - still exists - redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) + redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.ctx, addrVals[0]) assert.NilError(t, err) assert.Equal(t, 1, len(redelegations)) // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + err = f.stakingKeeper.UnbondingCanComplete(f.ctx, ubdeID) assert.NilError(t, err) // Redelegation is complete and record is gone - redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) + redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.ctx, addrVals[0]) assert.NilError(t, err) assert.Equal(t, 0, len(redelegations)) } @@ -385,17 +391,17 @@ func TestUnbondingDelegationOnHold1(t *testing.T) { // _, app, ctx := createTestInput(t) bondDenom, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) for _, addr := range addrDels { - acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) - f.accountKeeper.SetAccount(f.sdkCtx, acc) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, addr) + f.accountKeeper.SetAccount(f.ctx, acc) } - completionTime, bondedAmt1, notBondedAmt1 := doUnbondingDelegation(t, f.stakingKeeper, f.bankKeeper, f.sdkCtx, bondDenom, addrDels, addrVals, &hookCalled) + completionTime, bondedAmt1, notBondedAmt1 := doUnbondingDelegation(t, f.stakingKeeper, f.bankKeeper, f.ctx, bondDenom, addrDels, addrVals, &hookCalled) // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + err := f.stakingKeeper.UnbondingCanComplete(f.ctx, ubdeID) assert.NilError(t, err) - bondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - notBondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + bondedAmt3 := f.bankKeeper.GetBalance(f.ctx, f.stakingKeeper.GetBondedPool(f.ctx).GetAddress(), bondDenom).Amount + notBondedAmt3 := f.bankKeeper.GetBalance(f.ctx, f.stakingKeeper.GetNotBondedPool(f.ctx).GetAddress(), bondDenom).Amount // Bonded and unbonded amounts are the same as before because the completionTime has not yet passed and so the // unbondingDelegation has not completed @@ -403,13 +409,13 @@ func TestUnbondingDelegationOnHold1(t *testing.T) { assert.Assert(math.IntEq(t, notBondedAmt1, notBondedAmt3)) // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) - _, err = f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0]) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Time: completionTime}) + _, err = f.stakingKeeper.CompleteUnbonding(f.ctx, addrDels[0], addrVals[0]) assert.NilError(t, err) // Check that the unbonding was finally completed - bondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - notBondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + bondedAmt5 := f.bankKeeper.GetBalance(f.ctx, f.stakingKeeper.GetBondedPool(f.ctx).GetAddress(), bondDenom).Amount + notBondedAmt5 := f.bankKeeper.GetBalance(f.ctx, f.stakingKeeper.GetNotBondedPool(f.ctx).GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt5)) // Not bonded amount back to what it was originally @@ -428,18 +434,18 @@ func TestUnbondingDelegationOnHold2(t *testing.T) { // _, app, ctx := createTestInput(t) bondDenom, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) for _, addr := range addrDels { - acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) - f.accountKeeper.SetAccount(f.sdkCtx, acc) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, addr) + f.accountKeeper.SetAccount(f.ctx, acc) } - completionTime, bondedAmt1, notBondedAmt1 := doUnbondingDelegation(t, f.stakingKeeper, f.bankKeeper, f.sdkCtx, bondDenom, addrDels, addrVals, &hookCalled) + completionTime, bondedAmt1, notBondedAmt1 := doUnbondingDelegation(t, f.stakingKeeper, f.bankKeeper, f.ctx, bondDenom, addrDels, addrVals, &hookCalled) // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) - _, err := f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0]) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Time: completionTime}) + _, err := f.stakingKeeper.CompleteUnbonding(f.ctx, addrDels[0], addrVals[0]) assert.NilError(t, err) - bondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - notBondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + bondedAmt3 := f.bankKeeper.GetBalance(f.ctx, f.stakingKeeper.GetBondedPool(f.ctx).GetAddress(), bondDenom).Amount + notBondedAmt3 := f.bankKeeper.GetBalance(f.ctx, f.stakingKeeper.GetNotBondedPool(f.ctx).GetAddress(), bondDenom).Amount // Bonded and unbonded amounts are the same as before because the completionTime has not yet passed and so the // unbondingDelegation has not completed @@ -447,12 +453,12 @@ func TestUnbondingDelegationOnHold2(t *testing.T) { assert.Assert(math.IntEq(t, notBondedAmt1, notBondedAmt3)) // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) + err = f.stakingKeeper.UnbondingCanComplete(f.ctx, ubdeID) assert.NilError(t, err) // Check that the unbonding was finally completed - bondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - notBondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount + bondedAmt5 := f.bankKeeper.GetBalance(f.ctx, f.stakingKeeper.GetBondedPool(f.ctx).GetAddress(), bondDenom).Amount + notBondedAmt5 := f.bankKeeper.GetBalance(f.ctx, f.stakingKeeper.GetNotBondedPool(f.ctx).GetAddress(), bondDenom).Amount assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt5)) // Not bonded amount back to what it was originally diff --git a/tests/integration/v2/staking/validator_bench_test.go b/tests/integration/v2/staking/validator_bench_test.go index c9b7de3867a8..3ee9f0e59c63 100644 --- a/tests/integration/v2/staking/validator_bench_test.go +++ b/tests/integration/v2/staking/validator_bench_test.go @@ -29,7 +29,7 @@ func BenchmarkGetValidator(b *testing.B) { f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) for _, validator := range vals { - if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { + if err := f.stakingKeeper.SetValidator(f.ctx, validator); err != nil { panic(err) } } @@ -37,7 +37,7 @@ func BenchmarkGetValidator(b *testing.B) { b.ResetTimer() for n := 0; n < b.N; n++ { for _, addr := range valAddrs { - _, _ = f.stakingKeeper.GetValidator(f.sdkCtx, addr) + _, _ = f.stakingKeeper.GetValidator(f.ctx, addr) } } } @@ -54,7 +54,7 @@ func BenchmarkGetValidatorDelegations(b *testing.B) { f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) for _, validator := range vals { - if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { + if err := f.stakingKeeper.SetValidator(f.ctx, validator); err != nil { panic(err) } } @@ -63,14 +63,14 @@ func BenchmarkGetValidatorDelegations(b *testing.B) { for _, val := range valAddrs { for i := 0; i < delegationsNum; i++ { delegator := sdk.AccAddress(fmt.Sprintf("address%d", i)) - err := banktestutil.FundAccount(f.sdkCtx, f.bankKeeper, delegator, + err := banktestutil.FundAccount(f.ctx, f.bankKeeper, delegator, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(int64(i))))) if err != nil { panic(err) } NewDel := types.NewDelegation(delegator.String(), val.String(), math.LegacyNewDec(int64(i))) - if err := f.stakingKeeper.SetDelegation(f.sdkCtx, NewDel); err != nil { + if err := f.stakingKeeper.SetDelegation(f.ctx, NewDel); err != nil { panic(err) } } @@ -95,7 +95,7 @@ func BenchmarkGetValidatorDelegationsLegacy(b *testing.B) { f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) for _, validator := range vals { - if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { + if err := f.stakingKeeper.SetValidator(f.ctx, validator); err != nil { panic(err) } } @@ -104,13 +104,13 @@ func BenchmarkGetValidatorDelegationsLegacy(b *testing.B) { for _, val := range valAddrs { for i := 0; i < delegationsNum; i++ { delegator := sdk.AccAddress(fmt.Sprintf("address%d", i)) - err := banktestutil.FundAccount(f.sdkCtx, f.bankKeeper, delegator, + err := banktestutil.FundAccount(f.ctx, f.bankKeeper, delegator, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(int64(i))))) if err != nil { panic(err) } NewDel := types.NewDelegation(delegator.String(), val.String(), math.LegacyNewDec(int64(i))) - if err := f.stakingKeeper.SetDelegation(f.sdkCtx, NewDel); err != nil { + if err := f.stakingKeeper.SetDelegation(f.ctx, NewDel); err != nil { panic(err) } } @@ -123,12 +123,14 @@ func BenchmarkGetValidatorDelegationsLegacy(b *testing.B) { } func updateValidatorDelegationsLegacy(f *fixture, existingValAddr, newValAddr sdk.ValAddress) { - storeKey := f.keys[types.StoreKey] cdc, k := f.cdc, f.stakingKeeper - store := f.sdkCtx.KVStore(storeKey) + store := k.KVStoreService.OpenKVStore(f.ctx) - iterator := storetypes.KVStorePrefixIterator(store, types.DelegationKey) + iterator, err := store.Iterator(types.DelegationKey, storetypes.PrefixEndBytes(types.DelegationKey)) + if err != nil { + panic(err) + } defer iterator.Close() for ; iterator.Valid(); iterator.Next() { @@ -139,11 +141,11 @@ func updateValidatorDelegationsLegacy(f *fixture, existingValAddr, newValAddr sd } if bytes.EqualFold(valAddr, existingValAddr) { - if err := k.RemoveDelegation(f.sdkCtx, delegation); err != nil { + if err := k.RemoveDelegation(f.ctx, delegation); err != nil { panic(err) } delegation.ValidatorAddress = newValAddr.String() - if err := k.SetDelegation(f.sdkCtx, delegation); err != nil { + if err := k.SetDelegation(f.ctx, delegation); err != nil { panic(err) } } @@ -154,22 +156,22 @@ func updateValidatorDelegations(f *fixture, existingValAddr, newValAddr sdk.ValA k := f.stakingKeeper rng := collections.NewPrefixedPairRange[sdk.ValAddress, sdk.AccAddress](existingValAddr) - err := k.DelegationsByValidator.Walk(f.sdkCtx, rng, func(key collections.Pair[sdk.ValAddress, sdk.AccAddress], _ []byte) (stop bool, err error) { + err := k.DelegationsByValidator.Walk(f.ctx, rng, func(key collections.Pair[sdk.ValAddress, sdk.AccAddress], _ []byte) (stop bool, err error) { valAddr, delAddr := key.K1(), key.K2() - delegation, err := k.Delegations.Get(f.sdkCtx, collections.Join(delAddr, valAddr)) + delegation, err := k.Delegations.Get(f.ctx, collections.Join(delAddr, valAddr)) if err != nil { return true, err } // remove old operator addr from delegation - if err := k.RemoveDelegation(f.sdkCtx, delegation); err != nil { + if err := k.RemoveDelegation(f.ctx, delegation); err != nil { return true, err } delegation.ValidatorAddress = newValAddr.String() // add with new operator addr - if err := k.SetDelegation(f.sdkCtx, delegation); err != nil { + if err := k.SetDelegation(f.ctx, delegation); err != nil { return true, err } diff --git a/tests/integration/v2/staking/validator_test.go b/tests/integration/v2/staking/validator_test.go index 53462a96f440..e39bce5a675a 100644 --- a/tests/integration/v2/staking/validator_test.go +++ b/tests/integration/v2/staking/validator_test.go @@ -1,11 +1,13 @@ package staking import ( + "context" "fmt" "testing" "gotest.tools/v3/assert" + "cosmossdk.io/core/header" "cosmossdk.io/math" banktestutil "cosmossdk.io/x/bank/testutil" "cosmossdk.io/x/staking/keeper" @@ -13,6 +15,7 @@ import ( "cosmossdk.io/x/staking/types" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/module" @@ -31,18 +34,18 @@ func bootstrapValidatorTest(tb testing.TB, power int64, numAddrs int) (*fixture, addrDels, addrVals := generateAddresses(f, numAddrs) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(tb, err) - amt := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + amt := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) totalSupply := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(int64(len(addrDels))))) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) // set bonded pool supply - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) - assert.NilError(tb, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), totalSupply)) + assert.NilError(tb, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), totalSupply)) return f, addrDels, addrVals } @@ -55,7 +58,7 @@ func initValidators(tb testing.TB, power int64, numAddrs int, powers []int64) (* vs := make([]types.Validator, len(powers)) for i, power := range powers { vs[i] = testutil.NewValidator(tb, sdk.ValAddress(addrs[i]), pks[i]) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) vs[i], _ = vs[i].AddTokensFromDel(tokens) } return f, addrs, valAddrs, vs @@ -68,33 +71,33 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { // create context, keeper, and pool for tests f, _, valAddrs := bootstrapValidatorTest(t, 1, 100) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) // create keeper parameters - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) params.MaxValidators = uint32(maxVals) - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + assert.NilError(t, f.stakingKeeper.Params.Set(f.ctx, params)) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) // create a random pool - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1234))))) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10000))))) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 1234))))) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 10000))))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) validators := make([]types.Validator, numVals) for i := 0; i < len(validators); i++ { moniker := fmt.Sprintf("val#%d", int64(i)) val := newMonikerValidator(t, valAddrs[i], PKs[i], moniker) - delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, int64((i+1)*10)) + delTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, int64((i+1)*10)) val, _ = val.AddTokensFromDel(delTokens) - val = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, val, true) + val = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, val, true) validators[i] = val } @@ -102,10 +105,10 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { // remove enough tokens to kick out the validator below the current cliff // validator and next in line cliff validator - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, nextCliffVal)) - shares := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 21) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, nextCliffVal)) + shares := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 21) nextCliffVal, _ = nextCliffVal.RemoveDelShares(math.LegacyNewDecFromInt(shares)) - _ = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, nextCliffVal, true) + _ = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, nextCliffVal, true) expectedValStatus := map[int]sdk.BondStatus{ 9: sdk.Bonded, 8: sdk.Bonded, 7: sdk.Bonded, 5: sdk.Bonded, 4: sdk.Bonded, @@ -117,7 +120,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { valAddr := validators[valIdx].OperatorAddress addr, err := sdk.ValAddressFromBech32(valAddr) assert.NilError(t, err) - val, _ := f.stakingKeeper.GetValidator(f.sdkCtx, addr) + val, _ := f.stakingKeeper.GetValidator(f.ctx, addr) assert.Equal( t, status, val.GetStatus(), @@ -132,29 +135,29 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { // add a validator validator := testutil.NewValidator(t, addrVals[0], PKs[0]) - valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) + valTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 100) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, valTokens)))) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, valTokens)))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) validator, _ = validator.AddTokensFromDel(valTokens) assert.Equal(t, types.Unbonded, validator.Status) assert.DeepEqual(t, valTokens, validator.Tokens) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, validator)) - validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator, true) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, validator)) + validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validator, true) assert.DeepEqual(t, valTokens, validator.Tokens) // slash the validator by 100% - _, err = f.stakingKeeper.Slash(f.sdkCtx, sdk.ConsAddress(PKs[0].Address()), 0, 100, math.LegacyOneDec()) + _, err = f.stakingKeeper.Slash(f.ctx, sdk.ConsAddress(PKs[0].Address()), 0, 100, math.LegacyOneDec()) assert.NilError(t, err) // apply TM updates - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, -1) // validator should be unbonding - validator, _ = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) + validator, _ = f.stakingKeeper.GetValidator(f.ctx, addrVals[0]) assert.Equal(t, validator.GetStatus(), sdk.Unbonding) } @@ -165,10 +168,10 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { // initialize some validators into the state amts := []math.Int{ math.NewIntFromUint64(0), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(100), - f.stakingKeeper.PowerReduction(f.sdkCtx), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(400), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(200), + f.stakingKeeper.PowerReduction(f.ctx).MulRaw(100), + f.stakingKeeper.PowerReduction(f.ctx), + f.stakingKeeper.PowerReduction(f.ctx).MulRaw(400), + f.stakingKeeper.PowerReduction(f.ctx).MulRaw(200), } n := len(amts) var validators [5]types.Validator @@ -177,17 +180,17 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { validators[i].Status = types.Bonded validators[i].Tokens = amt validators[i].DelegatorShares = math.LegacyNewDecFromInt(amt) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[i], true) } // first make sure everything made it in to the gotValidator group - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, n, len(resValidators)) - assert.DeepEqual(t, math.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[0].BondedTokens()) - assert.DeepEqual(t, math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[1].BondedTokens()) - assert.DeepEqual(t, math.NewInt(100).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[2].BondedTokens()) - assert.DeepEqual(t, math.NewInt(1).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[3].BondedTokens()) + assert.DeepEqual(t, math.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.ctx)), resValidators[0].BondedTokens()) + assert.DeepEqual(t, math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.ctx)), resValidators[1].BondedTokens()) + assert.DeepEqual(t, math.NewInt(100).Mul(f.stakingKeeper.PowerReduction(f.ctx)), resValidators[2].BondedTokens()) + assert.DeepEqual(t, math.NewInt(1).Mul(f.stakingKeeper.PowerReduction(f.ctx)), resValidators[3].BondedTokens()) assert.DeepEqual(t, math.NewInt(0), resValidators[4].BondedTokens()) assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators) assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators) @@ -196,51 +199,51 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { assert.Equal(t, validators[0].OperatorAddress, resValidators[4].OperatorAddress, "%v", resValidators) // test a basic increase in voting power - validators[3].Tokens = math.NewInt(500).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[3].Tokens = math.NewInt(500).Mul(f.stakingKeeper.PowerReduction(f.ctx)) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) assert.Assert(ValEq(t, validators[3], resValidators[0])) // test a decrease in voting power - validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.ctx)) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) assert.Assert(ValEq(t, validators[3], resValidators[0])) assert.Assert(ValEq(t, validators[4], resValidators[1])) // test equal voting power, different age - validators[3].Tokens = math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - f.sdkCtx = f.sdkCtx.WithBlockHeight(10) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[3].Tokens = math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.ctx)) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 10}) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) assert.Assert(ValEq(t, validators[3], resValidators[0])) assert.Assert(ValEq(t, validators[4], resValidators[1])) // no change in voting power - no change in sort - f.sdkCtx = f.sdkCtx.WithBlockHeight(20) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[4], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 20}) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[4], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) assert.Assert(ValEq(t, validators[3], resValidators[0])) assert.Assert(ValEq(t, validators[4], resValidators[1])) // change in voting power of both validators, both still in v-set, no age change - validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - validators[4].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.ctx)) + validators[4].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.ctx)) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) - f.sdkCtx = f.sdkCtx.WithBlockHeight(30) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[4], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 30}) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[4], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n, "%v", resValidators) assert.Assert(ValEq(t, validators[3], resValidators[0])) @@ -249,31 +252,31 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { func TestGetValidatorSortingMixed(t *testing.T) { f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) + bondDenom, err := f.stakingKeeper.BondDenom(f.ctx) assert.NilError(t, err) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 501))))) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 0))))) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 501))))) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 0))))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) + f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) // now 2 max resValidators - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) params.MaxValidators = 2 - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + assert.NilError(t, f.stakingKeeper.Params.Set(f.ctx, params)) // initialize some validators into the state amts := []math.Int{ math.NewIntFromUint64(0), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(100), - f.stakingKeeper.PowerReduction(f.sdkCtx), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(400), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(200), + f.stakingKeeper.PowerReduction(f.ctx).MulRaw(100), + f.stakingKeeper.PowerReduction(f.ctx), + f.stakingKeeper.PowerReduction(f.ctx).MulRaw(400), + f.stakingKeeper.PowerReduction(f.ctx).MulRaw(200), } var validators [5]types.Validator @@ -282,18 +285,18 @@ func TestGetValidatorSortingMixed(t *testing.T) { validators[i].DelegatorShares = math.LegacyNewDecFromInt(amt) validators[i].Status = types.Bonded validators[i].Tokens = amt - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[i], true) } - val0, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[0])) + val0, found := f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addrs[0])) assert.Assert(t, found) - val1, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[1])) + val1, found := f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addrs[1])) assert.Assert(t, found) - val2, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[2])) + val2, found := f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addrs[2])) assert.Assert(t, found) - val3, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[3])) + val3, found := f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addrs[3])) assert.Assert(t, found) - val4, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[4])) + val4, found := f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addrs[4])) assert.Assert(t, found) assert.Equal(t, types.Bonded, val0.Status) assert.Equal(t, types.Unbonding, val1.Status) @@ -302,12 +305,12 @@ func TestGetValidatorSortingMixed(t *testing.T) { assert.Equal(t, types.Bonded, val4.Status) // first make sure everything made it in to the gotValidator group - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) // The validators returned should match the max validators assert.Equal(t, 2, len(resValidators)) - assert.DeepEqual(t, math.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[0].BondedTokens()) - assert.DeepEqual(t, math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[1].BondedTokens()) + assert.DeepEqual(t, math.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.ctx)), resValidators[0].BondedTokens()) + assert.DeepEqual(t, math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.ctx)), resValidators[1].BondedTokens()) assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators) assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators) } @@ -317,11 +320,11 @@ func TestGetValidatorsEdgeCases(t *testing.T) { f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) // set max validators to 2 - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) nMax := uint32(2) params.MaxValidators = nMax - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + assert.NilError(t, f.stakingKeeper.Params.Set(f.ctx, params)) // initialize some validators into the state powers := []int64{0, 100, 400, 400} var validators [4]types.Validator @@ -329,38 +332,38 @@ func TestGetValidatorsEdgeCases(t *testing.T) { moniker := fmt.Sprintf("val#%d", int64(i)) validators[i] = newMonikerValidator(t, sdk.ValAddress(addrs[i]), PKs[i], moniker) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - validators[i] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) + validators[i] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[i], true) } // ensure that the first two bonded validators are the largest validators - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) assert.Assert(ValEq(t, validators[2], resValidators[0])) assert.Assert(ValEq(t, validators[3], resValidators[1])) // delegate 500 tokens to validator 0 - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) - delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 500) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[0])) + delTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 500) validators[0], _ = validators[0].AddTokensFromDel(delTokens) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) + notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) newTokens := sdk.NewCoins() - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), newTokens)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), newTokens)) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) // test that the two largest validators are // a) validator 0 with 500 tokens // b) validator 2 with 400 tokens (delegated before validator 3) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) assert.Assert(ValEq(t, validators[0], resValidators[0])) @@ -376,59 +379,59 @@ func TestGetValidatorsEdgeCases(t *testing.T) { // - validator 3 adds 200 tokens (equal to validator 2 now) and does not get its spot back // validator 3 enters bonded validator set - f.sdkCtx = f.sdkCtx.WithBlockHeight(40) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 40}) valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[3].GetOperator()) assert.NilError(t, err) - validators[3], err = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + validators[3], err = f.stakingKeeper.GetValidator(f.ctx, valbz) assert.NilError(t, err) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) - validators[3], _ = validators[3].AddTokensFromDel(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1)) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[3])) + validators[3], _ = validators[3].AddTokensFromDel(f.stakingKeeper.TokensFromConsensusPower(f.ctx, 1)) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - newTokens = sdk.NewCoins(sdk.NewCoin(params.BondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1))) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), newTokens)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.ctx) + newTokens = sdk.NewCoins(sdk.NewCoin(params.BondDenom, f.stakingKeeper.TokensFromConsensusPower(f.ctx, 1))) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), newTokens)) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) assert.Assert(ValEq(t, validators[0], resValidators[0])) assert.Assert(ValEq(t, validators[3], resValidators[1])) // validator 3 kicked out temporarily - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[3])) rmTokens := validators[3].TokensFromShares(math.LegacyNewDec(201)).TruncateInt() validators[3], _ = validators[3].RemoveDelShares(math.LegacyNewDec(201)) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) + bondedPool := f.stakingKeeper.GetBondedPool(f.ctx) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) + f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) assert.Assert(ValEq(t, validators[0], resValidators[0])) assert.Assert(ValEq(t, validators[2], resValidators[1])) // validator 3 does not get spot back - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[3])) validators[3], _ = validators[3].AddTokensFromDel(math.NewInt(200)) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, math.NewInt(200))))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) + notBondedPool = f.stakingKeeper.GetNotBondedPool(f.ctx) + assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, math.NewInt(200))))) + f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) assert.Assert(ValEq(t, validators[0], resValidators[0])) assert.Assert(ValEq(t, validators[2], resValidators[1])) - _, exists := f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + _, exists := f.stakingKeeper.GetValidator(f.ctx, valbz) assert.Assert(t, exists) } @@ -436,73 +439,73 @@ func TestValidatorBondHeight(t *testing.T) { f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) // now 2 max resValidators - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) params.MaxValidators = 2 - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + assert.NilError(t, f.stakingKeeper.Params.Set(f.ctx, params)) // initialize some validators into the state var validators [3]types.Validator validators[0] = testutil.NewValidator(t, sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0]) validators[1] = testutil.NewValidator(t, sdk.ValAddress(addrs[1]), PKs[1]) validators[2] = testutil.NewValidator(t, sdk.ValAddress(addrs[2]), PKs[2]) - tokens0 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 200) - tokens1 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) - tokens2 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) + tokens0 := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 200) + tokens1 := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 100) + tokens2 := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 100) validators[0], _ = validators[0].AddTokensFromDel(tokens0) validators[1], _ = validators[1].AddTokensFromDel(tokens1) validators[2], _ = validators[2].AddTokensFromDel(tokens2) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], true) //////////////////////////////////////// // If two validators both increase to the same voting power in the same block, // the one with the first transaction should become bonded - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], true) - validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], true) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], true) + validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[2], true) - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, uint32(len(resValidators)), params.MaxValidators) assert.Assert(ValEq(t, validators[0], resValidators[0])) assert.Assert(ValEq(t, validators[1], resValidators[1])) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[1])) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[2])) - delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 50) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[1])) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[2])) + delTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 50) validators[1], _ = validators[1].AddTokensFromDel(delTokens) validators[2], _ = validators[2].AddTokensFromDel(delTokens) - validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[2], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, params.MaxValidators, uint32(len(resValidators))) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], true) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], true) assert.Assert(ValEq(t, validators[0], resValidators[0])) assert.Assert(ValEq(t, validators[2], resValidators[1])) } func TestFullValidatorSetPowerChange(t *testing.T) { f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) max := 2 params.MaxValidators = uint32(2) - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + assert.NilError(t, f.stakingKeeper.Params.Set(f.ctx, params)) // initialize some validators into the state powers := []int64{0, 100, 400, 400, 200} var validators [5]types.Validator for i, power := range powers { validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[i], true) } for i := range powers { valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[i].GetOperator()) assert.NilError(t, err) - validators[i], err = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) + validators[i], err = f.stakingKeeper.GetValidator(f.ctx, valbz) assert.NilError(t, err) } assert.Equal(t, types.Unbonded, validators[0].Status) @@ -510,7 +513,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { assert.Equal(t, types.Bonded, validators[2].Status) assert.Equal(t, types.Bonded, validators[3].Status) assert.Equal(t, types.Unbonded, validators[4].Status) - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, max, len(resValidators)) assert.Assert(ValEq(t, validators[2], resValidators[0])) // in the order of txs @@ -518,10 +521,10 @@ func TestFullValidatorSetPowerChange(t *testing.T) { // test a swap in voting power - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 600) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 600) validators[0], _ = validators[0].AddTokensFromDel(tokens) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], true) + resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, max, len(resValidators)) assert.Assert(ValEq(t, validators[0], resValidators[0])) @@ -538,27 +541,27 @@ func TestApplyAndReturnValidatorSetUpdatesAllNone(t *testing.T) { valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) validators[i] = testutil.NewValidator(t, valAddr, valPubKey) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) } // test from nothing to something // tendermintUpdate set: {} -> {c1, c3} - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[1])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[1])) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[1])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[1])) - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) assert.NilError(t, err) val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) assert.NilError(t, err) - validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) - validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + validators[0], _ = f.stakingKeeper.GetValidator(f.ctx, val0bz) + validators[1], _ = f.stakingKeeper.GetValidator(f.ctx, val1bz) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[1]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) } func TestApplyAndReturnValidatorSetUpdatesIdentical(t *testing.T) { @@ -569,19 +572,19 @@ func TestApplyAndReturnValidatorSetUpdatesIdentical(t *testing.T) { for i, power := range powers { validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test identical, // tendermintUpdate set: {} -> {} - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) } func TestApplyAndReturnValidatorSetUpdatesSingleValueChange(t *testing.T) { @@ -592,22 +595,22 @@ func TestApplyAndReturnValidatorSetUpdatesSingleValueChange(t *testing.T) { for i, power := range powers { validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test single value change // tendermintUpdate set: {} -> {c1'} validators[0].Status = types.Bonded - validators[0].Tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 600) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) + validators[0].Tokens = f.stakingKeeper.TokensFromConsensusPower(f.ctx, 600) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) } func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) { @@ -615,108 +618,108 @@ func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) { // TODO: use it in other places f, _, _, validators := initValidators(t, 1000, 20, powers) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test multiple value change // tendermintUpdate set: {c1, c3} -> {c1', c3'} - delTokens1 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 190) - delTokens2 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 80) + delTokens1 := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 190) + delTokens2 := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 80) validators[0], _ = validators[0].AddTokensFromDel(delTokens1) validators[1], _ = validators[1].AddTokensFromDel(delTokens2) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) + updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[1]) } func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) { powers := []int64{10, 20, 5, 15, 25} f, _, _, validators := initValidators(t, 1000, 20, powers) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test validator added at the beginning // tendermintUpdate set: {} -> {c0} - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[2])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[2])) - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[2])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[2])) + updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) assert.NilError(t, err) - validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) - assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + validators[2], _ = f.stakingKeeper.GetValidator(f.ctx, val2bz) + assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) // test validator added at the beginning // tendermintUpdate set: {} -> {c0} - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[3])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[3])) - updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[3])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[3])) + updates = applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) val3bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[3].GetOperator()) assert.NilError(t, err) - validators[3], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val3bz) - assert.DeepEqual(t, validators[3].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + validators[3], _ = f.stakingKeeper.GetValidator(f.ctx, val3bz) + assert.DeepEqual(t, validators[3].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) // test validator added at the end // tendermintUpdate set: {} -> {c0} - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[4])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[4])) - updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[4])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[4])) + updates = applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) val4bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[4].GetOperator()) assert.NilError(t, err) - validators[4], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val4bz) - assert.DeepEqual(t, validators[4].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + validators[4], _ = f.stakingKeeper.GetValidator(f.ctx, val4bz) + assert.DeepEqual(t, validators[4].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) } func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) { f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) params := types.DefaultParams() params.MaxValidators = 2 - err := f.stakingKeeper.Params.Set(f.sdkCtx, params) + err := f.stakingKeeper.Params.Set(f.ctx, params) assert.NilError(t, err) powers := []int64{10, 20, 5} var validators [5]types.Validator for i, power := range powers { validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) + validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test validator added at the end but not inserted in the valset // tendermintUpdate set: {} -> {} - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[2], false) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) // test validator change its power and become a gotValidator (pushing out an existing) // tendermintUpdate set: {} -> {c0, c4} - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 10) validators[2], _ = validators[2].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[2])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[2])) - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[2])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[2])) + updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) assert.NilError(t, err) - validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) + validators[2], _ = f.stakingKeeper.GetValidator(f.ctx, val2bz) assert.DeepEqual(t, validators[0].ModuleValidatorUpdateZero(), updates[1]) - assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) } func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) { f, _, _ := bootstrapValidatorTest(t, 1000, 20) - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) params.MaxValidators = uint32(3) - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + assert.NilError(t, f.stakingKeeper.Params.Set(f.ctx, params)) powers := []int64{100, 100} var validators [2]types.Validator @@ -727,36 +730,36 @@ func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) { valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) validators[i] = testutil.NewValidator(t, valAddr, valPubKey) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[i])) } // verify initial CometBFT updates are correct - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, len(validators)) + updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, len(validators)) val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) assert.NilError(t, err) val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) assert.NilError(t, err) - validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) - validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) + validators[0], _ = f.stakingKeeper.GetValidator(f.ctx, val0bz) + validators[1], _ = f.stakingKeeper.GetValidator(f.ctx, val1bz) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[1]) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) // update initial validator set for i, power := range powers { - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[i])) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[i])) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[i])) } // add a new validator that goes from zero power, to non-zero power, back to @@ -768,41 +771,41 @@ func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) { validator := testutil.NewValidator(t, valAddr, valPubKey) validator, _ = validator.AddTokensFromDel(amt) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validator)) validator, _ = validator.RemoveDelShares(math.LegacyNewDecFromInt(amt)) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validator)) // add a new validator that increases in power valPubKey = PKs[len(validators)+2] valAddr = sdk.ValAddress(valPubKey.Address().Bytes()) validator = testutil.NewValidator(t, valAddr, valPubKey) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 500) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 500) validator, _ = validator.AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validator)) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validator)) // verify initial CometBFT updates are correct - updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, len(validators)+1) + updates = applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, len(validators)+1) valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) assert.NilError(t, err) - validator, _ = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) - validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) - validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.DeepEqual(t, validator.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[2]) + validator, _ = f.stakingKeeper.GetValidator(f.ctx, valbz) + validators[0], _ = f.stakingKeeper.GetValidator(f.ctx, val0bz) + validators[1], _ = f.stakingKeeper.GetValidator(f.ctx, val1bz) + assert.DeepEqual(t, validator.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[1]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[2]) } func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) { f, _, _ := bootstrapValidatorTest(t, 1000, 20) - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) + params, err := f.stakingKeeper.Params.Get(f.ctx) assert.NilError(t, err) params.MaxValidators = uint32(2) - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) + assert.NilError(t, f.stakingKeeper.Params.Set(f.ctx, params)) powers := []int64{100, 200, 300} var validators [3]types.Validator @@ -814,69 +817,69 @@ func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) { valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) validators[i] = newMonikerValidator(t, valAddr, valPubKey, moniker) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[i])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[i])) } // verify initial CometBFT updates are correct - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) + updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) assert.NilError(t, err) val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) assert.NilError(t, err) - validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) - validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) + validators[2], _ = f.stakingKeeper.GetValidator(f.ctx, val2bz) + validators[1], _ = f.stakingKeeper.GetValidator(f.ctx, val1bz) + assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[1]) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) // delegate to validator with lowest power but not enough to bond - f.sdkCtx = f.sdkCtx.WithBlockHeight(1) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 1}) val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) assert.NilError(t, err) - validators[0], err = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) + validators[0], err = f.stakingKeeper.GetValidator(f.ctx, val0bz) assert.NilError(t, err) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[0])) + tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 1) validators[0], _ = validators[0].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[0])) // verify initial CometBFT updates are correct - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) // create a series of events that will bond and unbond the validator with // lowest power in a single block context (height) - f.sdkCtx = f.sdkCtx.WithBlockHeight(2) + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 2}) - validators[1], err = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) + validators[1], err = f.stakingKeeper.GetValidator(f.ctx, val1bz) assert.NilError(t, err) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[0])) validators[0], _ = validators[0].RemoveDelShares(validators[0].DelegatorShares) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[0])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[0])) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[1])) - tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 250) + assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, validators[1])) + tokens = f.stakingKeeper.TokensFromConsensusPower(f.ctx, 250) validators[1], _ = validators[1].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[1])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[1])) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validators[1])) + assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validators[1])) // verify initial CometBFT updates are correct - updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) + updates = applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) + assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) + applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) } -func applyValidatorSetUpdates(t *testing.T, ctx sdk.Context, k *keeper.Keeper, expectedUpdatesLen int) []module.ValidatorUpdate { +func applyValidatorSetUpdates(t *testing.T, ctx context.Context, k *keeper.Keeper, expectedUpdatesLen int) []module.ValidatorUpdate { t.Helper() updates, err := k.ApplyAndReturnValidatorSetUpdates(ctx) assert.NilError(t, err) diff --git a/tests/integration/v2/staking/vote_extensions_test.go b/tests/integration/v2/staking/vote_extensions_test.go index 362dfbdea48f..d3d0c533b3aa 100644 --- a/tests/integration/v2/staking/vote_extensions_test.go +++ b/tests/integration/v2/staking/vote_extensions_test.go @@ -18,9 +18,9 @@ import ( "cosmossdk.io/x/staking/testutil" stakingtypes "cosmossdk.io/x/staking/types" - "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" ) @@ -37,7 +37,10 @@ func TestValidateVoteExtensions(t *testing.T) { // enable vote extensions cp := simtestutil.DefaultConsensusParams cp.Feature = &cmtproto.FeatureParams{VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 1}} - f.sdkCtx = f.sdkCtx.WithConsensusParams(*cp).WithHeaderInfo(header.Info{Height: 2, ChainID: chainID}) + + assert.NilError(t, f.consensusKeeper.ParamsStore.Set(f.ctx, *cp)) + + f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 2, ChainID: chainID}) // setup the validators numVals := 1 @@ -49,9 +52,9 @@ func TestValidateVoteExtensions(t *testing.T) { vals := []stakingtypes.Validator{} for _, v := range privKeys { valAddr := sdk.ValAddress(v.PubKey().Address()) - acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, sdk.AccAddress(v.PubKey().Address())) - f.accountKeeper.SetAccount(f.sdkCtx, acc) - simtestutil.AddTestAddrsFromPubKeys(f.bankKeeper, f.stakingKeeper, f.sdkCtx, []cryptotypes.PubKey{v.PubKey()}, math.NewInt(100000000000)) + acc := f.accountKeeper.NewAccountWithAddress(f.ctx, sdk.AccAddress(v.PubKey().Address())) + f.accountKeeper.SetAccount(f.ctx, acc) + simtestutil.AddTestAddrsFromPubKeys(f.bankKeeper, f.stakingKeeper, f.ctx, []cryptotypes.PubKey{v.PubKey()}, math.NewInt(100000000000)) vals = append(vals, testutil.NewValidator(t, valAddr, v.PubKey())) } @@ -60,17 +63,17 @@ func TestValidateVoteExtensions(t *testing.T) { for i, v := range vals { v.Tokens = math.NewInt(1000000) v.Status = stakingtypes.Bonded - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, v)) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, v)) - assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, v)) - _, err := f.stakingKeeper.Delegate(f.sdkCtx, sdk.AccAddress(privKeys[i].PubKey().Address()), v.Tokens, stakingtypes.Unbonded, v, true) + assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, v)) + assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, v)) + assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.ctx, v)) + _, err := f.stakingKeeper.Delegate(f.ctx, sdk.AccAddress(privKeys[i].PubKey().Address()), v.Tokens, stakingtypes.Unbonded, v, true) assert.NilError(t, err) // each val produces a vote voteExt := []byte("something" + v.OperatorAddress) cve := cmtproto.CanonicalVoteExtension{ Extension: voteExt, - Height: f.sdkCtx.HeaderInfo().Height - 1, // the vote extension was signed in the previous height + Height: integration.HeaderInfoFromContext(f.ctx).Height - 1, // the vote extension was signed in the previous height Round: 0, ChainId: chainID, } @@ -95,11 +98,14 @@ func TestValidateVoteExtensions(t *testing.T) { votes = append(votes, ve) } - eci, ci := extendedCommitToLastCommit(abci.ExtendedCommitInfo{Round: 0, Votes: votes}) - f.sdkCtx = f.sdkCtx.WithCometInfo(ci) + _, ci := extendedCommitToLastCommit(abci.ExtendedCommitInfo{Round: 0, Votes: votes}) + f.ctx = integration.SetCometInfo(f.ctx, ci) + + t.Skip("cannot use integration app context in ValidateVoteExtensions") - err := baseapp.ValidateVoteExtensions(f.sdkCtx, f.stakingKeeper, eci) - assert.NilError(t, err) + // TODO: uncomment below code once ValidateVoteExtensions supports app context + // err := baseapp.ValidateVoteExtensions(f.ctx, f.stakingKeeper, eci) + // assert.NilError(t, err) } func mashalVoteExt(msg proto.Message) ([]byte, error) { diff --git a/x/staking/keeper/cons_pubkey.go b/x/staking/keeper/cons_pubkey.go index d60d4628b959..189cdf3efdc5 100644 --- a/x/staking/keeper/cons_pubkey.go +++ b/x/staking/keeper/cons_pubkey.go @@ -263,7 +263,7 @@ func (k Keeper) GetBlockConsPubKeyRotationHistory(ctx context.Context) ([]types. } // GetValidatorConsPubKeyRotationHistory iterates over all the rotated history objects in the state with the given valAddr and returns. -func (k Keeper) GetValidatorConsPubKeyRotationHistory(ctx sdk.Context, operatorAddress sdk.ValAddress) ([]types.ConsPubKeyRotationHistory, error) { +func (k Keeper) GetValidatorConsPubKeyRotationHistory(ctx context.Context, operatorAddress sdk.ValAddress) ([]types.ConsPubKeyRotationHistory, error) { var historyObjects []types.ConsPubKeyRotationHistory rng := collections.NewPrefixedPairRange[[]byte, uint64](operatorAddress.Bytes()) diff --git a/x/staking/keeper/test_common.go b/x/staking/keeper/test_common.go index 1f8a4babc5e6..7c1dcdf34140 100644 --- a/x/staking/keeper/test_common.go +++ b/x/staking/keeper/test_common.go @@ -21,7 +21,7 @@ func ValidatorByPowerIndexExists(ctx context.Context, keeper *Keeper, power []by } // TestingUpdateValidator updates a validator for testing -func TestingUpdateValidator(keeper *Keeper, ctx sdk.Context, validator types.Validator, apply bool) types.Validator { +func TestingUpdateValidator(keeper *Keeper, ctx context.Context, validator types.Validator, apply bool) types.Validator { err := keeper.SetValidator(ctx, validator) if err != nil { panic(err) @@ -61,9 +61,10 @@ func TestingUpdateValidator(keeper *Keeper, ctx sdk.Context, validator types.Val panic(err) } - if !apply { - ctx, _ = ctx.CacheContext() - } + // if !apply { + // sdkCtx := sdk.UnwrapSDKContext(ctx) + // ctx, _ = sdkCtx.CacheContext() + // } _, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx) if err != nil { panic(err) From b707514c9a34060cb89368be36ee00940f17b0c4 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Tue, 10 Dec 2024 14:08:40 +0530 Subject: [PATCH 03/13] revert change --- x/staking/keeper/test_common.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x/staking/keeper/test_common.go b/x/staking/keeper/test_common.go index 7c1dcdf34140..55453758ea88 100644 --- a/x/staking/keeper/test_common.go +++ b/x/staking/keeper/test_common.go @@ -61,10 +61,10 @@ func TestingUpdateValidator(keeper *Keeper, ctx context.Context, validator types panic(err) } - // if !apply { - // sdkCtx := sdk.UnwrapSDKContext(ctx) - // ctx, _ = sdkCtx.CacheContext() - // } + if !apply { + sdkCtx := sdk.UnwrapSDKContext(ctx) + ctx, _ = sdkCtx.CacheContext() + } _, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx) if err != nil { panic(err) From 9c6d3a0a5c8d4f5dd4b7e52ba0c9cdec46ee0f1e Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Wed, 11 Dec 2024 13:59:07 +0530 Subject: [PATCH 04/13] update deterministic tests --- .../v2/staking/deterministic_test.go | 263 ++++++++---------- testutil/configurator/configurator.go | 1 + 2 files changed, 110 insertions(+), 154 deletions(-) diff --git a/tests/integration/v2/staking/deterministic_test.go b/tests/integration/v2/staking/deterministic_test.go index bd733c3708c8..3a8d7f8200ee 100644 --- a/tests/integration/v2/staking/deterministic_test.go +++ b/tests/integration/v2/staking/deterministic_test.go @@ -7,43 +7,26 @@ import ( "testing" "time" - "go.uber.org/mock/gomock" "gotest.tools/v3/assert" "pgregory.net/rapid" - "cosmossdk.io/core/appmodule" - "cosmossdk.io/log" + "cosmossdk.io/core/gas" "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" - "cosmossdk.io/x/bank" bankkeeper "cosmossdk.io/x/bank/keeper" banktestutil "cosmossdk.io/x/bank/testutil" - banktypes "cosmossdk.io/x/bank/types" - "cosmossdk.io/x/consensus" - consensusparamkeeper "cosmossdk.io/x/consensus/keeper" - consensusparamtypes "cosmossdk.io/x/consensus/types" - "cosmossdk.io/x/distribution" minttypes "cosmossdk.io/x/mint/types" - "cosmossdk.io/x/staking" stakingkeeper "cosmossdk.io/x/staking/keeper" 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" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/integration" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" "github.com/cosmos/cosmos-sdk/testutil/testdata" 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" - authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" - authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + "github.com/cosmos/gogoproto/proto" ) var ( @@ -60,131 +43,66 @@ var ( type deterministicFixture struct { app *integration.App - ctx sdk.Context + ctx context.Context cdc codec.Codec keys map[string]*storetypes.KVStoreKey accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.BaseKeeper + bankKeeper bankkeeper.Keeper stakingKeeper *stakingkeeper.Keeper - queryClient stakingtypes.QueryClient - amt1 math.Int - amt2 math.Int + amt1 math.Int + amt2 math.Int } -func initDeterministicFixture(t *testing.T) *deterministicFixture { - t.Helper() - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, consensusparamtypes.StoreKey, - ) - encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, distribution.AppModule{}) - cdc := encodingCfg.Codec - - logger := log.NewTestLogger(t) - authority := authtypes.NewModuleAddress("gov") - - maccPerms := map[string][]string{ - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, +func queryFnFactory[RequestT, ResponseT proto.Message]( + f *deterministicFixture, +) func(RequestT) (ResponseT, error) { + return func(req RequestT) (ResponseT, error) { + var emptyResponse ResponseT + res, err := f.app.Query(f.ctx, 0, req) + if err != nil { + return emptyResponse, err + } + castedRes, ok := res.(ResponseT) + if !ok { + return emptyResponse, fmt.Errorf("unexpected response type: %T", res) + } + return castedRes, nil } +} - // gomock initializations - ctrl := gomock.NewController(t) - 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()), - 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()), - cdc, - accountKeeper, - blockedAddresses, - authority.String(), - ) - - consensusParamsKeeper := consensusparamkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]), log.NewNopLogger()), authtypes.NewModuleAddress("gov").String()) - - stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), log.NewNopLogger()), accountKeeper, bankKeeper, consensusParamsKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr), runtime.NewContextAwareCometInfoService()) - - authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) - bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper) - consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) - - integrationApp := integration.NewIntegrationApp(logger, keys, cdc, - encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), - encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), - map[string]appmodule.AppModule{ - authtypes.ModuleName: authModule, - banktypes.ModuleName: bankModule, - stakingtypes.ModuleName: stakingModule, - consensusparamtypes.ModuleName: consensusModule, - }, - baseapp.NewMsgServiceRouter(), - baseapp.NewGRPCQueryRouter(), - ) - - ctx := integrationApp.Context() - - // Register MsgServer and QueryServer - stakingtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), stakingkeeper.NewMsgServerImpl(stakingKeeper)) - stakingtypes.RegisterQueryServer(integrationApp.QueryHelper(), stakingkeeper.NewQuerier(stakingKeeper)) - - // set default staking params - assert.NilError(t, stakingKeeper.Params.Set(ctx, stakingtypes.DefaultParams())) +func initDeterministicFixture(t *testing.T) *deterministicFixture { + t.Helper() + f := initFixture(t) + ctx := f.ctx // set pools - startTokens := stakingKeeper.TokensFromConsensusPower(ctx, 10) - bondDenom, err := stakingKeeper.BondDenom(ctx) + startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 10) + bondDenom, err := f.stakingKeeper.BondDenom(ctx) assert.NilError(t, err) - notBondedPool := stakingKeeper.GetNotBondedPool(ctx) - assert.NilError(t, banktestutil.FundModuleAccount(ctx, bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) - accountKeeper.SetModuleAccount(ctx, notBondedPool) - bondedPool := stakingKeeper.GetBondedPool(ctx) - assert.NilError(t, banktestutil.FundModuleAccount(ctx, bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) - accountKeeper.SetModuleAccount(ctx, bondedPool) - - qr := integrationApp.QueryHelper() - queryClient := stakingtypes.NewQueryClient(qr) - - amt1 := stakingKeeper.TokensFromConsensusPower(ctx, 101) - amt2 := stakingKeeper.TokensFromConsensusPower(ctx, 102) - - f := deterministicFixture{ - app: integrationApp, - ctx: sdk.UnwrapSDKContext(ctx), - cdc: cdc, - keys: keys, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - stakingKeeper: stakingKeeper, - queryClient: queryClient, + notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx) + assert.NilError(t, banktestutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + f.accountKeeper.SetModuleAccount(ctx, notBondedPool) + bondedPool := f.stakingKeeper.GetBondedPool(ctx) + assert.NilError(t, banktestutil.FundModuleAccount(ctx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) + f.accountKeeper.SetModuleAccount(ctx, bondedPool) + + amt1 := f.stakingKeeper.TokensFromConsensusPower(ctx, 101) + amt2 := f.stakingKeeper.TokensFromConsensusPower(ctx, 102) + + df := deterministicFixture{ + app: f.app, + ctx: ctx, + cdc: f.cdc, + accountKeeper: f.accountKeeper, + bankKeeper: f.bankKeeper, + stakingKeeper: f.stakingKeeper, amt1: amt1, amt2: amt2, } - return &f + return &df } func durationGenerator() *rapid.Generator[time.Duration] { @@ -408,9 +326,21 @@ func fundAccountAndDelegate( return shares, err } +func assertZeroGas(t *testing.T, gasUsed gas.Gas) { + t.Helper() + assert.Check(t, gasUsed == 0) +} + +func assertNonZeroGas(t *testing.T, gasUsed gas.Gas) { + t.Helper() + assert.Check(t, gasUsed != 0) +} + func TestGRPCValidator(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryValidatorRequest, *stakingtypes.QueryValidatorResponse](f) rapid.Check(t, func(rt *rapid.T) { val := createAndSetValidator(t, rt, f) @@ -418,7 +348,7 @@ func TestGRPCValidator(t *testing.T) { ValidatorAddr: val.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validator, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -427,12 +357,14 @@ func TestGRPCValidator(t *testing.T) { ValidatorAddr: val.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validator, 1921, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCValidators(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryValidatorsRequest, *stakingtypes.QueryValidatorsResponse](f) validatorStatus := []string{stakingtypes.BondStatusBonded, stakingtypes.BondStatusUnbonded, stakingtypes.BondStatusUnbonding} rapid.Check(t, func(rt *rapid.T) { @@ -446,19 +378,21 @@ func TestGRPCValidators(t *testing.T) { Pagination: testdata.PaginationGenerator(rt, uint64(valsCount)).Draw(rt, "pagination"), } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validators, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset getStaticValidator(t, f) getStaticValidator2(t, f) - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryValidatorsRequest{}, f.queryClient.Validators, 2880, false) + testdata.DeterministicIterationsV2(t, &stakingtypes.QueryValidatorsRequest{}, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCValidatorDelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryValidatorDelegationsRequest, *stakingtypes.QueryValidatorDelegationsResponse](f) rapid.Check(t, func(rt *rapid.T) { validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) @@ -477,7 +411,7 @@ func TestGRPCValidatorDelegations(t *testing.T) { Pagination: testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination"), } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorDelegations, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -498,12 +432,14 @@ func TestGRPCValidatorDelegations(t *testing.T) { ValidatorAddr: validator.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorDelegations, 14628, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertZeroGas, nil) } func TestGRPCValidatorUnbondingDelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryValidatorUnbondingDelegationsRequest, *stakingtypes.QueryValidatorUnbondingDelegationsResponse](f) rapid.Check(t, func(rt *rapid.T) { validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) @@ -526,7 +462,7 @@ func TestGRPCValidatorUnbondingDelegations(t *testing.T) { Pagination: testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination"), } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorUnbondingDelegations, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -552,18 +488,21 @@ func TestGRPCValidatorUnbondingDelegations(t *testing.T) { ValidatorAddr: validator.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorUnbondingDelegations, 3719, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCDelegation(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryDelegationRequest, *stakingtypes.QueryDelegationResponse](f) rapid.Check(t, func(rt *rapid.T) { validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) f.accountKeeper.SetAccount(f.ctx, acc) + _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) assert.NilError(t, err) @@ -572,7 +511,7 @@ func TestGRPCDelegation(t *testing.T) { DelegatorAddr: delegator.String(), } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Delegation, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -588,12 +527,14 @@ func TestGRPCDelegation(t *testing.T) { DelegatorAddr: delegator1, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Delegation, 4686, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCUnbondingDelegation(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryUnbondingDelegationRequest, *stakingtypes.QueryUnbondingDelegationResponse](f) rapid.Check(t, func(rt *rapid.T) { validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) @@ -613,7 +554,7 @@ func TestGRPCUnbondingDelegation(t *testing.T) { DelegatorAddr: delegator.String(), } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.UnbondingDelegation, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -632,12 +573,14 @@ func TestGRPCUnbondingDelegation(t *testing.T) { DelegatorAddr: delegator1, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.UnbondingDelegation, 1621, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCDelegatorDelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryDelegatorDelegationsRequest, *stakingtypes.QueryDelegatorDelegationsResponse](f) rapid.Check(t, func(rt *rapid.T) { numVals := rapid.IntRange(1, 3).Draw(rt, "num-dels") @@ -656,7 +599,7 @@ func TestGRPCDelegatorDelegations(t *testing.T) { Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorDelegations, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -671,12 +614,14 @@ func TestGRPCDelegatorDelegations(t *testing.T) { DelegatorAddr: delegator1, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorDelegations, 4289, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCDelegatorValidator(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryDelegatorValidatorRequest, *stakingtypes.QueryDelegatorValidatorResponse](f) rapid.Check(t, func(rt *rapid.T) { validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) @@ -692,7 +637,7 @@ func TestGRPCDelegatorValidator(t *testing.T) { ValidatorAddr: validator.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidator, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -709,12 +654,14 @@ func TestGRPCDelegatorValidator(t *testing.T) { ValidatorAddr: validator.OperatorAddress, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidator, 3569, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryDelegatorUnbondingDelegationsRequest, *stakingtypes.QueryDelegatorUnbondingDelegationsResponse](f) rapid.Check(t, func(rt *rapid.T) { numVals := rapid.IntRange(1, 5).Draw(rt, "num-vals") @@ -737,7 +684,7 @@ func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorUnbondingDelegations, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -755,12 +702,14 @@ func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { DelegatorAddr: delegator1, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorUnbondingDelegations, 1302, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCDelegatorValidators(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryDelegatorValidatorsRequest, *stakingtypes.QueryDelegatorValidatorsResponse](f) rapid.Check(t, func(rt *rapid.T) { numVals := rapid.IntRange(1, 3).Draw(rt, "num-dels") @@ -779,7 +728,7 @@ func TestGRPCDelegatorValidators(t *testing.T) { Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidators, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -791,27 +740,31 @@ func TestGRPCDelegatorValidators(t *testing.T) { assert.NilError(t, err) req := &stakingtypes.QueryDelegatorValidatorsRequest{DelegatorAddr: delegator1} - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidators, 3172, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCPool(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryPoolRequest, *stakingtypes.QueryPoolResponse](f) rapid.Check(t, func(rt *rapid.T) { createAndSetValidator(t, rt, f) - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryPoolRequest{}, f.queryClient.Pool, 0, true) + testdata.DeterministicIterationsV2(t, &stakingtypes.QueryPoolRequest{}, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset getStaticValidator(t, f) - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryPoolRequest{}, f.queryClient.Pool, 6287, false) + testdata.DeterministicIterationsV2(t, &stakingtypes.QueryPoolRequest{}, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCRedelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryRedelegationsRequest, *stakingtypes.QueryRedelegationsResponse](f) rapid.Check(t, func(rt *rapid.T) { validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) @@ -854,7 +807,7 @@ func TestGRPCRedelegations(t *testing.T) { } req.Pagination = testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination") - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Redelegations, 0, true) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) f = initDeterministicFixture(t) // reset @@ -875,13 +828,15 @@ func TestGRPCRedelegations(t *testing.T) { DstValidatorAddr: validator2, } - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Redelegations, 3926, false) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } func TestGRPCParams(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) coinDenomRegex := `[a-zA-Z][a-zA-Z0-9/:._-]{2,127}` + gasMeterFactory := integration.GasMeterFactory(f.ctx) + queryFn := queryFnFactory[*stakingtypes.QueryParamsRequest, *stakingtypes.QueryParamsResponse](f) rapid.Check(t, func(rt *rapid.T) { bondDenom := rapid.StringMatching(coinDenomRegex).Draw(rt, "bond-denom") @@ -898,7 +853,7 @@ func TestGRPCParams(t *testing.T) { err := f.stakingKeeper.Params.Set(f.ctx, params) assert.NilError(t, err) - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryParamsRequest{}, f.queryClient.Params, 0, true) + testdata.DeterministicIterationsV2(t, &stakingtypes.QueryParamsRequest{}, gasMeterFactory, queryFn, assertNonZeroGas, nil) }) params := stakingtypes.Params{ @@ -914,5 +869,5 @@ func TestGRPCParams(t *testing.T) { err := f.stakingKeeper.Params.Set(f.ctx, params) assert.NilError(t, err) - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryParamsRequest{}, f.queryClient.Params, 1162, false) + testdata.DeterministicIterationsV2(t, &stakingtypes.QueryParamsRequest{}, gasMeterFactory, queryFn, assertNonZeroGas, nil) } diff --git a/testutil/configurator/configurator.go b/testutil/configurator/configurator.go index 82399afa10bd..70d460c6b271 100644 --- a/testutil/configurator/configurator.go +++ b/testutil/configurator/configurator.go @@ -165,6 +165,7 @@ func AuthModule() ModuleOption { {Account: "fee_collector"}, {Account: testutil.DistributionModuleName, Permissions: []string{"minter"}}, {Account: testutil.MintModuleName, Permissions: []string{"minter"}}, + {Account: testutil.StakingModuleName, Permissions: []string{"minter"}}, {Account: "bonded_tokens_pool", Permissions: []string{"burner", testutil.StakingModuleName}}, {Account: "not_bonded_tokens_pool", Permissions: []string{"burner", testutil.StakingModuleName}}, {Account: testutil.GovModuleName, Permissions: []string{"burner"}}, From 2afea1a32d67d3ad10879586d355c88eb12f6d53 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Wed, 11 Dec 2024 16:48:49 +0530 Subject: [PATCH 05/13] fix few tests --- tests/integration/v2/staking/common_test.go | 29 +++++++-- tests/integration/v2/staking/slash_test.go | 4 +- .../integration/v2/staking/unbonding_test.go | 61 +++++++++++-------- 3 files changed, 60 insertions(+), 34 deletions(-) diff --git a/tests/integration/v2/staking/common_test.go b/tests/integration/v2/staking/common_test.go index 2bd4621d82da..b8f88d73f0f1 100644 --- a/tests/integration/v2/staking/common_test.go +++ b/tests/integration/v2/staking/common_test.go @@ -28,7 +28,6 @@ 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 @@ -39,7 +38,11 @@ import ( _ "github.com/cosmos/cosmos-sdk/x/genutil" // import as blank for app wiring ) -var PKs = simtestutil.CreateTestPubKeys(500) +var ( + PKs = simtestutil.CreateTestPubKeys(500) + + mockStakingHook = types.StakingHooksWrapper{} +) type fixture struct { app *integration.App @@ -112,7 +115,11 @@ func createValidators( return addrs, valAddrs, vals } -func initFixture(tb testing.TB) *fixture { +func ProvideMockStakingHook() types.StakingHooksWrapper { + return mockStakingHook +} + +func initFixture(tb testing.TB, stakingHooks ...types.StakingHooksWrapper) *fixture { tb.Helper() res := fixture{} @@ -128,10 +135,22 @@ func initFixture(tb testing.TB) *fixture { configurator.ConsensusModule(), configurator.GenutilModule(), configurator.MintModule(), - configurator.DistributionModule(), configurator.ProtocolPoolModule(), } + configs := []depinject.Config{ + configurator.NewAppV2Config(moduleConfigs...), + depinject.Supply(log.NewNopLogger()), + } + + // add mock staking hooks if given + if len(stakingHooks) != 0 { + mockStakingHook = stakingHooks[0] + configs = append(configs, depinject.ProvideInModule( + "mock", ProvideMockStakingHook, + )) + } + var err error startupCfg := integration.DefaultStartUpConfig(tb) @@ -139,7 +158,7 @@ func initFixture(tb testing.TB) *fixture { startupCfg.HeaderService = &integration.HeaderService{} res.app, err = integration.NewApp( - depinject.Configs(configurator.NewAppV2Config(moduleConfigs...), depinject.Supply(log.NewNopLogger())), + depinject.Configs(configs...), startupCfg, &res.bankKeeper, &res.accountKeeper, &res.stakingKeeper, &res.slashKeeper, &res.consensusKeeper, &res.cdc) diff --git a/tests/integration/v2/staking/slash_test.go b/tests/integration/v2/staking/slash_test.go index 11d63937e69d..f4cd62e3dd9a 100644 --- a/tests/integration/v2/staking/slash_test.go +++ b/tests/integration/v2/staking/slash_test.go @@ -239,7 +239,7 @@ func TestSlashValidatorAtCurrentHeight(t *testing.T) { _, found := f.stakingKeeper.GetValidatorByConsAddr(f.ctx, consAddr) assert.Assert(t, found) - _, err = f.stakingKeeper.Slash(f.ctx, consAddr, int64(f.app.LastBlockHeight())+1, 10, fraction) + _, err = f.stakingKeeper.Slash(f.ctx, consAddr, int64(f.app.LastBlockHeight()), 10, fraction) assert.NilError(t, err) // read updated state @@ -633,7 +633,7 @@ func TestSlashAmount(t *testing.T) { f, _, _ := bootstrapSlashTest(t, 10) consAddr := sdk.ConsAddress(PKs[0].Address()) fraction := math.LegacyNewDecWithPrec(5, 1) - burnedCoins, err := f.stakingKeeper.Slash(f.ctx, consAddr, int64(f.app.LastBlockHeight())+1, 10, fraction) + burnedCoins, err := f.stakingKeeper.Slash(f.ctx, consAddr, int64(f.app.LastBlockHeight()), 10, fraction) assert.NilError(t, err) assert.Assert(t, burnedCoins.GT(math.ZeroInt())) diff --git a/tests/integration/v2/staking/unbonding_test.go b/tests/integration/v2/staking/unbonding_test.go index 7f94da34e0fc..249ca9e95ec5 100644 --- a/tests/integration/v2/staking/unbonding_test.go +++ b/tests/integration/v2/staking/unbonding_test.go @@ -20,19 +20,19 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" ) -// SetupUnbondingTests creates two validators and setup mocked staking hooks for testing unbonding -func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uint64) (bondDenom string, addrDels []sdk.AccAddress, addrVals []sdk.ValAddress) { - t.Helper() +var testStakingKeeper = &stakingkeeper.Keeper{} + +func mockHooks(t *testing.T, hookCalled *bool, ubdeID *uint64) *testutil.MockStakingHooks { // setup hooks mockCtrl := gomock.NewController(t) mockStackingHooks := testutil.NewMockStakingHooks(mockCtrl) mockStackingHooks.EXPECT().AfterDelegationModified(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().AfterUnbondingInitiated(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx sdk.Context, id uint64) error { + mockStackingHooks.EXPECT().AfterUnbondingInitiated(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx context.Context, id uint64) error { *hookCalled = true // save id *ubdeID = id // call back to stop unbonding - err := f.stakingKeeper.PutUnbondingOnHold(f.ctx, id) + err := testStakingKeeper.PutUnbondingOnHold(ctx, id) assert.NilError(t, err) return nil @@ -47,8 +47,12 @@ func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uin mockStackingHooks.EXPECT().BeforeValidatorModified(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() mockStackingHooks.EXPECT().BeforeValidatorSlashed(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() mockStackingHooks.EXPECT().AfterConsensusPubKeyUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - f.stakingKeeper.SetHooks(types.NewMultiStakingHooks(mockStackingHooks)) + return mockStackingHooks +} +// SetupUnbondingTests creates two validators and setup mocked staking hooks for testing unbonding +func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uint64) (bondDenom string, addrDels []sdk.AccAddress, addrVals []sdk.ValAddress) { + t.Helper() addrDels = simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.ctx, 2, math.NewInt(10000)) addrVals = simtestutil.ConvertAddrsToValAddrs(addrDels) @@ -178,14 +182,15 @@ func doValidatorUnbonding( } func TestValidatorUnbondingOnHold1(t *testing.T) { - t.Parallel() - f := initFixture(t) - var ( hookCalled bool ubdeID uint64 ) + f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + // set global staking keeper value which will be used in mock hooks + testStakingKeeper = f.stakingKeeper + _, _, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) // Start unbonding first validator @@ -227,15 +232,16 @@ func TestValidatorUnbondingOnHold1(t *testing.T) { } func TestValidatorUnbondingOnHold2(t *testing.T) { - t.Parallel() - f := initFixture(t) - var ( hookCalled bool ubdeID uint64 ubdeIDs []uint64 ) + f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + // set global staking keeper value which will be used in mock hooks + testStakingKeeper = f.stakingKeeper + _, _, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) // Start unbonding first validator @@ -314,15 +320,15 @@ func TestValidatorUnbondingOnHold2(t *testing.T) { } func TestRedelegationOnHold1(t *testing.T) { - t.Parallel() - f := initFixture(t) - var ( hookCalled bool ubdeID uint64 ) - // _, app, ctx := createTestInput(t) + f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + // set global staking keeper value which will be used in mock hooks + testStakingKeeper = f.stakingKeeper + _, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) completionTime := doRedelegation(t, f.stakingKeeper, f.ctx, addrDels, addrVals, &hookCalled) @@ -347,14 +353,15 @@ func TestRedelegationOnHold1(t *testing.T) { } func TestRedelegationOnHold2(t *testing.T) { - t.Parallel() - f := initFixture(t) - var ( hookCalled bool ubdeID uint64 ) + f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + // set global staking keeper value which will be used in mock hooks + testStakingKeeper = f.stakingKeeper + // _, app, ctx := createTestInput(t) _, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) completionTime := doRedelegation(t, f.stakingKeeper, f.ctx, addrDels, addrVals, &hookCalled) @@ -380,15 +387,15 @@ func TestRedelegationOnHold2(t *testing.T) { } func TestUnbondingDelegationOnHold1(t *testing.T) { - t.Parallel() - f := initFixture(t) - var ( hookCalled bool ubdeID uint64 ) - // _, app, ctx := createTestInput(t) + f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + // set global staking keeper value which will be used in mock hooks + testStakingKeeper = f.stakingKeeper + bondDenom, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) for _, addr := range addrDels { acc := f.accountKeeper.NewAccountWithAddress(f.ctx, addr) @@ -423,15 +430,15 @@ func TestUnbondingDelegationOnHold1(t *testing.T) { } func TestUnbondingDelegationOnHold2(t *testing.T) { - t.Parallel() - f := initFixture(t) - var ( hookCalled bool ubdeID uint64 ) - // _, app, ctx := createTestInput(t) + f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + // set global staking keeper value which will be used in mock hooks + testStakingKeeper = f.stakingKeeper + bondDenom, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) for _, addr := range addrDels { acc := f.accountKeeper.NewAccountWithAddress(f.ctx, addr) From 029ace1a3cb9647a145ccb68a3e296c810abaf39 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Thu, 12 Dec 2024 16:35:23 +0530 Subject: [PATCH 06/13] fix few more tests --- tests/integration/v2/services.go | 2 +- tests/integration/v2/staking/common_test.go | 5 +- .../integration/v2/staking/delegation_test.go | 2 +- .../v2/staking/deterministic_test.go | 63 +++++++++++++------ tests/integration/v2/staking/genesis_test.go | 11 ++-- .../integration/v2/staking/grpc_query_test.go | 51 ++++++++------- tests/integration/v2/staking/module_test.go | 2 +- .../integration/v2/staking/msg_server_test.go | 9 +-- tests/integration/v2/staking/slash_test.go | 4 +- .../integration/v2/staking/unbonding_test.go | 12 ++-- .../integration/v2/staking/validator_test.go | 2 +- .../v2/staking/vote_extensions_test.go | 2 +- 12 files changed, 95 insertions(+), 70 deletions(-) diff --git a/tests/integration/v2/services.go b/tests/integration/v2/services.go index 241a07cdd82f..edfce05aa42a 100644 --- a/tests/integration/v2/services.go +++ b/tests/integration/v2/services.go @@ -110,7 +110,7 @@ func GasMeterFactory(ctx context.Context) func() gas.Meter { } func (s storeService) OpenKVStore(ctx context.Context) corestore.KVStore { - const gasLimit = 100_000 + const gasLimit = 1_000_000 iCtx, ok := ctx.Value(contextKey).(*integrationContext) if !ok { return s.executionService.OpenKVStore(ctx) diff --git a/tests/integration/v2/staking/common_test.go b/tests/integration/v2/staking/common_test.go index b8f88d73f0f1..4776cef7bc60 100644 --- a/tests/integration/v2/staking/common_test.go +++ b/tests/integration/v2/staking/common_test.go @@ -119,7 +119,7 @@ func ProvideMockStakingHook() types.StakingHooksWrapper { return mockStakingHook } -func initFixture(tb testing.TB, stakingHooks ...types.StakingHooksWrapper) *fixture { +func initFixture(tb testing.TB, isGenesisSkip bool, stakingHooks ...types.StakingHooksWrapper) *fixture { tb.Helper() res := fixture{} @@ -156,6 +156,9 @@ func initFixture(tb testing.TB, stakingHooks ...types.StakingHooksWrapper) *fixt startupCfg.BranchService = &integration.BranchService{} startupCfg.HeaderService = &integration.HeaderService{} + if isGenesisSkip { + startupCfg.GenesisBehavior = integration.Genesis_SKIP + } res.app, err = integration.NewApp( depinject.Configs(configs...), diff --git a/tests/integration/v2/staking/delegation_test.go b/tests/integration/v2/staking/delegation_test.go index ea8e90ef4264..3f35beea7021 100644 --- a/tests/integration/v2/staking/delegation_test.go +++ b/tests/integration/v2/staking/delegation_test.go @@ -19,7 +19,7 @@ import ( func TestUnbondingDelegationsMaxEntries(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, false) ctx := f.ctx diff --git a/tests/integration/v2/staking/deterministic_test.go b/tests/integration/v2/staking/deterministic_test.go index 3a8d7f8200ee..973b48c1e569 100644 --- a/tests/integration/v2/staking/deterministic_test.go +++ b/tests/integration/v2/staking/deterministic_test.go @@ -74,7 +74,7 @@ func queryFnFactory[RequestT, ResponseT proto.Message]( func initDeterministicFixture(t *testing.T) *deterministicFixture { t.Helper() - f := initFixture(t) + f := initFixture(t, false) ctx := f.ctx // set pools @@ -326,17 +326,12 @@ func fundAccountAndDelegate( return shares, err } -func assertZeroGas(t *testing.T, gasUsed gas.Gas) { - t.Helper() - assert.Check(t, gasUsed == 0) -} - func assertNonZeroGas(t *testing.T, gasUsed gas.Gas) { t.Helper() assert.Check(t, gasUsed != 0) } -func TestGRPCValidator(t *testing.T) { +func TestValidator(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -352,6 +347,9 @@ func TestGRPCValidator(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryValidatorRequest, *stakingtypes.QueryValidatorResponse](f) + val := getStaticValidator(t, f) req := &stakingtypes.QueryValidatorRequest{ ValidatorAddr: val.OperatorAddress, @@ -360,7 +358,7 @@ func TestGRPCValidator(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCValidators(t *testing.T) { +func TestValidators(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -382,13 +380,16 @@ func TestGRPCValidators(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryValidatorsRequest, *stakingtypes.QueryValidatorsResponse](f) + getStaticValidator(t, f) getStaticValidator2(t, f) testdata.DeterministicIterationsV2(t, &stakingtypes.QueryValidatorsRequest{}, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCValidatorDelegations(t *testing.T) { +func TestValidatorDelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -415,6 +416,8 @@ func TestGRPCValidatorDelegations(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryValidatorDelegationsRequest, *stakingtypes.QueryValidatorDelegationsResponse](f) validator := getStaticValidator(t, f) @@ -432,10 +435,10 @@ func TestGRPCValidatorDelegations(t *testing.T) { ValidatorAddr: validator.OperatorAddress, } - testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertZeroGas, nil) + testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCValidatorUnbondingDelegations(t *testing.T) { +func TestValidatorUnbondingDelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -466,6 +469,8 @@ func TestGRPCValidatorUnbondingDelegations(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryValidatorUnbondingDelegationsRequest, *stakingtypes.QueryValidatorUnbondingDelegationsResponse](f) validator := getStaticValidator(t, f) acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) @@ -491,7 +496,7 @@ func TestGRPCValidatorUnbondingDelegations(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCDelegation(t *testing.T) { +func TestDelegation(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -515,6 +520,8 @@ func TestGRPCDelegation(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryDelegationRequest, *stakingtypes.QueryDelegationResponse](f) validator := getStaticValidator(t, f) acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) @@ -530,7 +537,7 @@ func TestGRPCDelegation(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCUnbondingDelegation(t *testing.T) { +func TestUnbondingDelegation(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -558,6 +565,9 @@ func TestGRPCUnbondingDelegation(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryUnbondingDelegationRequest, *stakingtypes.QueryUnbondingDelegationResponse](f) + validator := getStaticValidator(t, f) acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) @@ -576,7 +586,7 @@ func TestGRPCUnbondingDelegation(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCDelegatorDelegations(t *testing.T) { +func TestDelegatorDelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -603,6 +613,8 @@ func TestGRPCDelegatorDelegations(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryDelegatorDelegationsRequest, *stakingtypes.QueryDelegatorDelegationsResponse](f) validator := getStaticValidator(t, f) acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) @@ -617,7 +629,7 @@ func TestGRPCDelegatorDelegations(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCDelegatorValidator(t *testing.T) { +func TestDelegatorValidator(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -641,6 +653,8 @@ func TestGRPCDelegatorValidator(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryDelegatorValidatorRequest, *stakingtypes.QueryDelegatorValidatorResponse](f) validator := getStaticValidator(t, f) acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) @@ -657,7 +671,7 @@ func TestGRPCDelegatorValidator(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { +func TestDelegatorUnbondingDelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -688,6 +702,8 @@ func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryDelegatorUnbondingDelegationsRequest, *stakingtypes.QueryDelegatorUnbondingDelegationsResponse](f) validator := getStaticValidator(t, f) acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) @@ -705,7 +721,7 @@ func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCDelegatorValidators(t *testing.T) { +func TestDelegatorValidators(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -732,6 +748,8 @@ func TestGRPCDelegatorValidators(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryDelegatorValidatorsRequest, *stakingtypes.QueryDelegatorValidatorsResponse](f) validator := getStaticValidator(t, f) acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) @@ -743,7 +761,7 @@ func TestGRPCDelegatorValidators(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCPool(t *testing.T) { +func TestPool(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -756,11 +774,13 @@ func TestGRPCPool(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryPoolRequest, *stakingtypes.QueryPoolResponse](f) getStaticValidator(t, f) testdata.DeterministicIterationsV2(t, &stakingtypes.QueryPoolRequest{}, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCRedelegations(t *testing.T) { +func TestRedelegations(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) gasMeterFactory := integration.GasMeterFactory(f.ctx) @@ -811,6 +831,9 @@ func TestGRPCRedelegations(t *testing.T) { }) f = initDeterministicFixture(t) // reset + gasMeterFactory = integration.GasMeterFactory(f.ctx) + queryFn = queryFnFactory[*stakingtypes.QueryRedelegationsRequest, *stakingtypes.QueryRedelegationsResponse](f) + validator := getStaticValidator(t, f) _ = getStaticValidator2(t, f) @@ -831,7 +854,7 @@ func TestGRPCRedelegations(t *testing.T) { testdata.DeterministicIterationsV2(t, req, gasMeterFactory, queryFn, assertNonZeroGas, nil) } -func TestGRPCParams(t *testing.T) { +func TestParams(t *testing.T) { t.Parallel() f := initDeterministicFixture(t) coinDenomRegex := `[a-zA-Z][a-zA-Z0-9/:._-]{2,127}` diff --git a/tests/integration/v2/staking/genesis_test.go b/tests/integration/v2/staking/genesis_test.go index 977abe8abe61..35a0a92bec4d 100644 --- a/tests/integration/v2/staking/genesis_test.go +++ b/tests/integration/v2/staking/genesis_test.go @@ -21,7 +21,7 @@ import ( func bootstrapGenesisTest(t *testing.T, numAddrs int) (*fixture, []sdk.AccAddress) { t.Helper() t.Parallel() - f := initFixture(t) + f := initFixture(t, true) addrDels, _ := generateAddresses(f, numAddrs) return f, addrDels @@ -51,8 +51,7 @@ func TestInitGenesis(t *testing.T) { validators, err := f.stakingKeeper.GetAllValidators(f.ctx) assert.NilError(t, err) - // check validators count including init validator - assert.Assert(t, len(validators) == 2) + assert.Assert(t, len(validators) == 1) var delegations []types.Delegation pk1, err := codectypes.NewAnyWithValue(PKs[1]) @@ -82,7 +81,7 @@ func TestInitGenesis(t *testing.T) { // append new bonded validators to the list validators = append(validators, bondedVal1, bondedVal2) - // mint coins in the bonded pool representing the validators coins + // mint coins in the bonded pool representing the validators coins, ignore genesis validator i2 := len(validators) assert.NilError(t, banktestutil.FundModuleAccount( @@ -100,7 +99,7 @@ func TestInitGenesis(t *testing.T) { delegations = append(delegations, genesisDelegations...) genesisState := types.NewGenesisState(params, validators, delegations) - vals, err := (f.stakingKeeper.InitGenesis(f.ctx, genesisState)) + vals, err := f.stakingKeeper.InitGenesis(f.ctx, genesisState) assert.NilError(t, err) actualGenesis, err := (f.stakingKeeper.ExportGenesis(f.ctx)) @@ -138,7 +137,7 @@ func TestInitGenesis(t *testing.T) { func TestInitGenesis_PoolsBalanceMismatch(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) consPub, err := codectypes.NewAnyWithValue(PKs[0]) assert.NilError(t, err) diff --git a/tests/integration/v2/staking/grpc_query_test.go b/tests/integration/v2/staking/grpc_query_test.go index 03170808742b..44dd89ee527b 100644 --- a/tests/integration/v2/staking/grpc_query_test.go +++ b/tests/integration/v2/staking/grpc_query_test.go @@ -1,7 +1,6 @@ package staking import ( - gocontext "context" "fmt" "testing" @@ -30,7 +29,7 @@ func createValidatorAccs(t *testing.T, f *fixture) ([]sdk.AccAddress, []types.Va func TestGRPCQueryValidators(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) _, vals := createValidatorAccs(t, f) @@ -92,7 +91,7 @@ func TestGRPCQueryValidators(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - valsResp, err := queryClient.Validators(gocontext.Background(), req) + valsResp, err := queryClient.Validators(f.ctx, req) if tc.expPass { assert.NilError(t, err) assert.Assert(t, valsResp != nil) @@ -113,7 +112,7 @@ func TestGRPCQueryValidators(t *testing.T) { func TestGRPCQueryDelegatorValidators(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx addrs, _ := createValidatorAccs(t, f) @@ -166,7 +165,7 @@ func TestGRPCQueryDelegatorValidators(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.DelegatorValidators(gocontext.Background(), req) + res, err := queryClient.DelegatorValidators(f.ctx, req) if tc.expPass { assert.NilError(t, err) assert.Equal(t, 1, len(res.Validators)) @@ -182,7 +181,7 @@ func TestGRPCQueryDelegatorValidators(t *testing.T) { func TestGRPCQueryDelegatorValidator(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) addrs, vals := createValidatorAccs(t, f) @@ -254,7 +253,7 @@ func TestGRPCQueryDelegatorValidator(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.DelegatorValidator(gocontext.Background(), req) + res, err := queryClient.DelegatorValidator(f.ctx, req) if tc.expPass { assert.NilError(t, err) assert.Equal(t, addrVal1, res.Validator.OperatorAddress) @@ -268,7 +267,7 @@ func TestGRPCQueryDelegatorValidator(t *testing.T) { func TestGRPCQueryDelegation(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx addrs, vals := createValidatorAccs(t, f) @@ -321,7 +320,7 @@ func TestGRPCQueryDelegation(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.Delegation(gocontext.Background(), req) + res, err := queryClient.Delegation(f.ctx, req) if tc.expPass { assert.Equal(t, delegation.ValidatorAddress, res.DelegationResponse.Delegation.ValidatorAddress) assert.Equal(t, delegation.DelegatorAddress, res.DelegationResponse.Delegation.DelegatorAddress) @@ -336,7 +335,7 @@ func TestGRPCQueryDelegation(t *testing.T) { func TestGRPCQueryDelegatorDelegations(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx addrs, vals := createValidatorAccs(t, f) @@ -400,7 +399,7 @@ func TestGRPCQueryDelegatorDelegations(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.DelegatorDelegations(gocontext.Background(), req) + res, err := queryClient.DelegatorDelegations(f.ctx, req) if tc.expErr { assert.ErrorContains(t, err, tc.expErrMsg) } else { @@ -413,7 +412,7 @@ func TestGRPCQueryDelegatorDelegations(t *testing.T) { func TestGRPCQueryValidatorDelegations(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx addrs, vals := createValidatorAccs(t, f) @@ -472,7 +471,7 @@ func TestGRPCQueryValidatorDelegations(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.ValidatorDelegations(gocontext.Background(), req) + res, err := queryClient.ValidatorDelegations(f.ctx, req) switch { case tc.expPass && !tc.expErr: assert.NilError(t, err) @@ -483,7 +482,7 @@ func TestGRPCQueryValidatorDelegations(t *testing.T) { assert.DeepEqual(t, sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponses[0].Balance) case !tc.expPass && !tc.expErr: assert.NilError(t, err) - assert.Assert(t, res.DelegationResponses == nil) + assert.Assert(t, len(res.DelegationResponses) == 0) default: assert.ErrorContains(t, err, tc.expErrMsg) assert.Assert(t, res == nil) @@ -494,7 +493,7 @@ func TestGRPCQueryValidatorDelegations(t *testing.T) { func TestGRPCQueryUnbondingDelegation(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx addrs, vals := createValidatorAccs(t, f) @@ -582,7 +581,7 @@ func TestGRPCQueryUnbondingDelegation(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.UnbondingDelegation(gocontext.Background(), req) + res, err := queryClient.UnbondingDelegation(f.ctx, req) if tc.expPass { assert.Assert(t, res != nil) assert.DeepEqual(t, unbond, res.Unbond) @@ -596,7 +595,7 @@ func TestGRPCQueryUnbondingDelegation(t *testing.T) { func TestGRPCQueryDelegatorUnbondingDelegations(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx addrs, vals := createValidatorAccs(t, f) @@ -661,7 +660,7 @@ func TestGRPCQueryDelegatorUnbondingDelegations(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.DelegatorUnbondingDelegations(gocontext.Background(), req) + res, err := queryClient.DelegatorUnbondingDelegations(f.ctx, req) switch { case tc.expPass && !tc.expErr: assert.NilError(t, err) @@ -682,7 +681,7 @@ func TestGRPCQueryDelegatorUnbondingDelegations(t *testing.T) { func TestGRPCQueryPoolParameters(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx @@ -691,7 +690,7 @@ func TestGRPCQueryPoolParameters(t *testing.T) { bondDenom := sdk.DefaultBondDenom // Query pool - res, err := queryClient.Pool(gocontext.Background(), &types.QueryPoolRequest{}) + res, err := queryClient.Pool(f.ctx, &types.QueryPoolRequest{}) assert.NilError(t, err) bondedPool := f.stakingKeeper.GetBondedPool(ctx) notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx) @@ -699,7 +698,7 @@ func TestGRPCQueryPoolParameters(t *testing.T) { assert.DeepEqual(t, f.bankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount, res.Pool.BondedTokens) // Query Params - resp, err := queryClient.Params(gocontext.Background(), &types.QueryParamsRequest{}) + resp, err := queryClient.Params(f.ctx, &types.QueryParamsRequest{}) assert.NilError(t, err) params, err := f.stakingKeeper.Params.Get(ctx) assert.NilError(t, err) @@ -708,7 +707,7 @@ func TestGRPCQueryPoolParameters(t *testing.T) { func TestGRPCQueryRedelegations(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx addrs, vals := createValidatorAccs(t, f) @@ -807,7 +806,7 @@ func TestGRPCQueryRedelegations(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.Redelegations(gocontext.Background(), req) + res, err := queryClient.Redelegations(f.ctx, req) switch { case tc.expPass && !tc.expErr: assert.NilError(t, err) @@ -818,7 +817,7 @@ func TestGRPCQueryRedelegations(t *testing.T) { assert.Assert(t, len(redel.Entries) == len(res.RedelegationResponses[0].Entries)) case !tc.expPass && !tc.expErr: assert.NilError(t, err) - assert.Assert(t, res.RedelegationResponses == nil) + assert.Assert(t, len(res.RedelegationResponses) == 0) default: assert.ErrorContains(t, err, tc.expErrMsg) assert.Assert(t, res == nil) @@ -829,7 +828,7 @@ func TestGRPCQueryRedelegations(t *testing.T) { func TestGRPCQueryValidatorUnbondingDelegations(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, true) ctx := f.ctx addrs, vals := createValidatorAccs(t, f) @@ -889,7 +888,7 @@ func TestGRPCQueryValidatorUnbondingDelegations(t *testing.T) { for _, tc := range testCases { t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { tc.malleate() - res, err := queryClient.ValidatorUnbondingDelegations(gocontext.Background(), req) + res, err := queryClient.ValidatorUnbondingDelegations(f.ctx, req) if tc.expPass { assert.NilError(t, err) assert.Equal(t, uint64(1), res.Pagination.Total) diff --git a/tests/integration/v2/staking/module_test.go b/tests/integration/v2/staking/module_test.go index cfbcf58700dd..917657b9d722 100644 --- a/tests/integration/v2/staking/module_test.go +++ b/tests/integration/v2/staking/module_test.go @@ -11,7 +11,7 @@ import ( ) func TestItCreatesModuleAccountOnInitBlock(t *testing.T) { - f := initFixture(t) + f := initFixture(t, false) acc := f.accountKeeper.GetAccount(f.ctx, authtypes.NewModuleAddress(types.BondedPoolName)) require.NotNil(t, acc) diff --git a/tests/integration/v2/staking/msg_server_test.go b/tests/integration/v2/staking/msg_server_test.go index ccc4c9055382..01577438235d 100644 --- a/tests/integration/v2/staking/msg_server_test.go +++ b/tests/integration/v2/staking/msg_server_test.go @@ -23,7 +23,7 @@ import ( func TestCancelUnbondingDelegation(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, false) ctx := f.ctx msgServer := keeper.NewMsgServerImpl(f.stakingKeeper) @@ -181,7 +181,7 @@ func TestCancelUnbondingDelegation(t *testing.T) { func TestRotateConsPubKey(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, false) ctx := f.ctx stakingKeeper := f.stakingKeeper @@ -326,8 +326,9 @@ func TestRotateConsPubKey(t *testing.T) { _, err = msgServer.RotateConsPubKey(ctx, msg) assert.Error(t, err, "exceeding maximum consensus pubkey rotations within unbonding period") - newHeight = integration.HeaderInfoFromContext(ctx).Height + 1 - newCtx := integration.SetHeaderInfo(ctx, header.Info{Height: newHeight + 1}) + ctxHeader := integration.HeaderInfoFromContext(ctx) + newHeight = ctxHeader.Height + 1 + newCtx := integration.SetHeaderInfo(ctx, header.Info{Height: newHeight + 1, Time: ctxHeader.Time.Add(params.UnbondingTime)}) // this should remove keys from waiting queue since unbonding time is reached _, err = stakingKeeper.EndBlocker(newCtx) diff --git a/tests/integration/v2/staking/slash_test.go b/tests/integration/v2/staking/slash_test.go index f4cd62e3dd9a..5ddba3ecb100 100644 --- a/tests/integration/v2/staking/slash_test.go +++ b/tests/integration/v2/staking/slash_test.go @@ -32,7 +32,7 @@ import ( func bootstrapSlashTest(t *testing.T, power int64) (*fixture, []sdk.AccAddress, []sdk.ValAddress) { t.Helper() t.Parallel() - f := initFixture(t) + f := initFixture(t, false) addrDels, addrVals := generateAddresses(f, 100) @@ -647,7 +647,7 @@ func TestSlashAmount(t *testing.T) { // TestFixAvoidFullSlashPenalty fixes the following issue: https://github.com/cosmos/cosmos-sdk/issues/20641 func TestFixAvoidFullSlashPenalty(t *testing.T) { // setup - f := initFixture(t) + f := initFixture(t, false) ctx := f.ctx stakingMsgServer := keeper.NewMsgServerImpl(f.stakingKeeper) diff --git a/tests/integration/v2/staking/unbonding_test.go b/tests/integration/v2/staking/unbonding_test.go index 249ca9e95ec5..761991d2c304 100644 --- a/tests/integration/v2/staking/unbonding_test.go +++ b/tests/integration/v2/staking/unbonding_test.go @@ -187,7 +187,7 @@ func TestValidatorUnbondingOnHold1(t *testing.T) { ubdeID uint64 ) - f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + f := initFixture(t, false, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) // set global staking keeper value which will be used in mock hooks testStakingKeeper = f.stakingKeeper @@ -238,7 +238,7 @@ func TestValidatorUnbondingOnHold2(t *testing.T) { ubdeIDs []uint64 ) - f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + f := initFixture(t, false, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) // set global staking keeper value which will be used in mock hooks testStakingKeeper = f.stakingKeeper @@ -325,7 +325,7 @@ func TestRedelegationOnHold1(t *testing.T) { ubdeID uint64 ) - f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + f := initFixture(t, false, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) // set global staking keeper value which will be used in mock hooks testStakingKeeper = f.stakingKeeper @@ -358,7 +358,7 @@ func TestRedelegationOnHold2(t *testing.T) { ubdeID uint64 ) - f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + f := initFixture(t, false, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) // set global staking keeper value which will be used in mock hooks testStakingKeeper = f.stakingKeeper @@ -392,7 +392,7 @@ func TestUnbondingDelegationOnHold1(t *testing.T) { ubdeID uint64 ) - f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + f := initFixture(t, false, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) // set global staking keeper value which will be used in mock hooks testStakingKeeper = f.stakingKeeper @@ -435,7 +435,7 @@ func TestUnbondingDelegationOnHold2(t *testing.T) { ubdeID uint64 ) - f := initFixture(t, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) + f := initFixture(t, false, types.StakingHooksWrapper{StakingHooks: mockHooks(t, &hookCalled, &ubdeID)}) // set global staking keeper value which will be used in mock hooks testStakingKeeper = f.stakingKeeper diff --git a/tests/integration/v2/staking/validator_test.go b/tests/integration/v2/staking/validator_test.go index e39bce5a675a..712b9f6ae621 100644 --- a/tests/integration/v2/staking/validator_test.go +++ b/tests/integration/v2/staking/validator_test.go @@ -30,7 +30,7 @@ func newMonikerValidator(tb testing.TB, operator sdk.ValAddress, pubKey cryptoty func bootstrapValidatorTest(tb testing.TB, power int64, numAddrs int) (*fixture, []sdk.AccAddress, []sdk.ValAddress) { tb.Helper() - f := initFixture(tb) + f := initFixture(tb, true) addrDels, addrVals := generateAddresses(f, numAddrs) diff --git a/tests/integration/v2/staking/vote_extensions_test.go b/tests/integration/v2/staking/vote_extensions_test.go index d3d0c533b3aa..1695c27c93c6 100644 --- a/tests/integration/v2/staking/vote_extensions_test.go +++ b/tests/integration/v2/staking/vote_extensions_test.go @@ -32,7 +32,7 @@ const chainID = "chain-id-123" // and validates the vote extensions using the baseapp.ValidateVoteExtensions function. func TestValidateVoteExtensions(t *testing.T) { t.Parallel() - f := initFixture(t) + f := initFixture(t, false) // enable vote extensions cp := simtestutil.DefaultConsensusParams From 0e8ac6a788b2b7819c9fd463228c2364f2e892e1 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Fri, 13 Dec 2024 12:29:44 +0530 Subject: [PATCH 07/13] fix all tests --- tests/integration/staking/app_config.go | 31 - .../integration/staking/keeper/common_test.go | 214 ---- .../staking/keeper/delegation_test.go | 118 --- .../staking/keeper/deterministic_test.go | 918 ------------------ .../staking/keeper/genesis_test.go | 238 ----- .../staking/keeper/grpc_query_test.go | 915 ----------------- .../staking/keeper/msg_server_test.go | 390 -------- .../integration/staking/keeper/slash_test.go | 767 --------------- .../staking/keeper/unbonding_test.go | 460 --------- .../staking/keeper/validator_bench_test.go | 181 ---- .../staking/keeper/validator_test.go | 887 ----------------- .../staking/keeper/vote_extensions_test.go | 153 --- tests/integration/staking/module_test.go | 32 - .../integration/v2/staking/delegation_test.go | 2 +- tests/integration/v2/staking/slash_test.go | 2 +- .../integration/v2/staking/unbonding_test.go | 4 +- .../integration/v2/staking/validator_test.go | 90 +- .../v2/staking/vote_extensions_test.go | 2 +- x/staking/keeper/test_common.go | 65 +- 19 files changed, 117 insertions(+), 5352 deletions(-) delete mode 100644 tests/integration/staking/app_config.go delete mode 100644 tests/integration/staking/keeper/common_test.go delete mode 100644 tests/integration/staking/keeper/delegation_test.go delete mode 100644 tests/integration/staking/keeper/deterministic_test.go delete mode 100644 tests/integration/staking/keeper/genesis_test.go delete mode 100644 tests/integration/staking/keeper/grpc_query_test.go delete mode 100644 tests/integration/staking/keeper/msg_server_test.go delete mode 100644 tests/integration/staking/keeper/slash_test.go delete mode 100644 tests/integration/staking/keeper/unbonding_test.go delete mode 100644 tests/integration/staking/keeper/validator_bench_test.go delete mode 100644 tests/integration/staking/keeper/validator_test.go delete mode 100644 tests/integration/staking/keeper/vote_extensions_test.go delete mode 100644 tests/integration/staking/module_test.go diff --git a/tests/integration/staking/app_config.go b/tests/integration/staking/app_config.go deleted file mode 100644 index 4c08ff1faef6..000000000000 --- a/tests/integration/staking/app_config.go +++ /dev/null @@ -1,31 +0,0 @@ -package staking - -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.TxModule(), - configurator.ValidateModule(), - configurator.ConsensusModule(), - configurator.GenutilModule(), - configurator.MintModule(), - configurator.DistributionModule(), - configurator.ProtocolPoolModule(), -) diff --git a/tests/integration/staking/keeper/common_test.go b/tests/integration/staking/keeper/common_test.go deleted file mode 100644 index bcce987fc4f5..000000000000 --- a/tests/integration/staking/keeper/common_test.go +++ /dev/null @@ -1,214 +0,0 @@ -package keeper_test - -import ( - "context" - "math/big" - "testing" - - "go.uber.org/mock/gomock" - "gotest.tools/v3/assert" - - "cosmossdk.io/core/appmodule" - "cosmossdk.io/log" - "cosmossdk.io/math" - 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" - pooltypes "cosmossdk.io/x/protocolpool/types" - "cosmossdk.io/x/staking" - stakingkeeper "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/testutil" - "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" - 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" - authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" - authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -var PKs = simtestutil.CreateTestPubKeys(500) - -type fixture struct { - app *integration.App - - sdkCtx sdk.Context - cdc codec.Codec - keys map[string]*storetypes.KVStoreKey - - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper -} - -func init() { - sdk.DefaultPowerReduction = math.NewIntFromBigInt(new(big.Int).Exp(big.NewInt(10), big.NewInt(18), nil)) -} - -// intended to be used with require/assert: require.True(ValEq(...)) -func ValEq(t *testing.T, exp, got types.Validator) (*testing.T, bool, string, types.Validator, types.Validator) { - t.Helper() - return t, exp.MinEqual(&got), "expected:\n%v\ngot:\n%v", exp, got -} - -// generateAddresses generates numAddrs of normal AccAddrs and ValAddrs -func generateAddresses(f *fixture, numAddrs int) ([]sdk.AccAddress, []sdk.ValAddress) { - addrDels := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, numAddrs, math.NewInt(10000)) - addrVals := simtestutil.ConvertAddrsToValAddrs(addrDels) - - return addrDels, addrVals -} - -func createValidators( - t *testing.T, - f *fixture, - powers []int64, -) ([]sdk.AccAddress, []sdk.ValAddress, []types.Validator) { - t.Helper() - addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, 5, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 300)) - valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) - pks := simtestutil.CreateTestPubKeys(5) - - val1 := testutil.NewValidator(t, valAddrs[0], pks[0]) - val2 := testutil.NewValidator(t, valAddrs[1], pks[1]) - vals := []types.Validator{val1, val2} - - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, val1)) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, val2)) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val1)) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, val2)) - assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val1)) - assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, val2)) - - for _, addr := range addrs { - acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) - f.accountKeeper.SetAccount(f.sdkCtx, acc) - } - - _, err := f.stakingKeeper.Delegate(f.sdkCtx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[0]), types.Unbonded, val1, true) - assert.NilError(t, err) - _, err = f.stakingKeeper.Delegate(f.sdkCtx, addrs[1], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[1]), types.Unbonded, val2, true) - assert.NilError(t, err) - _, err = f.stakingKeeper.Delegate(f.sdkCtx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, powers[2]), types.Unbonded, val2, true) - assert.NilError(t, err) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) - - return addrs, valAddrs, vals -} - -func initFixture(tb testing.TB) *fixture { - tb.Helper() - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, types.StoreKey, consensustypes.StoreKey, - ) - encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, staking.AppModule{}) - cdc := encodingCfg.Codec - - msgRouter := baseapp.NewMsgServiceRouter() - queryRouter := baseapp.NewGRPCQueryRouter() - - logger := log.NewTestLogger(tb) - authority := authtypes.NewModuleAddress("gov") - - maccPerms := map[string][]string{ - pooltypes.ModuleName: {}, - minttypes.ModuleName: {authtypes.Minter}, - types.ModuleName: {authtypes.Minter}, - types.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - types.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - } - - // gomock initializations - ctrl := gomock.NewController(tb) - acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl) - var lastAccNum uint64 - acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) { - lastAccNum++ - return lastAccNum, 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()), - cdc, - accountKeeper, - blockedAddresses, - authority.String(), - ) - - consensusParamsKeeper := consensusparamkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensustypes.StoreKey]), log.NewNopLogger()), authtypes.NewModuleAddress("gov").String()) - - stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[types.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(msgRouter)), accountKeeper, bankKeeper, consensusParamsKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr), runtime.NewContextAwareCometInfoService()) - - authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) - bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper) - consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) - - integrationApp := integration.NewIntegrationApp(logger, keys, cdc, - encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), - encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), - map[string]appmodule.AppModule{ - authtypes.ModuleName: authModule, - banktypes.ModuleName: bankModule, - types.ModuleName: stakingModule, - consensustypes.ModuleName: consensusModule, - }, - msgRouter, - queryRouter, - ) - - sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) - - // Register MsgServer and QueryServer - types.RegisterMsgServer(integrationApp.MsgServiceRouter(), stakingkeeper.NewMsgServerImpl(stakingKeeper)) - types.RegisterQueryServer(integrationApp.QueryHelper(), stakingkeeper.NewQuerier(stakingKeeper)) - - // set default staking params - assert.NilError(tb, stakingKeeper.Params.Set(sdkCtx, types.DefaultParams())) - accNum := uint64(0) - acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) { - currentNum := accNum - accNum++ - return currentNum, nil - }) - - f := fixture{ - app: integrationApp, - sdkCtx: sdkCtx, - cdc: cdc, - keys: keys, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - stakingKeeper: stakingKeeper, - } - - return &f -} diff --git a/tests/integration/staking/keeper/delegation_test.go b/tests/integration/staking/keeper/delegation_test.go deleted file mode 100644 index 9e5dab17c0b4..000000000000 --- a/tests/integration/staking/keeper/delegation_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package keeper_test - -import ( - "testing" - "time" - - "gotest.tools/v3/assert" - - "cosmossdk.io/core/header" - "cosmossdk.io/math" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/testutil" - "cosmossdk.io/x/staking/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func TestUnbondingDelegationsMaxEntries(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - - initTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, int64(1000)) - assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, initTokens)))) - - addrDel := sdk.AccAddress([]byte("addr")) - accAmt := math.NewInt(10000) - bondDenom, err := f.stakingKeeper.BondDenom(ctx) - assert.NilError(t, err) - - initCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, accAmt)) - assert.NilError(t, f.bankKeeper.MintCoins(ctx, types.ModuleName, initCoins)) - assert.NilError(t, f.bankKeeper.SendCoinsFromModuleToAccount(ctx, types.ModuleName, addrDel, initCoins)) - addrVal := sdk.ValAddress(addrDel) - - startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 10) - - notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx) - - assert.NilError(t, banktestutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) - f.accountKeeper.SetModuleAccount(ctx, notBondedPool) - - // create a validator and a delegator to that validator - validator := testutil.NewValidator(t, addrVal, PKs[0]) - - validator, issuedShares := validator.AddTokensFromDel(startTokens) - assert.DeepEqual(t, startTokens, issuedShares.RoundInt()) - - validator = keeper.TestingUpdateValidator(f.stakingKeeper, ctx, validator, true) - assert.Assert(math.IntEq(t, startTokens, validator.BondedTokens())) - assert.Assert(t, validator.IsBonded()) - - delegation := types.NewDelegation(addrDel.String(), addrVal.String(), issuedShares) - assert.NilError(t, f.stakingKeeper.SetDelegation(ctx, delegation)) - - maxEntries, err := f.stakingKeeper.MaxEntries(ctx) - assert.NilError(t, err) - - oldBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - oldNotBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - // should all pass - var completionTime time.Time - totalUnbonded := math.NewInt(0) - for i := int64(0); i < int64(maxEntries); i++ { - var err error - ctx = ctx.WithHeaderInfo(header.Info{Height: i}) - var amount math.Int - completionTime, amount, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1)) - assert.NilError(t, err) - totalUnbonded = totalUnbonded.Add(amount) - } - - newBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - newNotBonded := f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, newBonded, oldBonded.SubRaw(int64(maxEntries)))) - assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(int64(maxEntries)))) - assert.Assert(math.IntEq(t, totalUnbonded, oldBonded.Sub(newBonded))) - assert.Assert(math.IntEq(t, totalUnbonded, newNotBonded.Sub(oldNotBonded))) - - oldBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - oldNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - // an additional unbond should fail due to max entries - _, _, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1)) - assert.Error(t, err, "too many unbonding delegation entries for (delegator, validator) tuple") - - newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - assert.Assert(math.IntEq(t, newBonded, oldBonded)) - assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded)) - - // mature unbonding delegations - ctx = ctx.WithHeaderInfo(header.Info{Time: completionTime}) - acc := f.accountKeeper.NewAccountWithAddress(ctx, addrDel) - f.accountKeeper.SetAccount(ctx, acc) - _, err = f.stakingKeeper.CompleteUnbonding(ctx, addrDel, addrVal) - assert.NilError(t, err) - - newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, newBonded, oldBonded)) - assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.SubRaw(int64(maxEntries)))) - - oldNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - // unbonding should work again - _, _, err = f.stakingKeeper.Undelegate(ctx, addrDel, addrVal, math.LegacyNewDec(1)) - assert.NilError(t, err) - - newBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - newNotBonded = f.bankKeeper.GetBalance(ctx, f.stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, newBonded, oldBonded.SubRaw(1))) - assert.Assert(math.IntEq(t, newNotBonded, oldNotBonded.AddRaw(1))) -} diff --git a/tests/integration/staking/keeper/deterministic_test.go b/tests/integration/staking/keeper/deterministic_test.go deleted file mode 100644 index 77f99c9d32ee..000000000000 --- a/tests/integration/staking/keeper/deterministic_test.go +++ /dev/null @@ -1,918 +0,0 @@ -package keeper_test - -import ( - "context" - "fmt" - "net/url" - "testing" - "time" - - "go.uber.org/mock/gomock" - "gotest.tools/v3/assert" - "pgregory.net/rapid" - - "cosmossdk.io/core/appmodule" - "cosmossdk.io/log" - "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" - "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - banktypes "cosmossdk.io/x/bank/types" - "cosmossdk.io/x/consensus" - consensusparamkeeper "cosmossdk.io/x/consensus/keeper" - consensusparamtypes "cosmossdk.io/x/consensus/types" - "cosmossdk.io/x/distribution" - minttypes "cosmossdk.io/x/mint/types" - "cosmossdk.io/x/staking" - stakingkeeper "cosmossdk.io/x/staking/keeper" - 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" - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/integration" - "github.com/cosmos/cosmos-sdk/testutil/testdata" - 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" - authsims "github.com/cosmos/cosmos-sdk/x/auth/simulation" - authtestutil "github.com/cosmos/cosmos-sdk/x/auth/testutil" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -var ( - validator1 = "cosmosvaloper1qqqryrs09ggeuqszqygqyqd2tgqmsqzewacjj7" - validatorAddr1, _ = sdk.ValAddressFromBech32(validator1) - validator2 = "cosmosvaloper1gghjut3ccd8ay0zduzj64hwre2fxs9ldmqhffj" - validatorAddr2, _ = sdk.ValAddressFromBech32(validator2) - delegator1 = "cosmos1nph3cfzk6trsmfxkeu943nvach5qw4vwstnvkl" - delegatorAddr1 = sdk.MustAccAddressFromBech32(delegator1) - delegator2 = "cosmos139f7kncmglres2nf3h4hc4tade85ekfr8sulz5" - delegatorAddr2 = sdk.MustAccAddressFromBech32(delegator2) -) - -type deterministicFixture struct { - app *integration.App - - ctx sdk.Context - cdc codec.Codec - keys map[string]*storetypes.KVStoreKey - - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.BaseKeeper - stakingKeeper *stakingkeeper.Keeper - - queryClient stakingtypes.QueryClient - amt1 math.Int - amt2 math.Int -} - -func initDeterministicFixture(t *testing.T) *deterministicFixture { - t.Helper() - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, consensusparamtypes.StoreKey, - ) - encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, distribution.AppModule{}) - cdc := encodingCfg.Codec - - logger := log.NewTestLogger(t) - authority := authtypes.NewModuleAddress("gov") - - maccPerms := map[string][]string{ - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - } - - // gomock initializations - ctrl := gomock.NewController(t) - 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()), - 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()), - cdc, - accountKeeper, - blockedAddresses, - authority.String(), - ) - - consensusParamsKeeper := consensusparamkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]), log.NewNopLogger()), authtypes.NewModuleAddress("gov").String()) - - stakingKeeper := stakingkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[stakingtypes.StoreKey]), log.NewNopLogger()), accountKeeper, bankKeeper, consensusParamsKeeper, authority.String(), addresscodec.NewBech32Codec(sdk.Bech32PrefixValAddr), addresscodec.NewBech32Codec(sdk.Bech32PrefixConsAddr), runtime.NewContextAwareCometInfoService()) - - authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) - bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper) - consensusModule := consensus.NewAppModule(cdc, consensusParamsKeeper) - - integrationApp := integration.NewIntegrationApp(logger, keys, cdc, - encodingCfg.InterfaceRegistry.SigningContext().AddressCodec(), - encodingCfg.InterfaceRegistry.SigningContext().ValidatorAddressCodec(), - map[string]appmodule.AppModule{ - authtypes.ModuleName: authModule, - banktypes.ModuleName: bankModule, - stakingtypes.ModuleName: stakingModule, - consensusparamtypes.ModuleName: consensusModule, - }, - baseapp.NewMsgServiceRouter(), - baseapp.NewGRPCQueryRouter(), - ) - - ctx := integrationApp.Context() - - // Register MsgServer and QueryServer - stakingtypes.RegisterMsgServer(integrationApp.MsgServiceRouter(), stakingkeeper.NewMsgServerImpl(stakingKeeper)) - stakingtypes.RegisterQueryServer(integrationApp.QueryHelper(), stakingkeeper.NewQuerier(stakingKeeper)) - - // set default staking params - assert.NilError(t, stakingKeeper.Params.Set(ctx, stakingtypes.DefaultParams())) - - // set pools - startTokens := stakingKeeper.TokensFromConsensusPower(ctx, 10) - bondDenom, err := stakingKeeper.BondDenom(ctx) - assert.NilError(t, err) - notBondedPool := stakingKeeper.GetNotBondedPool(ctx) - assert.NilError(t, banktestutil.FundModuleAccount(ctx, bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) - accountKeeper.SetModuleAccount(ctx, notBondedPool) - bondedPool := stakingKeeper.GetBondedPool(ctx) - assert.NilError(t, banktestutil.FundModuleAccount(ctx, bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) - accountKeeper.SetModuleAccount(ctx, bondedPool) - - qr := integrationApp.QueryHelper() - queryClient := stakingtypes.NewQueryClient(qr) - - amt1 := stakingKeeper.TokensFromConsensusPower(ctx, 101) - amt2 := stakingKeeper.TokensFromConsensusPower(ctx, 102) - - f := deterministicFixture{ - app: integrationApp, - ctx: sdk.UnwrapSDKContext(ctx), - cdc: cdc, - keys: keys, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - stakingKeeper: stakingKeeper, - queryClient: queryClient, - amt1: amt1, - amt2: amt2, - } - - return &f -} - -func durationGenerator() *rapid.Generator[time.Duration] { - return rapid.Custom(func(t *rapid.T) time.Duration { - now := time.Now() - // range from current time to 365days. - duration := rapid.Int64Range(now.Unix(), 365*24*60*60*now.Unix()).Draw(t, "time") - return time.Duration(duration) - }) -} - -func pubKeyGenerator() *rapid.Generator[ed25519.PubKey] { - return rapid.Custom(func(t *rapid.T) ed25519.PubKey { - pkBz := rapid.SliceOfN(rapid.Byte(), 32, 32).Draw(t, "hex") - return ed25519.PubKey{Key: pkBz} - }) -} - -func bondTypeGenerator() *rapid.Generator[stakingtypes.BondStatus] { - bondTypes := []stakingtypes.BondStatus{stakingtypes.Bonded, stakingtypes.Unbonded, stakingtypes.Unbonding} - return rapid.Custom(func(t *rapid.T) stakingtypes.BondStatus { - return bondTypes[rapid.IntRange(0, 2).Draw(t, "range")] - }) -} - -func metadataGenerator() *rapid.Generator[*stakingtypes.Metadata] { - return rapid.Custom(func(t *rapid.T) *stakingtypes.Metadata { - return &stakingtypes.Metadata{ - ProfilePicUri: generateUri(t), - SocialHandleUris: []string{generateUri(t), generateUri(t)}, - } - }) -} - -func generateUri(t *rapid.T) string { - host := fmt.Sprintf("%s.com", rapid.StringN(5, 250, 255).Draw(t, "host")) - path := rapid.StringN(5, 250, 255).Draw(t, "path") - uri := url.URL{ - Scheme: "https", - Host: host, - Path: path, - } - return uri.String() -} - -// createValidator creates a validator with random values. -func createValidator(t *testing.T, rt *rapid.T, _ *deterministicFixture) stakingtypes.Validator { - t.Helper() - pubkey := pubKeyGenerator().Draw(rt, "pubkey") - pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey) - assert.NilError(t, err) - return stakingtypes.Validator{ - OperatorAddress: sdk.ValAddress(testdata.AddressGenerator(rt).Draw(rt, "address")).String(), - ConsensusPubkey: pubkeyAny, - Jailed: rapid.Bool().Draw(rt, "jailed"), - Status: bondTypeGenerator().Draw(rt, "bond-status"), - Tokens: math.NewInt(rapid.Int64Min(10000).Draw(rt, "tokens")), - DelegatorShares: math.LegacyNewDecWithPrec(rapid.Int64Range(1, 100).Draw(rt, "commission"), 2), - Description: stakingtypes.NewDescription( - rapid.StringN(5, 250, 255).Draw(rt, "moniker"), - rapid.StringN(5, 250, 255).Draw(rt, "identity"), - rapid.StringN(5, 250, 255).Draw(rt, "website"), - rapid.StringN(5, 250, 255).Draw(rt, "securityContact"), - rapid.StringN(5, 250, 255).Draw(rt, "details"), - metadataGenerator().Draw(rt, "metadata"), - ), - UnbondingHeight: rapid.Int64Min(1).Draw(rt, "unbonding-height"), - UnbondingTime: time.Now().Add(durationGenerator().Draw(rt, "duration")), - Commission: stakingtypes.NewCommission( - math.LegacyNewDecWithPrec(rapid.Int64Range(0, 100).Draw(rt, "rate"), 2), - math.LegacyNewDecWithPrec(rapid.Int64Range(0, 100).Draw(rt, "max-rate"), 2), - math.LegacyNewDecWithPrec(rapid.Int64Range(0, 100).Draw(rt, "max-change-rate"), 2), - ), - MinSelfDelegation: math.NewInt(rapid.Int64Min(1).Draw(rt, "tokens")), - } -} - -// createAndSetValidatorWithStatus creates a validator with random values but with given status and sets to the state -func createAndSetValidatorWithStatus( - t *testing.T, - rt *rapid.T, - f *deterministicFixture, - status stakingtypes.BondStatus, -) stakingtypes.Validator { - t.Helper() - val := createValidator(t, rt, f) - val.Status = status - setValidator(t, f, val) - return val -} - -// createAndSetValidator creates a validator with random values and sets to the state -func createAndSetValidator(t *testing.T, rt *rapid.T, f *deterministicFixture) stakingtypes.Validator { - t.Helper() - val := createValidator(t, rt, f) - setValidator(t, f, val) - return val -} - -func setValidator(t *testing.T, f *deterministicFixture, validator stakingtypes.Validator) { - t.Helper() - assert.NilError(t, f.stakingKeeper.SetValidator(f.ctx, validator)) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.ctx, validator)) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, validator)) - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - assert.NilError(t, err) - - assert.NilError(t, f.stakingKeeper.Hooks().AfterValidatorCreated(f.ctx, valbz)) - - delegatorAddress := sdk.AccAddress(valbz) - coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, validator.BondedTokens())) - assert.NilError(t, banktestutil.FundAccount(f.ctx, f.bankKeeper, delegatorAddress, coins)) - - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddress) - f.accountKeeper.SetAccount(f.ctx, acc) - - _, err = f.stakingKeeper.Delegate(f.ctx, delegatorAddress, validator.BondedTokens(), stakingtypes.Unbonded, validator, true) - assert.NilError(t, err) -} - -// getStaticValidator creates a validator with hard-coded values and sets to the state. -func getStaticValidator(t *testing.T, f *deterministicFixture) stakingtypes.Validator { - t.Helper() - pubkey := ed25519.PubKey{Key: []byte{24, 179, 242, 2, 151, 3, 34, 6, 1, 11, 0, 194, 202, 201, 77, 1, 167, 40, 249, 115, 32, 97, 18, 1, 1, 127, 255, 103, 13, 1, 34, 1}} - pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey) - assert.NilError(t, err) - - validator := stakingtypes.Validator{ - OperatorAddress: validator1, - ConsensusPubkey: pubkeyAny, - Jailed: false, - Status: stakingtypes.Bonded, - Tokens: math.NewInt(100), - DelegatorShares: math.LegacyNewDecWithPrec(5, 2), - Description: stakingtypes.NewDescription( - "moniker", - "identity", - "website", - "securityContact", - "details", - &stakingtypes.Metadata{}, - ), - UnbondingHeight: 10, - UnbondingTime: time.Date(2022, 10, 1, 0, 0, 0, 0, time.UTC), - Commission: stakingtypes.NewCommission( - math.LegacyNewDecWithPrec(5, 2), - math.LegacyNewDecWithPrec(5, 2), - math.LegacyNewDecWithPrec(5, 2), - ), - MinSelfDelegation: math.NewInt(10), - } - - setValidator(t, f, validator) - return validator -} - -// getStaticValidator2 creates a validator with hard-coded values and sets to the state. -func getStaticValidator2(t *testing.T, f *deterministicFixture) stakingtypes.Validator { - t.Helper() - pubkey := ed25519.PubKey{Key: []byte{40, 249, 115, 32, 97, 18, 1, 1, 127, 255, 103, 13, 1, 34, 1, 24, 179, 242, 2, 151, 3, 34, 6, 1, 11, 0, 194, 202, 201, 77, 1, 167}} - pubkeyAny, err := codectypes.NewAnyWithValue(&pubkey) - assert.NilError(t, err) - - validator := stakingtypes.Validator{ - OperatorAddress: validator2, - ConsensusPubkey: pubkeyAny, - Jailed: true, - Status: stakingtypes.Bonded, - Tokens: math.NewInt(10012), - DelegatorShares: math.LegacyNewDecWithPrec(96, 2), - Description: stakingtypes.NewDescription( - "moniker", - "identity", - "website", - "securityContact", - "details", - &stakingtypes.Metadata{}, - ), - UnbondingHeight: 100132, - UnbondingTime: time.Date(2025, 10, 1, 0, 0, 0, 0, time.UTC), - Commission: stakingtypes.NewCommission( - math.LegacyNewDecWithPrec(15, 2), - math.LegacyNewDecWithPrec(59, 2), - math.LegacyNewDecWithPrec(51, 2), - ), - MinSelfDelegation: math.NewInt(1), - } - setValidator(t, f, validator) - - return validator -} - -// createDelegationAndDelegate funds the delegator account with a random delegation in range 100-1000 and delegates. -func createDelegationAndDelegate( - t *testing.T, - rt *rapid.T, - f *deterministicFixture, - delegator sdk.AccAddress, - validator stakingtypes.Validator, -) (newShares math.LegacyDec, err error) { - t.Helper() - amt := f.stakingKeeper.TokensFromConsensusPower(f.ctx, rapid.Int64Range(100, 1000).Draw(rt, "amount")) - return fundAccountAndDelegate(t, f, delegator, validator, amt) -} - -// fundAccountAndDelegate funds the delegator account with the specified delegation and delegates. -func fundAccountAndDelegate( - t *testing.T, - f *deterministicFixture, - delegator sdk.AccAddress, - validator stakingtypes.Validator, - amt math.Int, -) (newShares math.LegacyDec, err error) { - t.Helper() - coins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, amt)) - - assert.NilError(t, f.bankKeeper.MintCoins(f.ctx, minttypes.ModuleName, coins)) - assert.NilError(t, banktestutil.FundAccount(f.ctx, f.bankKeeper, delegator, coins)) - - shares, err := f.stakingKeeper.Delegate(f.ctx, delegator, amt, stakingtypes.Unbonded, validator, true) - return shares, err -} - -func TestGRPCValidator(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - val := createAndSetValidator(t, rt, f) - req := &stakingtypes.QueryValidatorRequest{ - ValidatorAddr: val.OperatorAddress, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validator, 0, true) - }) - - f = initDeterministicFixture(t) // reset - val := getStaticValidator(t, f) - req := &stakingtypes.QueryValidatorRequest{ - ValidatorAddr: val.OperatorAddress, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validator, 1921, false) -} - -func TestGRPCValidators(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - validatorStatus := []string{stakingtypes.BondStatusBonded, stakingtypes.BondStatusUnbonded, stakingtypes.BondStatusUnbonding} - rapid.Check(t, func(rt *rapid.T) { - valsCount := rapid.IntRange(1, 3).Draw(rt, "num-validators") - for i := 0; i < valsCount; i++ { - createAndSetValidator(t, rt, f) - } - - req := &stakingtypes.QueryValidatorsRequest{ - Status: validatorStatus[rapid.IntRange(0, 2).Draw(rt, "status")], - Pagination: testdata.PaginationGenerator(rt, uint64(valsCount)).Draw(rt, "pagination"), - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Validators, 0, true) - }) - - f = initDeterministicFixture(t) // reset - getStaticValidator(t, f) - getStaticValidator2(t, f) - - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryValidatorsRequest{}, f.queryClient.Validators, 2880, false) -} - -func TestGRPCValidatorDelegations(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - numDels := rapid.IntRange(1, 5).Draw(rt, "num-dels") - - for i := 0; i < numDels; i++ { - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - } - - req := &stakingtypes.QueryValidatorDelegationsRequest{ - ValidatorAddr: validator.OperatorAddress, - Pagination: testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination"), - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorDelegations, 0, true) - }) - - f = initDeterministicFixture(t) // reset - - validator := getStaticValidator(t, f) - - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - assert.NilError(t, err) - - acc = f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr2) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err = fundAccountAndDelegate(t, f, delegatorAddr2, validator, f.amt2) - assert.NilError(t, err) - - req := &stakingtypes.QueryValidatorDelegationsRequest{ - ValidatorAddr: validator.OperatorAddress, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorDelegations, 14628, false) -} - -func TestGRPCValidatorUnbondingDelegations(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - numDels := rapid.IntRange(1, 3).Draw(rt, "num-dels") - - for i := 0; i < numDels; i++ { - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - shares, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - assert.NilError(t, err) - _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegator, valbz, shares) - assert.NilError(t, err) - } - - req := &stakingtypes.QueryValidatorUnbondingDelegationsRequest{ - ValidatorAddr: validator.OperatorAddress, - Pagination: testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination"), - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorUnbondingDelegations, 0, true) - }) - - f = initDeterministicFixture(t) // reset - - validator := getStaticValidator(t, f) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - shares1, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - assert.NilError(t, err) - - _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegatorAddr1, validatorAddr1, shares1) - assert.NilError(t, err) - - acc = f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr2) - f.accountKeeper.SetAccount(f.ctx, acc) - shares2, err := fundAccountAndDelegate(t, f, delegatorAddr2, validator, f.amt2) - assert.NilError(t, err) - - _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegatorAddr2, validatorAddr1, shares2) - assert.NilError(t, err) - - req := &stakingtypes.QueryValidatorUnbondingDelegationsRequest{ - ValidatorAddr: validator.OperatorAddress, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.ValidatorUnbondingDelegations, 3719, false) -} - -func TestGRPCDelegation(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - - req := &stakingtypes.QueryDelegationRequest{ - ValidatorAddr: validator.OperatorAddress, - DelegatorAddr: delegator.String(), - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Delegation, 0, true) - }) - - f = initDeterministicFixture(t) // reset - - validator := getStaticValidator(t, f) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - assert.NilError(t, err) - - req := &stakingtypes.QueryDelegationRequest{ - ValidatorAddr: validator.OperatorAddress, - DelegatorAddr: delegator1, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Delegation, 4686, false) -} - -func TestGRPCUnbondingDelegation(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - shares, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - assert.NilError(t, err) - _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegator, valbz, shares) - assert.NilError(t, err) - - req := &stakingtypes.QueryUnbondingDelegationRequest{ - ValidatorAddr: validator.OperatorAddress, - DelegatorAddr: delegator.String(), - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.UnbondingDelegation, 0, true) - }) - - f = initDeterministicFixture(t) // reset - validator := getStaticValidator(t, f) - - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - shares1, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - assert.NilError(t, err) - - _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegatorAddr1, validatorAddr1, shares1) - assert.NilError(t, err) - - req := &stakingtypes.QueryUnbondingDelegationRequest{ - ValidatorAddr: validator.OperatorAddress, - DelegatorAddr: delegator1, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.UnbondingDelegation, 1621, false) -} - -func TestGRPCDelegatorDelegations(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - numVals := rapid.IntRange(1, 3).Draw(rt, "num-dels") - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - - for i := 0; i < numVals; i++ { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - } - - req := &stakingtypes.QueryDelegatorDelegationsRequest{ - DelegatorAddr: delegator.String(), - Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorDelegations, 0, true) - }) - - f = initDeterministicFixture(t) // reset - - validator := getStaticValidator(t, f) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - assert.NilError(t, err) - - req := &stakingtypes.QueryDelegatorDelegationsRequest{ - DelegatorAddr: delegator1, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorDelegations, 4289, false) -} - -func TestGRPCDelegatorValidator(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - - req := &stakingtypes.QueryDelegatorValidatorRequest{ - DelegatorAddr: delegator.String(), - ValidatorAddr: validator.OperatorAddress, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidator, 0, true) - }) - - f = initDeterministicFixture(t) // reset - - validator := getStaticValidator(t, f) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - - assert.NilError(t, err) - - req := &stakingtypes.QueryDelegatorValidatorRequest{ - DelegatorAddr: delegator1, - ValidatorAddr: validator.OperatorAddress, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidator, 3569, false) -} - -func TestGRPCDelegatorUnbondingDelegations(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - numVals := rapid.IntRange(1, 5).Draw(rt, "num-vals") - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - - for i := 0; i < numVals; i++ { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - shares, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - assert.NilError(t, err) - _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegator, valbz, shares) - assert.NilError(t, err) - } - - req := &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{ - DelegatorAddr: delegator.String(), - Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorUnbondingDelegations, 0, true) - }) - - f = initDeterministicFixture(t) // reset - - validator := getStaticValidator(t, f) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - shares1, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - assert.NilError(t, err) - - _, _, err = f.stakingKeeper.Undelegate(f.ctx, delegatorAddr1, validatorAddr1, shares1) - assert.NilError(t, err) - - req := &stakingtypes.QueryDelegatorUnbondingDelegationsRequest{ - DelegatorAddr: delegator1, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorUnbondingDelegations, 1302, false) -} - -func TestGRPCDelegatorValidators(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - numVals := rapid.IntRange(1, 3).Draw(rt, "num-dels") - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - - for i := 0; i < numVals; i++ { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - } - - req := &stakingtypes.QueryDelegatorValidatorsRequest{ - DelegatorAddr: delegator.String(), - Pagination: testdata.PaginationGenerator(rt, uint64(numVals)).Draw(rt, "pagination"), - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidators, 0, true) - }) - - f = initDeterministicFixture(t) // reset - - validator := getStaticValidator(t, f) - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - _, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - assert.NilError(t, err) - - req := &stakingtypes.QueryDelegatorValidatorsRequest{DelegatorAddr: delegator1} - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.DelegatorValidators, 3172, false) -} - -func TestGRPCPool(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - createAndSetValidator(t, rt, f) - - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryPoolRequest{}, f.queryClient.Pool, 0, true) - }) - - f = initDeterministicFixture(t) // reset - getStaticValidator(t, f) - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryPoolRequest{}, f.queryClient.Pool, 6287, false) -} - -func TestGRPCRedelegations(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - - rapid.Check(t, func(rt *rapid.T) { - validator := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - srcValAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) - assert.NilError(t, err) - - validator2 := createAndSetValidatorWithStatus(t, rt, f, stakingtypes.Bonded) - dstValAddr, err := sdk.ValAddressFromBech32(validator2.OperatorAddress) - assert.NilError(t, err) - - numDels := rapid.IntRange(1, 5).Draw(rt, "num-dels") - - delegator := testdata.AddressGenerator(rt).Draw(rt, "delegator") - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegator) - f.accountKeeper.SetAccount(f.ctx, acc) - shares, err := createDelegationAndDelegate(t, rt, f, delegator, validator) - assert.NilError(t, err) - - _, err = f.stakingKeeper.BeginRedelegation(f.ctx, delegator, srcValAddr, dstValAddr, shares) - assert.NilError(t, err) - - var req *stakingtypes.QueryRedelegationsRequest - - reqType := rapid.IntRange(0, 2).Draw(rt, "req-type") - switch reqType { - case 0: // queries redelegation with delegator, source and destination validators combination. - req = &stakingtypes.QueryRedelegationsRequest{ - DelegatorAddr: delegator.String(), - SrcValidatorAddr: srcValAddr.String(), - DstValidatorAddr: dstValAddr.String(), - } - case 1: // queries redelegations of source validator. - req = &stakingtypes.QueryRedelegationsRequest{ - SrcValidatorAddr: srcValAddr.String(), - } - case 2: // queries all redelegations of a delegator. - req = &stakingtypes.QueryRedelegationsRequest{ - DelegatorAddr: delegator.String(), - } - } - - req.Pagination = testdata.PaginationGenerator(rt, uint64(numDels)).Draw(rt, "pagination") - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Redelegations, 0, true) - }) - - f = initDeterministicFixture(t) // reset - validator := getStaticValidator(t, f) - _ = getStaticValidator2(t, f) - - acc := f.accountKeeper.NewAccountWithAddress(f.ctx, delegatorAddr1) - f.accountKeeper.SetAccount(f.ctx, acc) - shares, err := fundAccountAndDelegate(t, f, delegatorAddr1, validator, f.amt1) - assert.NilError(t, err) - - _, err = f.stakingKeeper.BeginRedelegation(f.ctx, delegatorAddr1, validatorAddr1, validatorAddr2, shares) - assert.NilError(t, err) - - req := &stakingtypes.QueryRedelegationsRequest{ - DelegatorAddr: delegator1, - SrcValidatorAddr: validator1, - DstValidatorAddr: validator2, - } - - testdata.DeterministicIterations(t, f.ctx, req, f.queryClient.Redelegations, 3926, false) -} - -func TestGRPCParams(t *testing.T) { - t.Parallel() - f := initDeterministicFixture(t) - coinDenomRegex := `[a-zA-Z][a-zA-Z0-9/:._-]{2,127}` - - rapid.Check(t, func(rt *rapid.T) { - bondDenom := rapid.StringMatching(coinDenomRegex).Draw(rt, "bond-denom") - params := stakingtypes.Params{ - BondDenom: bondDenom, - UnbondingTime: durationGenerator().Draw(rt, "duration"), - MaxValidators: rapid.Uint32Min(1).Draw(rt, "max-validators"), - MaxEntries: rapid.Uint32Min(1).Draw(rt, "max-entries"), - HistoricalEntries: rapid.Uint32Min(1).Draw(rt, "historical-entries"), - MinCommissionRate: math.LegacyNewDecWithPrec(rapid.Int64Range(0, 100).Draw(rt, "commission"), 2), - KeyRotationFee: sdk.NewInt64Coin(bondDenom, rapid.Int64Range(10000, 100000).Draw(rt, "amount")), - } - - err := f.stakingKeeper.Params.Set(f.ctx, params) - assert.NilError(t, err) - - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryParamsRequest{}, f.queryClient.Params, 0, true) - }) - - params := stakingtypes.Params{ - BondDenom: "denom", - UnbondingTime: time.Hour, - MaxValidators: 85, - MaxEntries: 5, - HistoricalEntries: 5, - MinCommissionRate: math.LegacyNewDecWithPrec(5, 2), - KeyRotationFee: sdk.NewInt64Coin("denom", 10000), - } - - err := f.stakingKeeper.Params.Set(f.ctx, params) - assert.NilError(t, err) - - testdata.DeterministicIterations(t, f.ctx, &stakingtypes.QueryParamsRequest{}, f.queryClient.Params, 1162, false) -} diff --git a/tests/integration/staking/keeper/genesis_test.go b/tests/integration/staking/keeper/genesis_test.go deleted file mode 100644 index 82bc85562ce1..000000000000 --- a/tests/integration/staking/keeper/genesis_test.go +++ /dev/null @@ -1,238 +0,0 @@ -package keeper_test - -import ( - "fmt" - "testing" - - "github.com/stretchr/testify/require" - "gotest.tools/v3/assert" - - "cosmossdk.io/core/appmodule" - "cosmossdk.io/math" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/staking" - "cosmossdk.io/x/staking/types" - - codectypes "github.com/cosmos/cosmos-sdk/codec/types" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" -) - -func bootstrapGenesisTest(t *testing.T, numAddrs int) (*fixture, []sdk.AccAddress) { - t.Helper() - t.Parallel() - f := initFixture(t) - - addrDels, _ := generateAddresses(f, numAddrs) - return f, addrDels -} - -func TestInitGenesis(t *testing.T) { - f, addrs := bootstrapGenesisTest(t, 10) - - valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) - - pk0, err := codectypes.NewAnyWithValue(PKs[0]) - assert.NilError(t, err) - - bondedVal := types.Validator{ - OperatorAddress: sdk.ValAddress(addrs[0]).String(), - ConsensusPubkey: pk0, - Status: types.Bonded, - Tokens: valTokens, - DelegatorShares: math.LegacyNewDecFromInt(valTokens), - Description: types.NewDescription("hoop", "", "", "", "", &types.Metadata{}), - } - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, bondedVal)) - - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - - validators, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) - assert.NilError(t, err) - - assert.Assert(t, len(validators) == 1) - var delegations []types.Delegation - - pk1, err := codectypes.NewAnyWithValue(PKs[1]) - assert.NilError(t, err) - - pk2, err := codectypes.NewAnyWithValue(PKs[2]) - assert.NilError(t, err) - - // initialize the validators - bondedVal1 := types.Validator{ - OperatorAddress: sdk.ValAddress(addrs[1]).String(), - ConsensusPubkey: pk1, - Status: types.Bonded, - Tokens: valTokens, - DelegatorShares: math.LegacyNewDecFromInt(valTokens), - Description: types.NewDescription("hoop", "", "", "", "", &types.Metadata{}), - } - bondedVal2 := types.Validator{ - OperatorAddress: sdk.ValAddress(addrs[2]).String(), - ConsensusPubkey: pk2, - Status: types.Bonded, - Tokens: valTokens, - DelegatorShares: math.LegacyNewDecFromInt(valTokens), - Description: types.NewDescription("bloop", "", "", "", "", &types.Metadata{}), - } - - // append new bonded validators to the list - validators = append(validators, bondedVal1, bondedVal2) - - // mint coins in the bonded pool representing the validators coins - i2 := len(validators) - assert.NilError(t, - banktestutil.FundModuleAccount( - f.sdkCtx, - f.bankKeeper, - types.BondedPoolName, - sdk.NewCoins( - sdk.NewCoin(params.BondDenom, valTokens.MulRaw((int64)(i2))), - ), - ), - ) - - genesisDelegations, err := f.stakingKeeper.GetAllDelegations(f.sdkCtx) - assert.NilError(t, err) - delegations = append(delegations, genesisDelegations...) - - genesisState := types.NewGenesisState(params, validators, delegations) - vals, err := (f.stakingKeeper.InitGenesis(f.sdkCtx, genesisState)) - assert.NilError(t, err) - - actualGenesis, err := (f.stakingKeeper.ExportGenesis(f.sdkCtx)) - assert.NilError(t, err) - assert.DeepEqual(t, genesisState.Params, actualGenesis.Params) - assert.DeepEqual(t, genesisState.Delegations, actualGenesis.Delegations) - - allvals, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) - assert.NilError(t, err) - assert.DeepEqual(t, allvals, actualGenesis.Validators) - - // Ensure validators have addresses. - vals2, err := staking.WriteValidators(f.sdkCtx, (f.stakingKeeper)) - assert.NilError(t, err) - - for _, val := range vals2 { - assert.Assert(t, val.Address.String() != "") - } - - // now make sure the validators are bonded and intra-tx counters are correct - resVal, found := (f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[1]))) - assert.Assert(t, found) - assert.Equal(t, types.Bonded, resVal.Status) - - resVal, found = (f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[2]))) - assert.Assert(t, found) - assert.Equal(t, types.Bonded, resVal.Status) - - validatorUpdates := make([]appmodule.ValidatorUpdate, len(vals)) - for i, val := range validators { - validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)) - } - assert.DeepEqual(t, validatorUpdates, vals) -} - -func TestInitGenesis_PoolsBalanceMismatch(t *testing.T) { - t.Parallel() - f := initFixture(t) - - consPub, err := codectypes.NewAnyWithValue(PKs[0]) - assert.NilError(t, err) - - validator := types.Validator{ - OperatorAddress: sdk.ValAddress("12345678901234567890").String(), - ConsensusPubkey: consPub, - Jailed: false, - Tokens: math.NewInt(10), - DelegatorShares: math.LegacyNewDecFromInt(math.NewInt(10)), - Description: types.NewDescription("bloop", "", "", "", "", &types.Metadata{}), - } - - params := types.Params{ - UnbondingTime: 10000, - MaxValidators: 1, - MaxEntries: 10, - BondDenom: "stake", - } - - // setting validator status to bonded so the balance counts towards bonded pool - validator.Status = types.Bonded - _, err = f.stakingKeeper.InitGenesis(f.sdkCtx, &types.GenesisState{ - Params: params, - Validators: []types.Validator{validator}, - }) - // "should error because bonded pool balance is different from bonded pool coins", - require.NotNil(t, err) - - // setting validator status to unbonded so the balance counts towards not bonded pool - validator.Status = types.Unbonded - _, err = f.stakingKeeper.InitGenesis(f.sdkCtx, &types.GenesisState{ - Params: params, - Validators: []types.Validator{validator}, - }) - // "should panic because not bonded pool balance is different from not bonded pool coins", - require.NotNil(t, err) -} - -func TestInitGenesisLargeValidatorSet(t *testing.T) { - size := 200 - assert.Assert(t, size > 100) - - f, addrs := bootstrapGenesisTest(t, 200) - genesisValidators, err := f.stakingKeeper.GetAllValidators(f.sdkCtx) - assert.NilError(t, err) - - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - delegations := []types.Delegation{} - validators := make([]types.Validator, size) - - bondedPoolAmt := math.ZeroInt() - for i := range validators { - validators[i], err = types.NewValidator( - sdk.ValAddress(addrs[i]).String(), - PKs[i], - types.NewDescription(fmt.Sprintf("#%d", i), "", "", "", "", &types.Metadata{}), - ) - assert.NilError(t, err) - validators[i].Status = types.Bonded - - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) - if i < 100 { - tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 2) - } - - validators[i].Tokens = tokens - validators[i].DelegatorShares = math.LegacyNewDecFromInt(tokens) - - // add bonded coins - bondedPoolAmt = bondedPoolAmt.Add(tokens) - } - - validators = append(validators, genesisValidators...) - genesisState := types.NewGenesisState(params, validators, delegations) - - // mint coins in the bonded pool representing the validators coins - assert.NilError(t, - banktestutil.FundModuleAccount( - f.sdkCtx, - f.bankKeeper, - types.BondedPoolName, - sdk.NewCoins(sdk.NewCoin(params.BondDenom, bondedPoolAmt)), - ), - ) - - vals, err := f.stakingKeeper.InitGenesis(f.sdkCtx, genesisState) - assert.NilError(t, err) - - validatorUpdates := make([]module.ValidatorUpdate, 100) - for i, val := range validators[:100] { - validatorUpdates[i] = val.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)) - } - // remove genesis validator - vals = vals[:100] - assert.DeepEqual(t, validatorUpdates, vals) -} diff --git a/tests/integration/staking/keeper/grpc_query_test.go b/tests/integration/staking/keeper/grpc_query_test.go deleted file mode 100644 index a7fb3520973a..000000000000 --- a/tests/integration/staking/keeper/grpc_query_test.go +++ /dev/null @@ -1,915 +0,0 @@ -package keeper_test - -import ( - gocontext "context" - "fmt" - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/collections" - "cosmossdk.io/math" - "cosmossdk.io/x/staking/types" - - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/query" -) - -func createValidatorAccs(t *testing.T, f *fixture) ([]sdk.AccAddress, []types.Validator) { - t.Helper() - addrs, _, validators := createValidators(&testing.T{}, f, []int64{9, 8, 7}) - - // sort a copy of the validators, so that original validators does not - // have its order changed - sortedVals := make([]types.Validator, len(validators)) - copy(sortedVals, validators) - - return addrs, validators -} - -func TestGRPCQueryValidators(t *testing.T) { - t.Parallel() - f := initFixture(t) - - _, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - var req *types.QueryValidatorsRequest - testCases := []struct { - msg string - malleate func() - expPass bool - numVals int - hasNext bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryValidatorsRequest{} - }, - true, - len(vals), - false, - "", - }, - { - "empty status returns all the validators", - func() { - req = &types.QueryValidatorsRequest{Status: ""} - }, - true, - len(vals), - false, - "", - }, - { - "invalid request", - func() { - req = &types.QueryValidatorsRequest{Status: "test"} - }, - false, - 0, - false, - "invalid validator status test", - }, - { - "valid request", - func() { - req = &types.QueryValidatorsRequest{ - Status: types.Bonded.String(), - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - true, - 1, - true, - "", - }, - } - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - valsResp, err := queryClient.Validators(gocontext.Background(), req) - if tc.expPass { - assert.NilError(t, err) - assert.Assert(t, valsResp != nil) - assert.Equal(t, tc.numVals, len(valsResp.Validators)) - assert.Equal(t, uint64(len(vals)), valsResp.Pagination.Total) - - if tc.hasNext { - assert.Assert(t, valsResp.Pagination.NextKey != nil) - } else { - assert.Assert(t, valsResp.Pagination.NextKey == nil) - } - } else { - assert.ErrorContains(t, err, tc.expErrMsg) - } - }) - } -} - -func TestGRPCQueryDelegatorValidators(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - addrs, _ := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - params, err := f.stakingKeeper.Params.Get(ctx) - assert.NilError(t, err) - delValidators, err := f.stakingKeeper.GetDelegatorValidators(ctx, addrs[0], params.MaxValidators) - assert.NilError(t, err) - var req *types.QueryDelegatorValidatorsRequest - testCases := []struct { - msg string - malleate func() - expPass bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryDelegatorValidatorsRequest{} - }, - false, - "delegator address cannot be empty", - }, - { - "invalid delegator address", - func() { - req = &types.QueryDelegatorValidatorsRequest{ - DelegatorAddr: "invalid", - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - false, - "invalid bech32", - }, - { - "valid request", - func() { - req = &types.QueryDelegatorValidatorsRequest{ - DelegatorAddr: addrs[0].String(), - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - true, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.DelegatorValidators(gocontext.Background(), req) - if tc.expPass { - assert.NilError(t, err) - assert.Equal(t, 1, len(res.Validators)) - assert.Assert(t, res.Pagination.NextKey != nil) - assert.Equal(t, uint64(len(delValidators.Validators)), res.Pagination.Total) - } else { - assert.ErrorContains(t, err, tc.expErrMsg) - assert.Assert(t, res == nil) - } - }) - } -} - -func TestGRPCQueryDelegatorValidator(t *testing.T) { - t.Parallel() - f := initFixture(t) - - addrs, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - addr := addrs[1] - addrVal, addrVal1 := vals[0].OperatorAddress, vals[1].OperatorAddress - var req *types.QueryDelegatorValidatorRequest - testCases := []struct { - msg string - malleate func() - expPass bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryDelegatorValidatorRequest{} - }, - false, - "delegator address cannot be empty", - }, - { - "invalid delegator, validator pair", - func() { - req = &types.QueryDelegatorValidatorRequest{ - DelegatorAddr: addr.String(), - ValidatorAddr: addrVal, - } - }, - false, - "not found", - }, - { - "empty delegator address", - func() { - req = &types.QueryDelegatorValidatorRequest{ - DelegatorAddr: "", - ValidatorAddr: addrVal1, - } - }, - false, - "delegator address cannot be empty", - }, - { - "empty validator address", - func() { - req = &types.QueryDelegatorValidatorRequest{ - DelegatorAddr: addr.String(), - ValidatorAddr: "", - } - }, - false, - "validator address cannot be empty", - }, - { - "valid request", - func() { - req = &types.QueryDelegatorValidatorRequest{ - DelegatorAddr: addr.String(), - ValidatorAddr: addrVal1, - } - }, - true, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.DelegatorValidator(gocontext.Background(), req) - if tc.expPass { - assert.NilError(t, err) - assert.Equal(t, addrVal1, res.Validator.OperatorAddress) - } else { - assert.ErrorContains(t, err, tc.expErrMsg) - assert.Assert(t, res == nil) - } - }) - } -} - -func TestGRPCQueryDelegation(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - addrs, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - addrAcc, addrAcc1 := addrs[0], addrs[1] - addrVal := vals[0].OperatorAddress - valAddr, err := sdk.ValAddressFromBech32(addrVal) - assert.NilError(t, err) - delegation, found := f.stakingKeeper.Delegations.Get(ctx, collections.Join(addrAcc, valAddr)) - assert.Assert(t, found) - var req *types.QueryDelegationRequest - - testCases := []struct { - msg string - malleate func() - expPass bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryDelegationRequest{} - }, - false, - "delegator address cannot be empty", - }, - { - "invalid validator, delegator pair", - func() { - req = &types.QueryDelegationRequest{ - DelegatorAddr: addrAcc1.String(), - ValidatorAddr: addrVal, - } - }, - false, - fmt.Sprintf("delegation with delegator %s not found for validator %s", addrAcc1.String(), addrVal), - }, - { - "valid request", - func() { - req = &types.QueryDelegationRequest{DelegatorAddr: addrAcc.String(), ValidatorAddr: addrVal} - }, - true, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.Delegation(gocontext.Background(), req) - if tc.expPass { - assert.Equal(t, delegation.ValidatorAddress, res.DelegationResponse.Delegation.ValidatorAddress) - assert.Equal(t, delegation.DelegatorAddress, res.DelegationResponse.Delegation.DelegatorAddress) - assert.DeepEqual(t, sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponse.Balance) - } else { - assert.ErrorContains(t, err, tc.expErrMsg) - assert.Assert(t, res == nil) - } - }) - } -} - -func TestGRPCQueryDelegatorDelegations(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - addrs, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - addrAcc := addrs[0] - addrVal1 := vals[0].OperatorAddress - valAddr, err := sdk.ValAddressFromBech32(addrVal1) - assert.NilError(t, err) - delegation, found := f.stakingKeeper.Delegations.Get(ctx, collections.Join(addrAcc, valAddr)) - assert.Assert(t, found) - var req *types.QueryDelegatorDelegationsRequest - - testCases := []struct { - msg string - malleate func() - onSuccess func(response *types.QueryDelegatorDelegationsResponse) - expErr bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryDelegatorDelegationsRequest{} - }, - func(response *types.QueryDelegatorDelegationsResponse) {}, - true, - "delegator address cannot be empty", - }, - { - "valid request with no delegations", - func() { - req = &types.QueryDelegatorDelegationsRequest{DelegatorAddr: addrs[4].String()} - }, - func(response *types.QueryDelegatorDelegationsResponse) { - assert.Equal(t, uint64(0), response.Pagination.Total) - assert.Assert(t, len(response.DelegationResponses) == 0) - }, - false, - "", - }, - { - "valid request", - func() { - req = &types.QueryDelegatorDelegationsRequest{ - DelegatorAddr: addrAcc.String(), - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - func(response *types.QueryDelegatorDelegationsResponse) { - assert.Equal(t, uint64(2), response.Pagination.Total) - assert.Assert(t, len(response.DelegationResponses) == 1) - assert.DeepEqual(t, sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), response.DelegationResponses[0].Balance) - }, - false, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.DelegatorDelegations(gocontext.Background(), req) - if tc.expErr { - assert.ErrorContains(t, err, tc.expErrMsg) - } else { - assert.NilError(t, err) - tc.onSuccess(res) - } - }) - } -} - -func TestGRPCQueryValidatorDelegations(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - addrs, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - addrAcc := addrs[0] - addrVal1 := vals[1].OperatorAddress - valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) - addrVal2 := valAddrs[4] - valAddr, err := sdk.ValAddressFromBech32(addrVal1) - assert.NilError(t, err) - delegation, found := f.stakingKeeper.Delegations.Get(ctx, collections.Join(addrAcc, valAddr)) - assert.Assert(t, found) - - var req *types.QueryValidatorDelegationsRequest - testCases := []struct { - msg string - malleate func() - expPass bool - expErr bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryValidatorDelegationsRequest{} - }, - false, - true, - "validator address cannot be empty", - }, - { - "invalid validator address", - func() { - req = &types.QueryValidatorDelegationsRequest{ValidatorAddr: addrVal2.String()} - }, - false, - false, - "", - }, - { - "valid request", - func() { - req = &types.QueryValidatorDelegationsRequest{ - ValidatorAddr: addrVal1, - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - true, - false, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.ValidatorDelegations(gocontext.Background(), req) - switch { - case tc.expPass && !tc.expErr: - assert.NilError(t, err) - assert.Assert(t, len(res.DelegationResponses) == 1) - assert.Assert(t, res.Pagination.NextKey != nil) - assert.Equal(t, uint64(2), res.Pagination.Total) - assert.Equal(t, addrVal1, res.DelegationResponses[0].Delegation.ValidatorAddress) - assert.DeepEqual(t, sdk.NewCoin(sdk.DefaultBondDenom, delegation.Shares.TruncateInt()), res.DelegationResponses[0].Balance) - case !tc.expPass && !tc.expErr: - assert.NilError(t, err) - assert.Assert(t, res.DelegationResponses == nil) - default: - assert.ErrorContains(t, err, tc.expErrMsg) - assert.Assert(t, res == nil) - } - }) - } -} - -func TestGRPCQueryUnbondingDelegation(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - addrs, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - addrAcc2 := addrs[1] - addrVal2 := vals[1].OperatorAddress - - unbondingTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 2) - valAddr, err1 := sdk.ValAddressFromBech32(addrVal2) - assert.NilError(t, err1) - _, _, err := f.stakingKeeper.Undelegate(ctx, addrAcc2, valAddr, math.LegacyNewDecFromInt(unbondingTokens)) - assert.NilError(t, err) - - unbond, found := f.stakingKeeper.GetUnbondingDelegation(ctx, addrAcc2, valAddr) - assert.Assert(t, found) - var req *types.QueryUnbondingDelegationRequest - testCases := []struct { - msg string - malleate func() - expPass bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryUnbondingDelegationRequest{} - }, - false, - "delegator address cannot be empty", - }, - { - "empty validator address", - func() { - req = &types.QueryUnbondingDelegationRequest{ - DelegatorAddr: addrAcc2.String(), - } - }, - false, - "validator address cannot be empty", - }, - { - "empty delegator address", - func() { - req = &types.QueryUnbondingDelegationRequest{ - ValidatorAddr: addrVal2, - } - }, - false, - "delegator address cannot be empty", - }, - { - "invalid validator address", - func() { - req = &types.QueryUnbondingDelegationRequest{ - DelegatorAddr: addrAcc2.String(), ValidatorAddr: sdk.AccAddress([]byte("invalid")).String(), - } - }, - false, - "hrp does not match bech32 prefix", - }, - { - "delegation not found for validator", - func() { - req = &types.QueryUnbondingDelegationRequest{ - DelegatorAddr: addrAcc2.String(), ValidatorAddr: sdk.ValAddress([]byte("invalid")).String(), - } - }, - false, - fmt.Sprintf("unbonding delegation with delegator %s not found for validator", addrAcc2.String()), - }, - { - "valid request", - func() { - req = &types.QueryUnbondingDelegationRequest{ - DelegatorAddr: addrAcc2.String(), ValidatorAddr: addrVal2, - } - }, - true, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.UnbondingDelegation(gocontext.Background(), req) - if tc.expPass { - assert.Assert(t, res != nil) - assert.DeepEqual(t, unbond, res.Unbond) - } else { - assert.ErrorContains(t, err, tc.expErrMsg) - assert.Assert(t, res == nil) - } - }) - } -} - -func TestGRPCQueryDelegatorUnbondingDelegations(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - addrs, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - addrAcc, addrAcc1 := addrs[0], addrs[1] - addrVal, addrVal2 := vals[0].OperatorAddress, vals[1].OperatorAddress - - unbondingTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 2) - valAddr1, err1 := sdk.ValAddressFromBech32(addrVal) - assert.NilError(t, err1) - _, _, err := f.stakingKeeper.Undelegate(ctx, addrAcc, valAddr1, math.LegacyNewDecFromInt(unbondingTokens)) - assert.NilError(t, err) - valAddr2, err1 := sdk.ValAddressFromBech32(addrVal2) - assert.NilError(t, err1) - _, _, err = f.stakingKeeper.Undelegate(ctx, addrAcc, valAddr2, math.LegacyNewDecFromInt(unbondingTokens)) - assert.NilError(t, err) - - unbond, found := f.stakingKeeper.GetUnbondingDelegation(ctx, addrAcc, valAddr1) - assert.Assert(t, found) - var req *types.QueryDelegatorUnbondingDelegationsRequest - testCases := []struct { - msg string - malleate func() - expPass bool - expErr bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryDelegatorUnbondingDelegationsRequest{} - }, - false, - true, - "delegator address cannot be empty", - }, - { - "invalid request", - func() { - req = &types.QueryDelegatorUnbondingDelegationsRequest{DelegatorAddr: addrAcc1.String()} - }, - false, - false, - "", - }, - { - "valid request", - func() { - req = &types.QueryDelegatorUnbondingDelegationsRequest{ - DelegatorAddr: addrAcc.String(), - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - true, - false, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.DelegatorUnbondingDelegations(gocontext.Background(), req) - switch { - case tc.expPass && !tc.expErr: - assert.NilError(t, err) - assert.Assert(t, res.Pagination.NextKey != nil) - assert.Equal(t, uint64(2), res.Pagination.Total) - assert.Assert(t, len(res.UnbondingResponses) == 1) - assert.DeepEqual(t, unbond, res.UnbondingResponses[0]) - case !tc.expPass && !tc.expErr: - assert.NilError(t, err) - assert.Assert(t, res.UnbondingResponses == nil) - default: - assert.ErrorContains(t, err, tc.expErrMsg) - assert.Assert(t, res == nil) - } - }) - } -} - -func TestGRPCQueryPoolParameters(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - bondDenom := sdk.DefaultBondDenom - - // Query pool - res, err := queryClient.Pool(gocontext.Background(), &types.QueryPoolRequest{}) - assert.NilError(t, err) - bondedPool := f.stakingKeeper.GetBondedPool(ctx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx) - assert.DeepEqual(t, f.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom).Amount, res.Pool.NotBondedTokens) - assert.DeepEqual(t, f.bankKeeper.GetBalance(ctx, bondedPool.GetAddress(), bondDenom).Amount, res.Pool.BondedTokens) - - // Query Params - resp, err := queryClient.Params(gocontext.Background(), &types.QueryParamsRequest{}) - assert.NilError(t, err) - params, err := f.stakingKeeper.Params.Get(ctx) - assert.NilError(t, err) - assert.DeepEqual(t, params, resp.Params) -} - -func TestGRPCQueryRedelegations(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - addrs, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - addrAcc, addrAcc1 := addrs[0], addrs[1] - valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) - val1, val2, val3, val4 := vals[0], vals[1], valAddrs[3], valAddrs[4] - delAmount := f.stakingKeeper.TokensFromConsensusPower(ctx, 1) - _, err := f.stakingKeeper.Delegate(ctx, addrAcc1, delAmount, types.Unbonded, val1, true) - assert.NilError(t, err) - applyValidatorSetUpdates(t, ctx, f.stakingKeeper, -1) - - rdAmount := f.stakingKeeper.TokensFromConsensusPower(ctx, 1) - val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(val1.GetOperator()) - assert.NilError(t, err) - val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(val2.GetOperator()) - assert.NilError(t, err) - - _, err = f.stakingKeeper.BeginRedelegation(ctx, addrAcc1, val1bz, val2bz, math.LegacyNewDecFromInt(rdAmount)) - assert.NilError(t, err) - applyValidatorSetUpdates(t, ctx, f.stakingKeeper, -1) - - redel, found := f.stakingKeeper.Redelegations.Get(ctx, collections.Join3(addrAcc1.Bytes(), valAddrs[0].Bytes(), valAddrs[1].Bytes())) - assert.Assert(t, found) - - var req *types.QueryRedelegationsRequest - testCases := []struct { - msg string - malleate func() - expPass bool - expErr bool - expErrMsg string - }{ - { - "request redelegations for non existent addr", - func() { - req = &types.QueryRedelegationsRequest{DelegatorAddr: addrAcc.String()} - }, - false, - false, - fmt.Sprintf("redelegation not found for delegator address %s", addrAcc.String()), - }, - { - "request redelegations with non existent pairs", - func() { - req = &types.QueryRedelegationsRequest{ - DelegatorAddr: addrAcc.String(), SrcValidatorAddr: val3.String(), - DstValidatorAddr: val4.String(), - } - }, - false, - true, - fmt.Sprintf("redelegation not found for delegator address %s from validator address %s", - addrAcc.String(), val3.String()), - }, - { - "request redelegations with delegatoraddr, sourceValAddr, destValAddr", - func() { - req = &types.QueryRedelegationsRequest{ - DelegatorAddr: addrAcc1.String(), SrcValidatorAddr: val1.OperatorAddress, - DstValidatorAddr: val2.OperatorAddress, Pagination: &query.PageRequest{}, - } - }, - true, - false, - "", - }, - { - "request redelegations with delegatoraddr and sourceValAddr", - func() { - req = &types.QueryRedelegationsRequest{ - DelegatorAddr: addrAcc1.String(), SrcValidatorAddr: val1.OperatorAddress, - Pagination: &query.PageRequest{}, - } - }, - true, - false, - "", - }, - { - "query redelegations with sourceValAddr only", - func() { - req = &types.QueryRedelegationsRequest{ - SrcValidatorAddr: val1.GetOperator(), - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - true, - false, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.Redelegations(gocontext.Background(), req) - switch { - case tc.expPass && !tc.expErr: - assert.NilError(t, err) - assert.Assert(t, len(res.RedelegationResponses) == len(redel.Entries)) - assert.Equal(t, redel.DelegatorAddress, res.RedelegationResponses[0].Redelegation.DelegatorAddress) - assert.Equal(t, redel.ValidatorSrcAddress, res.RedelegationResponses[0].Redelegation.ValidatorSrcAddress) - assert.Equal(t, redel.ValidatorDstAddress, res.RedelegationResponses[0].Redelegation.ValidatorDstAddress) - assert.Assert(t, len(redel.Entries) == len(res.RedelegationResponses[0].Entries)) - case !tc.expPass && !tc.expErr: - assert.NilError(t, err) - assert.Assert(t, res.RedelegationResponses == nil) - default: - assert.ErrorContains(t, err, tc.expErrMsg) - assert.Assert(t, res == nil) - } - }) - } -} - -func TestGRPCQueryValidatorUnbondingDelegations(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - addrs, vals := createValidatorAccs(t, f) - - qr := f.app.QueryHelper() - queryClient := types.NewQueryClient(qr) - - addrAcc1, _ := addrs[0], addrs[1] - val1 := vals[0] - - // undelegate - undelAmount := f.stakingKeeper.TokensFromConsensusPower(ctx, 2) - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(val1.GetOperator()) - assert.NilError(t, err) - _, _, err = f.stakingKeeper.Undelegate(ctx, addrAcc1, valbz, math.LegacyNewDecFromInt(undelAmount)) - assert.NilError(t, err) - applyValidatorSetUpdates(t, ctx, f.stakingKeeper, -1) - - var req *types.QueryValidatorUnbondingDelegationsRequest - testCases := []struct { - msg string - malleate func() - expPass bool - expErrMsg string - }{ - { - "empty request", - func() { - req = &types.QueryValidatorUnbondingDelegationsRequest{} - }, - false, - "validator address cannot be empty", - }, - { - "invalid validator address", - func() { - req = &types.QueryValidatorUnbondingDelegationsRequest{ - ValidatorAddr: "invalid", - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - false, - "invalid bech32", - }, - { - "valid request", - func() { - req = &types.QueryValidatorUnbondingDelegationsRequest{ - ValidatorAddr: val1.GetOperator(), - Pagination: &query.PageRequest{Limit: 1, CountTotal: true}, - } - }, - true, - "", - }, - } - - for _, tc := range testCases { - t.Run(fmt.Sprintf("Case %s", tc.msg), func(t *testing.T) { - tc.malleate() - res, err := queryClient.ValidatorUnbondingDelegations(gocontext.Background(), req) - if tc.expPass { - assert.NilError(t, err) - assert.Equal(t, uint64(1), res.Pagination.Total) - assert.Equal(t, 1, len(res.UnbondingResponses)) - assert.Equal(t, res.UnbondingResponses[0].ValidatorAddress, val1.OperatorAddress) - } else { - assert.ErrorContains(t, err, tc.expErrMsg) - assert.Assert(t, res == nil) - } - }) - } -} diff --git a/tests/integration/staking/keeper/msg_server_test.go b/tests/integration/staking/keeper/msg_server_test.go deleted file mode 100644 index cea78ae9f1f7..000000000000 --- a/tests/integration/staking/keeper/msg_server_test.go +++ /dev/null @@ -1,390 +0,0 @@ -package keeper_test - -import ( - "testing" - "time" - - "gotest.tools/v3/assert" - - "cosmossdk.io/core/header" - "cosmossdk.io/math" - "cosmossdk.io/x/bank/testutil" - pooltypes "cosmossdk.io/x/protocolpool/types" - "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/codec/address" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func TestCancelUnbondingDelegation(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - msgServer := keeper.NewMsgServerImpl(f.stakingKeeper) - bondDenom, err := f.stakingKeeper.BondDenom(ctx) - assert.NilError(t, err) - - // set the not bonded pool module account - notBondedPool := f.stakingKeeper.GetNotBondedPool(ctx) - startTokens := f.stakingKeeper.TokensFromConsensusPower(ctx, 5) - - assert.NilError(t, testutil.FundModuleAccount(ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) - f.accountKeeper.SetModuleAccount(ctx, notBondedPool) - - moduleBalance := f.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom) - assert.DeepEqual(t, sdk.NewInt64Coin(bondDenom, startTokens.Int64()), moduleBalance) - - // accounts - addrs := simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, ctx, 2, math.NewInt(10000)) - valAddr := sdk.ValAddress(addrs[0]) - delegatorAddr := addrs[1] - - // setup a new validator with bonded status - validator, err := types.NewValidator(valAddr.String(), PKs[0], types.NewDescription("Validator", "", "", "", "", &types.Metadata{})) - validator.Status = types.Bonded - assert.NilError(t, err) - assert.NilError(t, f.stakingKeeper.SetValidator(ctx, validator)) - - validatorAddr, err := sdk.ValAddressFromBech32(validator.OperatorAddress) - assert.NilError(t, err) - - // setting the ubd entry - unbondingAmount := sdk.NewInt64Coin(bondDenom, 5) - ubd := types.NewUnbondingDelegation( - delegatorAddr, validatorAddr, 10, - ctx.HeaderInfo().Time.Add(time.Minute*10), - unbondingAmount.Amount, - 0, - address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos"), - ) - - // set and retrieve a record - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(ctx, ubd)) - resUnbond, found := f.stakingKeeper.GetUnbondingDelegation(ctx, delegatorAddr, validatorAddr) - assert.Assert(t, found) - assert.DeepEqual(t, ubd, resUnbond) - - testCases := []struct { - name string - exceptErr bool - req types.MsgCancelUnbondingDelegation - expErrMsg string - }{ - { - name: "entry not found at height", - exceptErr: true, - req: types.MsgCancelUnbondingDelegation{ - DelegatorAddress: resUnbond.DelegatorAddress, - ValidatorAddress: resUnbond.ValidatorAddress, - Amount: sdk.NewCoin(bondDenom, math.NewInt(4)), - CreationHeight: 11, - }, - expErrMsg: "unbonding delegation entry is not found at block height", - }, - { - name: "invalid height", - exceptErr: true, - req: types.MsgCancelUnbondingDelegation{ - DelegatorAddress: resUnbond.DelegatorAddress, - ValidatorAddress: resUnbond.ValidatorAddress, - Amount: sdk.NewCoin(bondDenom, math.NewInt(4)), - CreationHeight: 0, - }, - expErrMsg: "invalid height", - }, - { - name: "invalid coin", - exceptErr: true, - req: types.MsgCancelUnbondingDelegation{ - DelegatorAddress: resUnbond.DelegatorAddress, - ValidatorAddress: resUnbond.ValidatorAddress, - Amount: sdk.NewCoin("dump_coin", math.NewInt(4)), - CreationHeight: 10, - }, - expErrMsg: "invalid coin denomination", - }, - { - name: "validator not exists", - exceptErr: true, - req: types.MsgCancelUnbondingDelegation{ - DelegatorAddress: resUnbond.DelegatorAddress, - ValidatorAddress: sdk.ValAddress(sdk.AccAddress("asdsad")).String(), - Amount: unbondingAmount, - CreationHeight: 10, - }, - expErrMsg: "validator does not exist", - }, - { - name: "invalid delegator address", - exceptErr: true, - req: types.MsgCancelUnbondingDelegation{ - DelegatorAddress: "invalid_delegator_addrtess", - ValidatorAddress: resUnbond.ValidatorAddress, - Amount: unbondingAmount, - CreationHeight: 0, - }, - expErrMsg: "decoding bech32 failed", - }, - { - name: "invalid amount", - exceptErr: true, - req: types.MsgCancelUnbondingDelegation{ - DelegatorAddress: resUnbond.DelegatorAddress, - ValidatorAddress: resUnbond.ValidatorAddress, - Amount: unbondingAmount.Add(sdk.NewInt64Coin(bondDenom, 10)), - CreationHeight: 10, - }, - expErrMsg: "amount is greater than the unbonding delegation entry balance", - }, - { - name: "success", - exceptErr: false, - req: types.MsgCancelUnbondingDelegation{ - DelegatorAddress: resUnbond.DelegatorAddress, - ValidatorAddress: resUnbond.ValidatorAddress, - Amount: unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1)), - CreationHeight: 10, - }, - }, - { - name: "success", - exceptErr: false, - req: types.MsgCancelUnbondingDelegation{ - DelegatorAddress: resUnbond.DelegatorAddress, - ValidatorAddress: resUnbond.ValidatorAddress, - Amount: unbondingAmount.Sub(unbondingAmount.Sub(sdk.NewInt64Coin(bondDenom, 1))), - CreationHeight: 10, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - _, err := msgServer.CancelUnbondingDelegation(ctx, &tc.req) - if tc.exceptErr { - assert.ErrorContains(t, err, tc.expErrMsg) - } else { - assert.NilError(t, err) - balanceForNotBondedPool := f.bankKeeper.GetBalance(ctx, notBondedPool.GetAddress(), bondDenom) - assert.DeepEqual(t, balanceForNotBondedPool, moduleBalance.Sub(tc.req.Amount)) - moduleBalance = moduleBalance.Sub(tc.req.Amount) - } - }) - } -} - -func TestRotateConsPubKey(t *testing.T) { - t.Parallel() - f := initFixture(t) - - ctx := f.sdkCtx - stakingKeeper := f.stakingKeeper - bankKeeper := f.bankKeeper - accountKeeper := f.accountKeeper - - msgServer := keeper.NewMsgServerImpl(stakingKeeper) - bondDenom, err := stakingKeeper.BondDenom(ctx) - assert.NilError(t, err) - - params, err := stakingKeeper.Params.Get(ctx) - assert.NilError(t, err) - - params.KeyRotationFee = sdk.NewInt64Coin(bondDenom, 10) - err = stakingKeeper.Params.Set(ctx, params) - assert.NilError(t, err) - - addrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 5, stakingKeeper.TokensFromConsensusPower(ctx, 100)) - valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) - - // create 5 validators - for i := 0; i < 5; i++ { - comm := types.NewCommissionRates(math.LegacyNewDec(0), math.LegacyNewDec(0), math.LegacyNewDec(0)) - acc := f.accountKeeper.NewAccountWithAddress(ctx, sdk.AccAddress(valAddrs[i])) - f.accountKeeper.SetAccount(ctx, acc) - msg, err := types.NewMsgCreateValidator(valAddrs[i].String(), PKs[i], sdk.NewCoin(sdk.DefaultBondDenom, stakingKeeper.TokensFromConsensusPower(ctx, 30)), - types.Description{Moniker: "NewVal"}, comm, math.OneInt()) - assert.NilError(t, err) - _, err = msgServer.CreateValidator(ctx, msg) - assert.NilError(t, err) - } - - // call endblocker to update the validator state - _, err = stakingKeeper.EndBlocker(ctx.WithBlockHeight(ctx.BlockHeader().Height + 1)) - assert.NilError(t, err) - - params, err = stakingKeeper.Params.Get(ctx) - assert.NilError(t, err) - - validators, err := stakingKeeper.GetAllValidators(ctx) - assert.NilError(t, err) - assert.Equal(t, len(validators) >= 5, true) - - testCases := []struct { - name string - malleate func() sdk.Context - pass bool - validator string - newPubKey cryptotypes.PubKey - expErrMsg string - expHistoryObjs int - fees sdk.Coin - }{ - { - name: "successful consensus pubkey rotation", - malleate: func() sdk.Context { - return ctx - }, - validator: validators[0].GetOperator(), - newPubKey: PKs[499], - pass: true, - expHistoryObjs: 1, - fees: params.KeyRotationFee, - }, - { - name: "non existing validator check", - malleate: func() sdk.Context { - return ctx - }, - validator: sdk.ValAddress("non_existing_val").String(), - newPubKey: PKs[498], - pass: false, - expErrMsg: "validator does not exist", - }, - { - name: "pubkey already associated with another validator", - malleate: func() sdk.Context { - return ctx - }, - validator: validators[0].GetOperator(), - newPubKey: validators[1].ConsensusPubkey.GetCachedValue().(cryptotypes.PubKey), - pass: false, - expErrMsg: "validator already exist for this pubkey; must use new validator pubkey", - }, - { - name: "consensus pubkey rotation limit check", - malleate: func() sdk.Context { - params, err := stakingKeeper.Params.Get(ctx) - assert.NilError(t, err) - - params.KeyRotationFee = sdk.NewInt64Coin(bondDenom, 10) - err = stakingKeeper.Params.Set(ctx, params) - assert.NilError(t, err) - - msg, err := types.NewMsgRotateConsPubKey( - validators[1].GetOperator(), - PKs[498], - ) - assert.NilError(t, err) - _, err = msgServer.RotateConsPubKey(ctx, msg) - assert.NilError(t, err) - - return ctx - }, - validator: validators[1].GetOperator(), - newPubKey: PKs[497], - pass: false, - expErrMsg: "exceeding maximum consensus pubkey rotations within unbonding period", - }, - { - name: "limit reached, but should rotate after the unbonding period", - malleate: func() sdk.Context { - params, err := stakingKeeper.Params.Get(ctx) - assert.NilError(t, err) - - params.KeyRotationFee = sdk.NewInt64Coin(bondDenom, 10) - err = stakingKeeper.Params.Set(ctx, params) - assert.NilError(t, err) - - msg, err := types.NewMsgRotateConsPubKey( - validators[3].GetOperator(), - PKs[495], - ) - - assert.NilError(t, err) - _, err = msgServer.RotateConsPubKey(ctx, msg) - assert.NilError(t, err) - ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) - - // this shouldn't remove the existing keys from waiting queue since unbonding time isn't reached - _, err = stakingKeeper.EndBlocker(ctx) - assert.NilError(t, err) - - msg, err = types.NewMsgRotateConsPubKey( - validators[3].GetOperator(), - PKs[494], - ) - - assert.NilError(t, err) - _, err = msgServer.RotateConsPubKey(ctx, msg) - assert.Error(t, err, "exceeding maximum consensus pubkey rotations within unbonding period") - - ctx = ctx.WithBlockHeight(ctx.BlockHeight() + 1) - - newCtx := ctx.WithHeaderInfo(header.Info{Height: ctx.BlockHeight() + 1, Time: ctx.HeaderInfo().Time.Add(params.UnbondingTime)}).WithBlockHeight(ctx.BlockHeight() + 1) - // this should remove keys from waiting queue since unbonding time is reached - _, err = stakingKeeper.EndBlocker(newCtx) - assert.NilError(t, err) - - return newCtx - }, - validator: validators[3].GetOperator(), - newPubKey: PKs[494], - pass: true, - expErrMsg: "", - expHistoryObjs: 2, - fees: params.KeyRotationFee, - }, - } - - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - newCtx := testCase.malleate() - oldDistrBalance := bankKeeper.GetBalance(newCtx, accountKeeper.GetModuleAddress(pooltypes.ModuleName), bondDenom) - msg, err := types.NewMsgRotateConsPubKey( - testCase.validator, - testCase.newPubKey, - ) - assert.NilError(t, err) - - _, err = msgServer.RotateConsPubKey(newCtx, msg) - - if testCase.pass { - assert.NilError(t, err) - - _, err = stakingKeeper.EndBlocker(newCtx) - assert.NilError(t, err) - - // rotation fee payment from sender to distrtypes - newDistrBalance := bankKeeper.GetBalance(newCtx, accountKeeper.GetModuleAddress(pooltypes.ModuleName), bondDenom) - assert.DeepEqual(t, newDistrBalance, oldDistrBalance.Add(testCase.fees)) - - valBytes, err := stakingKeeper.ValidatorAddressCodec().StringToBytes(testCase.validator) - assert.NilError(t, err) - - // validator consensus pubkey update check - validator, err := stakingKeeper.GetValidator(newCtx, valBytes) - assert.NilError(t, err) - - consAddr, err := validator.GetConsAddr() - assert.NilError(t, err) - assert.DeepEqual(t, consAddr, testCase.newPubKey.Address().Bytes()) - - // consensus rotation history set check - historyObjects, err := stakingKeeper.GetValidatorConsPubKeyRotationHistory(newCtx, valBytes) - assert.NilError(t, err) - assert.Equal(t, len(historyObjects), testCase.expHistoryObjs) - - historyObjects, err = stakingKeeper.GetBlockConsPubKeyRotationHistory(newCtx) - assert.NilError(t, err) - assert.Equal(t, len(historyObjects), 1) - - } else { - assert.ErrorContains(t, err, testCase.expErrMsg) - } - }) - } -} diff --git a/tests/integration/staking/keeper/slash_test.go b/tests/integration/staking/keeper/slash_test.go deleted file mode 100644 index f9620b9e05cc..000000000000 --- a/tests/integration/staking/keeper/slash_test.go +++ /dev/null @@ -1,767 +0,0 @@ -package keeper_test - -import ( - "context" - "testing" - "time" - - "github.com/stretchr/testify/require" - "gotest.tools/v3/assert" - - "cosmossdk.io/collections" - "cosmossdk.io/core/header" - "cosmossdk.io/depinject" - "cosmossdk.io/log" - "cosmossdk.io/math" - _ "cosmossdk.io/x/accounts" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktestutil "cosmossdk.io/x/bank/testutil" - _ "cosmossdk.io/x/consensus" - _ "cosmossdk.io/x/distribution" - distributionkeeper "cosmossdk.io/x/distribution/keeper" - _ "cosmossdk.io/x/protocolpool" - _ "cosmossdk.io/x/slashing" - slashingkeeper "cosmossdk.io/x/slashing/keeper" - "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/testutil" - "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/codec/address" - "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" - "github.com/cosmos/cosmos-sdk/testutil/configurator" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" -) - -// bootstrapSlashTest creates 3 validators and bootstrap the app. -func bootstrapSlashTest(t *testing.T, power int64) (*fixture, []sdk.AccAddress, []sdk.ValAddress) { - t.Helper() - t.Parallel() - f := initFixture(t) - - addrDels, addrVals := generateAddresses(f, 100) - - amt := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - require.NoError(t, err) - totalSupply := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(int64(len(addrDels))))) - - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), totalSupply)) - - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - - numVals := int64(3) - bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(numVals))) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - - // set bonded pool balance - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), bondedCoins)) - - for i := int64(0); i < numVals; i++ { - validator := testutil.NewValidator(t, addrVals[i], PKs[i]) - validator, _ = validator.AddTokensFromDel(amt) - validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator, true) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, validator)) - } - - return f, addrDels, addrVals -} - -// tests slashUnbondingDelegation -func TestSlashUnbondingDelegation(t *testing.T) { - f, addrDels, addrVals := bootstrapSlashTest(t, 10) - - fraction := math.LegacyNewDecWithPrec(5, 1) - - // set an unbonding delegation with expiration timestamp (beyond which the - // unbonding delegation shouldn't be slashed) - ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 0, - time.Unix(5, 0), math.NewInt(10), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) - - // unbonding started prior to the infraction height, stakw didn't contribute - slashAmount, err := f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 1, fraction) - assert.NilError(t, err) - assert.Assert(t, slashAmount.Equal(math.NewInt(0))) - - // after the expiration time, no longer eligible for slashing - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(10, 0)}) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) - slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction) - assert.NilError(t, err) - assert.Assert(t, slashAmount.Equal(math.NewInt(0))) - - // test valid slash, before expiration timestamp and to which stake contributed - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - oldUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, notBondedPool.GetAddress()) - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(0, 0)}) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) - slashAmount, err = f.stakingKeeper.SlashUnbondingDelegation(f.sdkCtx, ubd, 0, fraction) - assert.NilError(t, err) - assert.Assert(t, slashAmount.Equal(math.NewInt(5))) - ubd, found := f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) - assert.Assert(t, found) - assert.Assert(t, len(ubd.Entries) == 1) - - // initial balance unchanged - assert.DeepEqual(t, math.NewInt(10), ubd.Entries[0].InitialBalance) - - // balance decreased - assert.DeepEqual(t, math.NewInt(5), ubd.Entries[0].Balance) - newUnbondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, notBondedPool.GetAddress()) - diffTokens := oldUnbondedPoolBalances.Sub(newUnbondedPoolBalances...) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - assert.Assert(t, diffTokens.AmountOf(bondDenom).Equal(math.NewInt(5))) -} - -// tests slashRedelegation -func TestSlashRedelegation(t *testing.T) { - f, addrDels, addrVals := bootstrapSlashTest(t, 10) - fraction := math.LegacyNewDecWithPrec(5, 1) - - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - - // add bonded tokens to pool for (re)delegations - startCoins := sdk.NewCoins(sdk.NewInt64Coin(bondDenom, 15)) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - _ = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), startCoins)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - - // set a redelegation with an expiration timestamp beyond which the - // redelegation shouldn't be slashed - rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 0, - time.Unix(5, 0), math.NewInt(10), math.LegacyNewDec(10), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) - - // set the associated delegation - del := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDec(10)) - assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, del)) - - // started redelegating prior to the current height, stake didn't contribute to infraction - validator, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) - assert.Assert(t, found) - slashAmount, err := f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 1, fraction) - assert.NilError(t, err) - assert.Assert(t, slashAmount.Equal(math.NewInt(0))) - - // after the expiration time, no longer eligible for slashing - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(10, 0)}) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) - assert.Assert(t, found) - slashAmount, err = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction) - assert.NilError(t, err) - assert.Assert(t, slashAmount.Equal(math.NewInt(0))) - - balances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - - // test valid slash, before expiration timestamp and to which stake contributed - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: time.Unix(0, 0)}) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) - assert.Assert(t, found) - slashAmount, err = f.stakingKeeper.SlashRedelegation(f.sdkCtx, validator, rd, 0, fraction) - assert.NilError(t, err) - assert.Assert(t, slashAmount.Equal(math.NewInt(5))) - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) - assert.Assert(t, found) - assert.Assert(t, len(rd.Entries) == 1) - - // end block - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - - // initialbalance unchanged - assert.DeepEqual(t, math.NewInt(10), rd.Entries[0].InitialBalance) - - // shares decreased - del, found = f.stakingKeeper.Delegations.Get(f.sdkCtx, collections.Join(addrDels[0], addrVals[1])) - assert.Assert(t, found) - assert.Equal(t, int64(5), del.Shares.RoundInt64()) - - // pool bonded tokens should decrease - burnedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, slashAmount)) - assert.DeepEqual(t, balances.Sub(burnedCoins...), f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress())) -} - -// test slash at a negative height -// this just represents pre-genesis and should have the same effect as slashing at height 0 -func TestSlashAtNegativeHeight(t *testing.T) { - f, _, _ := bootstrapSlashTest(t, 10) - consAddr := sdk.ConsAddress(PKs[0].Address()) - fraction := math.LegacyNewDecWithPrec(5, 1) - - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - _, err := f.stakingKeeper.Slash(f.sdkCtx, consAddr, -2, 10, fraction) - assert.NilError(t, err) - - // read updated state - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - - // end block - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - assert.NilError(t, err) - - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) - assert.Assert(t, found) - // power decreased - assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) - - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - - // pool bonded shares decreased - newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 5).String(), diffTokens.String()) -} - -// tests Slash at the current height -func TestSlashValidatorAtCurrentHeight(t *testing.T) { - f, _, _ := bootstrapSlashTest(t, 10) - consAddr := sdk.ConsAddress(PKs[0].Address()) - fraction := math.LegacyNewDecWithPrec(5, 1) - - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction) - assert.NilError(t, err) - - // read updated state - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - - // end block - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - assert.NilError(t, err) - - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) - assert.Assert(t, found) - // power decreased - assert.Equal(t, int64(5), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) - - // pool bonded shares decreased - newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 5).String(), diffTokens.String()) -} - -// TestSlashWithUnbondingDelegation tests the slashing of a validator with an unbonding delegation. -// It sets up an environment with a validator and an unbonding delegation, and then performs slashing -// operations on the validator. The test verifies that the slashing correctly affects the unbonding -// delegation and the validator's power. -func TestSlashWithUnbondingDelegation(t *testing.T) { - f, addrDels, addrVals := bootstrapSlashTest(t, 10) - - consAddr := sdk.ConsAddress(PKs[0].Address()) - fraction := math.LegacyNewDecWithPrec(5, 1) - - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - - // set an unbonding delegation with expiration timestamp beyond which the - // unbonding delegation shouldn't be slashed - ubdTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 4) - ubd := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, time.Unix(0, 0), ubdTokens, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubd)) - - // slash validator for the first time - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Height: 12}) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - oldBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction) - assert.NilError(t, err) - - // end block - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - - // read updating unbonding delegation - ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) - assert.Assert(t, found) - assert.Assert(t, len(ubd.Entries) == 1) - - // balance decreased - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 2), ubd.Entries[0].Balance) - - // bonded tokens burned - newBondedPoolBalances := f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - diffTokens := oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 3), diffTokens) - - // read updated validator - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - - // power decreased by 3 - 6 stake originally bonded at the time of infraction - // was still bonded at the time of discovery and was slashed by half, 4 stake - // bonded at the time of discovery hadn't been bonded at the time of infraction - // and wasn't slashed - assert.Equal(t, int64(7), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) - - // slash validator again - f.sdkCtx = f.sdkCtx.WithBlockHeight(13) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) - assert.NilError(t, err) - - ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) - assert.Assert(t, found) - assert.Assert(t, len(ubd.Entries) == 1) - - // balance decreased again - assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) - - // bonded tokens burned again - newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6), diffTokens) - - // read updated validator - validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - - // power decreased by 3 again - assert.Equal(t, int64(4), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) - - // slash validator again - // all originally bonded stake has been slashed, so this will have no effect - // on the unbonding delegation, but it will slash stake bonded since the infraction - // this may not be the desirable behavior, ref https://github.com/cosmos/cosmos-sdk/issues/1440 - f.sdkCtx = f.sdkCtx.WithBlockHeight(13) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) - assert.NilError(t, err) - - ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) - assert.Assert(t, found) - assert.Assert(t, len(ubd.Entries) == 1) - - // balance unchanged - assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) - - // bonded tokens burned again - newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 9), diffTokens) - - // read updated validator - validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - - // power decreased by 3 again - assert.Equal(t, int64(1), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) - - // slash validator again - // all originally bonded stake has been slashed, so this will have no effect - // on the unbonding delegation, but it will slash stake bonded since the infraction - // this may not be the desirable behavior, ref https://github.com/cosmos/cosmos-sdk/issues/1440 - f.sdkCtx = f.sdkCtx.WithBlockHeight(13) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 9, 10, fraction) - assert.NilError(t, err) - - ubd, found = f.stakingKeeper.GetUnbondingDelegation(f.sdkCtx, addrDels[0], addrVals[0]) - assert.Assert(t, found) - assert.Assert(t, len(ubd.Entries) == 1) - - // balance unchanged - assert.DeepEqual(t, math.NewInt(0), ubd.Entries[0].Balance) - - // just 1 bonded token burned again since that's all the validator now has - newBondedPoolBalances = f.bankKeeper.GetAllBalances(f.sdkCtx, bondedPool.GetAddress()) - diffTokens = oldBondedPoolBalances.Sub(newBondedPoolBalances...).AmountOf(bondDenom) - assert.DeepEqual(t, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10), diffTokens) - - // apply TM updates - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) - - // read updated validator - // power decreased by 1 again, validator is out of stake - // validator should be in unbonding period - validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Equal(t, validator.GetStatus(), sdk.Unbonding) -} - -// tests Slash at a previous height with a redelegation -func TestSlashWithRedelegation(t *testing.T) { - f, addrDels, addrVals := bootstrapSlashTest(t, 10) - consAddr := sdk.ConsAddress(PKs[0].Address()) - fraction := math.LegacyNewDecWithPrec(5, 1) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - - // set a redelegation - rdTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6) - rd := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdTokens, math.LegacyNewDecFromInt(rdTokens), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rd)) - - // set the associated delegation - del := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDecFromInt(rdTokens)) - assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, del)) - - // update bonded tokens - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - rdCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdTokens.MulRaw(2))) - - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), rdCoins)) - - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - - oldBonded := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - oldNotBonded := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount - - // slash validator - f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, fraction) - assert.NilError(t, err) - - burnAmount := math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(fraction).TruncateInt() - - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - // burn bonded tokens from only from delegations - bondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) - - notBondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - - // read updating redelegation - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) - assert.Assert(t, found) - assert.Assert(t, len(rd.Entries) == 1) - // read updated validator - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - // power decreased by 2 - 4 stake originally bonded at the time of infraction - // was still bonded at the time of discovery and was slashed by half, 4 stake - // bonded at the time of discovery hadn't been bonded at the time of infraction - // and wasn't slashed - assert.Equal(t, int64(8), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) - - // slash the validator again - _, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) - assert.NilError(t, err) - burnAmount = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 7) - - // read updated pool - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - // seven bonded tokens burned - bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) - assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - - bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) - - notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - - // read updating redelegation - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) - assert.Assert(t, found) - assert.Assert(t, len(rd.Entries) == 1) - // read updated validator - validator, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - // power decreased by 4 - assert.Equal(t, int64(4), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) - - // slash the validator again, by 100% - f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) - _, found = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Assert(t, found) - - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) - assert.NilError(t, err) - - burnAmount = math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(math.LegacyOneDec()).TruncateInt() - burnAmount = burnAmount.Sub(math.LegacyOneDec().MulInt(rdTokens).TruncateInt()) - - // read updated pool - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldBonded.Sub(burnAmount), bondedPoolBalance)) - notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - oldBonded = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - - // read updating redelegation - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) - assert.Assert(t, found) - assert.Assert(t, len(rd.Entries) == 1) - // apply TM updates - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) - // read updated validator - // validator decreased to zero power, should be in unbonding period - validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Equal(t, validator.GetStatus(), sdk.Unbonding) - - // slash the validator again, by 100% - // no stake remains to be slashed - f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) - // validator still in unbonding period - validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Equal(t, validator.GetStatus(), sdk.Unbonding) - - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr, 10, 10, math.LegacyOneDec()) - assert.NilError(t, err) - - // read updated pool - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - bondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldBonded, bondedPoolBalance)) - notBondedPoolBalance = f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldNotBonded, notBondedPoolBalance)) - - // read updating redelegation - rd, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) - assert.Assert(t, found) - assert.Assert(t, len(rd.Entries) == 1) - // read updated validator - // power still zero, still in unbonding period - validator, _ = f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, consAddr) - assert.Equal(t, validator.GetStatus(), sdk.Unbonding) -} - -// tests Slash at a previous height with both an unbonding delegation and a redelegation -func TestSlashBoth(t *testing.T) { - f, addrDels, addrVals := bootstrapSlashTest(t, 10) - fraction := math.LegacyNewDecWithPrec(5, 1) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - - // set a redelegation with expiration timestamp beyond which the - // redelegation shouldn't be slashed - rdATokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 6) - rdA := types.NewRedelegation(addrDels[0], addrVals[0], addrVals[1], 11, time.Unix(0, 0), rdATokens, math.LegacyNewDecFromInt(rdATokens), 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetRedelegation(f.sdkCtx, rdA)) - - // set the associated delegation - delA := types.NewDelegation(addrDels[0].String(), addrVals[1].String(), math.LegacyNewDecFromInt(rdATokens)) - assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, delA)) - - // set an unbonding delegation with expiration timestamp (beyond which the - // unbonding delegation shouldn't be slashed) - ubdATokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 4) - ubdA := types.NewUnbondingDelegation(addrDels[0], addrVals[0], 11, - time.Unix(0, 0), ubdATokens, 0, address.NewBech32Codec("cosmosvaloper"), address.NewBech32Codec("cosmos")) - assert.NilError(t, f.stakingKeeper.SetUnbondingDelegation(f.sdkCtx, ubdA)) - - bondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, rdATokens.MulRaw(2))) - notBondedCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, ubdATokens)) - - // update bonded tokens - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), bondedCoins)) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), notBondedCoins)) - - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - - oldBonded := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - oldNotBonded := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount - // slash validator - f.sdkCtx = f.sdkCtx.WithBlockHeight(12).WithHeaderInfo(header.Info{Height: 12}) - _, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, sdk.GetConsAddress(PKs[0])) - assert.Assert(t, found) - consAddr0 := sdk.ConsAddress(PKs[0].Address()) - _, err = f.stakingKeeper.Slash(f.sdkCtx, consAddr0, 10, 10, fraction) - assert.NilError(t, err) - - burnedNotBondedAmount := fraction.MulInt(ubdATokens).TruncateInt() - burnedBondAmount := math.LegacyNewDecFromInt(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10)).Mul(fraction).TruncateInt() - burnedBondAmount = burnedBondAmount.Sub(burnedNotBondedAmount) - - // read updated pool - bondedPool = f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - bondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, bondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldBonded.Sub(burnedBondAmount), bondedPoolBalance)) - - notBondedPoolBalance := f.bankKeeper.GetBalance(f.sdkCtx, notBondedPool.GetAddress(), bondDenom).Amount - assert.Assert(math.IntEq(t, oldNotBonded.Sub(burnedNotBondedAmount), notBondedPoolBalance)) - - // read updating redelegation - rdA, found = f.stakingKeeper.Redelegations.Get(f.sdkCtx, collections.Join3(addrDels[0].Bytes(), addrVals[0].Bytes(), addrVals[1].Bytes())) - assert.Assert(t, found) - assert.Assert(t, len(rdA.Entries) == 1) - // read updated validator - validator, found := f.stakingKeeper.GetValidatorByConsAddr(f.sdkCtx, sdk.GetConsAddress(PKs[0])) - assert.Assert(t, found) - // power not decreased, all stake was bonded since - assert.Equal(t, int64(10), validator.GetConsensusPower(f.stakingKeeper.PowerReduction(f.sdkCtx))) -} - -func TestSlashAmount(t *testing.T) { - f, _, _ := bootstrapSlashTest(t, 10) - consAddr := sdk.ConsAddress(PKs[0].Address()) - fraction := math.LegacyNewDecWithPrec(5, 1) - burnedCoins, err := f.stakingKeeper.Slash(f.sdkCtx, consAddr, f.sdkCtx.BlockHeight(), 10, fraction) - assert.NilError(t, err) - assert.Assert(t, burnedCoins.GT(math.ZeroInt())) - - // test the case where the validator was not found, which should return no coins - _, addrVals := generateAddresses(f, 100) - noBurned, err := f.stakingKeeper.Slash(f.sdkCtx, sdk.ConsAddress(addrVals[0]), f.sdkCtx.BlockHeight(), 10, fraction) - assert.NilError(t, err) - assert.Assert(t, math.NewInt(0).Equal(noBurned)) -} - -// TestFixAvoidFullSlashPenalty fixes the following issue: https://github.com/cosmos/cosmos-sdk/issues/20641 -func TestFixAvoidFullSlashPenalty(t *testing.T) { - // setup - var authKeeper authkeeper.AccountKeeperI - var stakingKeeper *keeper.Keeper - var bankKeeper bankkeeper.Keeper - var slashKeeper slashingkeeper.Keeper - var distrKeeper distributionkeeper.Keeper - app, err := simtestutil.Setup(depinject.Configs( - depinject.Supply(log.NewNopLogger()), - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.BankModule(), - configurator.ConsensusModule(), - configurator.StakingModule(), - configurator.SlashingModule(), - configurator.ProtocolPoolModule(), - configurator.DistributionModule(), - ), - ), &authKeeper, &stakingKeeper, &bankKeeper, &slashKeeper, &distrKeeper) - require.NoError(t, err) - ctx := app.BaseApp.NewContext(false) - stakingMsgServer := keeper.NewMsgServerImpl(stakingKeeper) - bondDenom, err := stakingKeeper.BondDenom(ctx) - require.NoError(t, err) - // create 2 evil validators, controlled by attacker - evilValPubKey := secp256k1.GenPrivKey().PubKey() - evilValPubKey2 := secp256k1.GenPrivKey().PubKey() - // attacker user account - badtestAcc := sdk.AccAddress("addr1_______________") - // normal users who stakes on evilValAddr1 - testAcc1 := sdk.AccAddress("addr2_______________") - testAcc2 := sdk.AccAddress("addr3_______________") - createAccount(t, ctx, authKeeper, badtestAcc) - createAccount(t, ctx, authKeeper, testAcc1) - createAccount(t, ctx, authKeeper, testAcc2) - // fund all accounts - testCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, stakingKeeper.TokensFromConsensusPower(ctx, 1))) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, badtestAcc, testCoins)) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, testAcc1, testCoins)) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, testAcc2, testCoins)) - // create evilValAddr1 for normal staking operations - evilValAddr1 := sdk.ValAddress(evilValPubKey.Address()) - createAccount(t, ctx, authKeeper, evilValAddr1.Bytes()) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, sdk.AccAddress(evilValAddr1), testCoins)) - createValMsg1, _ := types.NewMsgCreateValidator( - evilValAddr1.String(), evilValPubKey, testCoins[0], types.Description{Details: "test"}, types.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) - _, err = stakingMsgServer.CreateValidator(ctx, createValMsg1) - require.NoError(t, err) - // very small amount coin for evilValAddr2 - smallCoins := sdk.NewCoins(sdk.NewCoin(bondDenom, math.NewInt(1))) - // create evilValAddr2 to circumvent slashing - evilValAddr2 := sdk.ValAddress(evilValPubKey2.Address()) - require.NoError(t, banktestutil.FundAccount(ctx, bankKeeper, sdk.AccAddress(evilValAddr2), smallCoins)) - createValMsg3, _ := types.NewMsgCreateValidator( - evilValAddr2.String(), evilValPubKey2, smallCoins[0], types.Description{Details: "test"}, types.NewCommissionRates(math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDecWithPrec(5, 1), math.LegacyNewDec(0)), math.OneInt()) - createAccount(t, ctx, authKeeper, evilValAddr2.Bytes()) - _, err = stakingMsgServer.CreateValidator(ctx, createValMsg3) - 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)) - require.NoError(t, err) - // all accs delegate to evilValAddr1 - delMsg := types.NewMsgDelegate(badtestAcc.String(), evilValAddr1.String(), testCoins[0]) - _, err = stakingMsgServer.Delegate(ctx, delMsg) - require.NoError(t, err) - delMsg = types.NewMsgDelegate(testAcc1.String(), evilValAddr1.String(), testCoins[0]) - _, err = stakingMsgServer.Delegate(ctx, delMsg) - require.NoError(t, err) - delMsg = types.NewMsgDelegate(testAcc2.String(), evilValAddr1.String(), testCoins[0]) - _, err = stakingMsgServer.Delegate(ctx, delMsg) - require.NoError(t, err) - // next block - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) - require.NoError(t, err) - // 1. badtestAcc redelegates from evilValAddr1 to evilValAddr2 - redelMsg := types.NewMsgBeginRedelegate(badtestAcc.String(), evilValAddr1.String(), evilValAddr2.String(), smallCoins[0]) - _, err = stakingMsgServer.BeginRedelegate(ctx, redelMsg) - require.NoError(t, err) - // 2. evilValAddr2 undelegates its self-delegation and jail themselves - undelMsg := types.NewMsgUndelegate(sdk.AccAddress(evilValAddr2).String(), evilValAddr2.String(), smallCoins[0]) - _, err = stakingMsgServer.Undelegate(ctx, undelMsg) - require.NoError(t, err) - // assert evilValAddr2 is jailed - evilVal2, err := stakingKeeper.GetValidator(ctx, evilValAddr2) - require.NoError(t, err) - require.True(t, evilVal2.Jailed) - // next block - ctx, err = simtestutil.NextBlock(app, ctx, time.Duration(1)) - require.NoError(t, err) - // assert invariants - _, stop := keeper.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) - // evilValAddr1 is bad! - // lets slash evilValAddr1 with a 100% penalty - evilVal, err := stakingKeeper.GetValidator(ctx, evilValAddr1) - require.NoError(t, err) - evilValConsAddr, err := evilVal.GetConsAddr() - require.NoError(t, err) - evilPower := stakingKeeper.TokensToConsensusPower(ctx, evilVal.Tokens) - err = slashKeeper.Slash(ctx, evilValConsAddr, math.LegacyMustNewDecFromStr("1.0"), evilPower, 3) - require.NoError(t, err) -} - -func createAccount(t *testing.T, ctx context.Context, k authkeeper.AccountKeeperI, addr sdk.AccAddress) { - t.Helper() - acc := k.NewAccountWithAddress(ctx, addr) - k.SetAccount(ctx, acc) -} diff --git a/tests/integration/staking/keeper/unbonding_test.go b/tests/integration/staking/keeper/unbonding_test.go deleted file mode 100644 index 7a39f4ab20dd..000000000000 --- a/tests/integration/staking/keeper/unbonding_test.go +++ /dev/null @@ -1,460 +0,0 @@ -package keeper_test - -import ( - "testing" - "time" - - "go.uber.org/mock/gomock" - "gotest.tools/v3/assert" - - "cosmossdk.io/core/header" - "cosmossdk.io/math" - banktestutil "cosmossdk.io/x/bank/testutil" - stakingkeeper "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/testutil" - "cosmossdk.io/x/staking/types" - - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -// SetupUnbondingTests creates two validators and setup mocked staking hooks for testing unbonding -func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uint64) (bondDenom string, addrDels []sdk.AccAddress, addrVals []sdk.ValAddress) { - t.Helper() - // setup hooks - mockCtrl := gomock.NewController(t) - mockStackingHooks := testutil.NewMockStakingHooks(mockCtrl) - mockStackingHooks.EXPECT().AfterDelegationModified(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().AfterUnbondingInitiated(gomock.Any(), gomock.Any()).DoAndReturn(func(ctx sdk.Context, id uint64) error { - *hookCalled = true - // save id - *ubdeID = id - // call back to stop unbonding - err := f.stakingKeeper.PutUnbondingOnHold(f.sdkCtx, id) - assert.NilError(t, err) - - return nil - }).AnyTimes() - mockStackingHooks.EXPECT().AfterValidatorBeginUnbonding(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().AfterValidatorBonded(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().AfterValidatorCreated(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().AfterValidatorRemoved(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().BeforeDelegationCreated(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().BeforeDelegationRemoved(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().BeforeDelegationSharesModified(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().BeforeValidatorModified(gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().BeforeValidatorSlashed(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - mockStackingHooks.EXPECT().AfterConsensusPubKeyUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() - f.stakingKeeper.SetHooks(types.NewMultiStakingHooks(mockStackingHooks)) - - addrDels = simtestutil.AddTestAddrsIncremental(f.bankKeeper, f.stakingKeeper, f.sdkCtx, 2, math.NewInt(10000)) - addrVals = simtestutil.ConvertAddrsToValAddrs(addrDels) - - valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10) - startTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 20) - - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, startTokens)))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - - // Create a validator - validator1 := testutil.NewValidator(t, addrVals[0], PKs[0]) - validator1, issuedShares1 := validator1.AddTokensFromDel(valTokens) - assert.DeepEqual(t, valTokens, issuedShares1.RoundInt()) - - validator1 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator1, true) - assert.Assert(math.IntEq(t, valTokens, validator1.BondedTokens())) - assert.Assert(t, validator1.IsBonded()) - - // Create a delegator - delegation := types.NewDelegation(addrDels[0].String(), addrVals[0].String(), issuedShares1) - assert.NilError(t, f.stakingKeeper.SetDelegation(f.sdkCtx, delegation)) - - // Create a validator to redelegate to - validator2 := testutil.NewValidator(t, addrVals[1], PKs[1]) - validator2, issuedShares2 := validator2.AddTokensFromDel(valTokens) - assert.DeepEqual(t, valTokens, issuedShares2.RoundInt()) - - validator2 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator2, true) - assert.Equal(t, types.Bonded, validator2.Status) - assert.Assert(t, validator2.IsBonded()) - - return bondDenom, addrDels, addrVals -} - -func doUnbondingDelegation( - t *testing.T, - stakingKeeper *stakingkeeper.Keeper, - bankKeeper types.BankKeeper, - ctx sdk.Context, - bondDenom string, - addrDels []sdk.AccAddress, - addrVals []sdk.ValAddress, - hookCalled *bool, -) (completionTime time.Time, bondedAmt, notBondedAmt math.Int) { - t.Helper() - // UNDELEGATE - // Save original bonded and unbonded amounts - bondedAmt1 := bankKeeper.GetBalance(ctx, stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - notBondedAmt1 := bankKeeper.GetBalance(ctx, stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - - var err error - undelegateAmount := math.LegacyNewDec(1) - completionTime, undelegatedAmount, err := stakingKeeper.Undelegate(ctx, addrDels[0], addrVals[0], undelegateAmount) - assert.NilError(t, err) - assert.Assert(t, undelegateAmount.Equal(math.LegacyNewDecFromInt(undelegatedAmount))) - // check that the unbonding actually happened - bondedAmt2 := bankKeeper.GetBalance(ctx, stakingKeeper.GetBondedPool(ctx).GetAddress(), bondDenom).Amount - notBondedAmt2 := bankKeeper.GetBalance(ctx, stakingKeeper.GetNotBondedPool(ctx).GetAddress(), bondDenom).Amount - // Bonded amount is less - assert.Assert(math.IntEq(t, bondedAmt1.SubRaw(1), bondedAmt2)) - // Unbonded amount is more - assert.Assert(math.IntEq(t, notBondedAmt1.AddRaw(1), notBondedAmt2)) - - // Check that the unbonding happened- we look up the entry and see that it has the correct number of shares - unbondingDelegations, err := stakingKeeper.GetUnbondingDelegationsFromValidator(ctx, addrVals[0]) - assert.NilError(t, err) - assert.DeepEqual(t, math.NewInt(1), unbondingDelegations[0].Entries[0].Balance) - - // check that our hook was called - assert.Assert(t, *hookCalled) - - return completionTime, bondedAmt2, notBondedAmt2 -} - -func doRedelegation( - t *testing.T, - stakingKeeper *stakingkeeper.Keeper, - ctx sdk.Context, - addrDels []sdk.AccAddress, - addrVals []sdk.ValAddress, - hookCalled *bool, -) (completionTime time.Time) { - t.Helper() - var err error - completionTime, err = stakingKeeper.BeginRedelegation(ctx, addrDels[0], addrVals[0], addrVals[1], math.LegacyNewDec(1)) - assert.NilError(t, err) - - // Check that the redelegation happened- we look up the entry and see that it has the correct number of shares - redelegations, err := stakingKeeper.GetRedelegationsFromSrcValidator(ctx, addrVals[0]) - assert.NilError(t, err) - assert.Equal(t, 1, len(redelegations)) - assert.DeepEqual(t, math.LegacyNewDec(1), redelegations[0].Entries[0].SharesDst) - - // check that our hook was called - assert.Assert(t, *hookCalled) - - return completionTime -} - -func doValidatorUnbonding( - t *testing.T, - stakingKeeper *stakingkeeper.Keeper, - ctx sdk.Context, - addrVal sdk.ValAddress, - hookCalled *bool, -) (validator types.Validator) { - t.Helper() - validator, found := stakingKeeper.GetValidator(ctx, addrVal) - assert.Assert(t, found) - // Check that status is bonded - assert.Equal(t, types.BondStatus(3), validator.Status) - - validator, err := stakingKeeper.BeginUnbondingValidator(ctx, validator) - assert.NilError(t, err) - - // Check that status is unbonding - assert.Equal(t, types.BondStatus(2), validator.Status) - - // check that our hook was called - assert.Assert(t, *hookCalled) - - return validator -} - -func TestValidatorUnbondingOnHold1(t *testing.T) { - t.Parallel() - f := initFixture(t) - - var ( - hookCalled bool - ubdeID uint64 - ) - - _, _, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) - - // Start unbonding first validator - validator := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[0], &hookCalled) - - completionTime := validator.UnbondingTime - completionHeight := validator.UnbondingHeight - - // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) - assert.NilError(t, err) - - // Try to unbond validator - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) - - // Check that validator unbonding is not complete (is not mature yet) - validator, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) - assert.Assert(t, found) - assert.Equal(t, types.Unbonding, validator.Status) - unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) - assert.NilError(t, err) - assert.Equal(t, 1, len(unbondingVals)) - assert.Equal(t, validator.OperatorAddress, unbondingVals[0]) - - // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime.Add(time.Duration(1))}) - f.sdkCtx = f.sdkCtx.WithBlockHeight(completionHeight + 1) - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) - - // Check that validator unbonding is complete - validator, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) - assert.Assert(t, found) - assert.Equal(t, types.Unbonded, validator.Status) - unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) - assert.NilError(t, err) - assert.Equal(t, 0, len(unbondingVals)) -} - -func TestValidatorUnbondingOnHold2(t *testing.T) { - t.Parallel() - f := initFixture(t) - - var ( - hookCalled bool - ubdeID uint64 - ubdeIDs []uint64 - ) - - _, _, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) - - // Start unbonding first validator - validator1 := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[0], &hookCalled) - ubdeIDs = append(ubdeIDs, ubdeID) - - // Reset hookCalled flag - hookCalled = false - - // Start unbonding second validator - validator2 := doValidatorUnbonding(t, f.stakingKeeper, f.sdkCtx, addrVals[1], &hookCalled) - ubdeIDs = append(ubdeIDs, ubdeID) - - // Check that there are two unbonding operations - assert.Equal(t, 2, len(ubdeIDs)) - - // Check that both validators have same unbonding time - assert.Equal(t, validator1.UnbondingTime, validator2.UnbondingTime) - - completionTime := validator1.UnbondingTime - completionHeight := validator1.UnbondingHeight - - // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime.Add(time.Duration(1))}) - f.sdkCtx = f.sdkCtx.WithBlockHeight(completionHeight + 1) - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) - - // Check that unbonding is not complete for both validators - validator1, found := f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) - assert.Assert(t, found) - assert.Equal(t, types.Unbonding, validator1.Status) - validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) - assert.Assert(t, found) - assert.Equal(t, types.Unbonding, validator2.Status) - unbondingVals, err := f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) - assert.NilError(t, err) - assert.Equal(t, 2, len(unbondingVals)) - assert.Equal(t, validator1.OperatorAddress, unbondingVals[0]) - assert.Equal(t, validator2.OperatorAddress, unbondingVals[1]) - - // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeIDs[0]) - assert.NilError(t, err) - - // Try again to unbond validators - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) - - // Check that unbonding is complete for validator1, but not for validator2 - validator1, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) - assert.Assert(t, found) - assert.Equal(t, types.Unbonded, validator1.Status) - validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) - assert.Assert(t, found) - assert.Equal(t, types.Unbonding, validator2.Status) - unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) - assert.NilError(t, err) - assert.Equal(t, 1, len(unbondingVals)) - assert.Equal(t, validator2.OperatorAddress, unbondingVals[0]) - - // Unbonding for validator2 can complete - err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeIDs[1]) - assert.NilError(t, err) - - // Try again to unbond validators - assert.NilError(t, f.stakingKeeper.UnbondAllMatureValidators(f.sdkCtx)) - - // Check that unbonding is complete for validator2 - validator2, found = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[1]) - assert.Assert(t, found) - assert.Equal(t, types.Unbonded, validator2.Status) - unbondingVals, err = f.stakingKeeper.GetUnbondingValidators(f.sdkCtx, completionTime, completionHeight) - assert.NilError(t, err) - assert.Equal(t, 0, len(unbondingVals)) -} - -func TestRedelegationOnHold1(t *testing.T) { - t.Parallel() - f := initFixture(t) - - var ( - hookCalled bool - ubdeID uint64 - ) - - // _, app, ctx := createTestInput(t) - _, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) - completionTime := doRedelegation(t, f.stakingKeeper, f.sdkCtx, addrDels, addrVals, &hookCalled) - - // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) - assert.NilError(t, err) - - // Redelegation is not complete - still exists - redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) - assert.NilError(t, err) - assert.Equal(t, 1, len(redelegations)) - - // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) - _, err = f.stakingKeeper.CompleteRedelegation(f.sdkCtx, addrDels[0], addrVals[0], addrVals[1]) - assert.NilError(t, err) - - // Redelegation is complete and record is gone - redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) - assert.NilError(t, err) - assert.Equal(t, 0, len(redelegations)) -} - -func TestRedelegationOnHold2(t *testing.T) { - t.Parallel() - f := initFixture(t) - - var ( - hookCalled bool - ubdeID uint64 - ) - - // _, app, ctx := createTestInput(t) - _, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) - completionTime := doRedelegation(t, f.stakingKeeper, f.sdkCtx, addrDels, addrVals, &hookCalled) - - // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) - _, err := f.stakingKeeper.CompleteRedelegation(f.sdkCtx, addrDels[0], addrVals[0], addrVals[1]) - assert.NilError(t, err) - - // Redelegation is not complete - still exists - redelegations, err := f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) - assert.NilError(t, err) - assert.Equal(t, 1, len(redelegations)) - - // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) - assert.NilError(t, err) - - // Redelegation is complete and record is gone - redelegations, err = f.stakingKeeper.GetRedelegationsFromSrcValidator(f.sdkCtx, addrVals[0]) - assert.NilError(t, err) - assert.Equal(t, 0, len(redelegations)) -} - -func TestUnbondingDelegationOnHold1(t *testing.T) { - t.Parallel() - f := initFixture(t) - - var ( - hookCalled bool - ubdeID uint64 - ) - - // _, app, ctx := createTestInput(t) - bondDenom, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) - for _, addr := range addrDels { - acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) - f.accountKeeper.SetAccount(f.sdkCtx, acc) - } - completionTime, bondedAmt1, notBondedAmt1 := doUnbondingDelegation(t, f.stakingKeeper, f.bankKeeper, f.sdkCtx, bondDenom, addrDels, addrVals, &hookCalled) - - // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - err := f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) - assert.NilError(t, err) - - bondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - notBondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - - // Bonded and unbonded amounts are the same as before because the completionTime has not yet passed and so the - // unbondingDelegation has not completed - assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt3)) - assert.Assert(math.IntEq(t, notBondedAmt1, notBondedAmt3)) - - // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) - _, err = f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0]) - assert.NilError(t, err) - - // Check that the unbonding was finally completed - bondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - notBondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - - assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt5)) - // Not bonded amount back to what it was originally - assert.Assert(math.IntEq(t, notBondedAmt1.SubRaw(1), notBondedAmt5)) -} - -func TestUnbondingDelegationOnHold2(t *testing.T) { - t.Parallel() - f := initFixture(t) - - var ( - hookCalled bool - ubdeID uint64 - ) - - // _, app, ctx := createTestInput(t) - bondDenom, addrDels, addrVals := SetupUnbondingTests(t, f, &hookCalled, &ubdeID) - for _, addr := range addrDels { - acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, addr) - f.accountKeeper.SetAccount(f.sdkCtx, acc) - } - completionTime, bondedAmt1, notBondedAmt1 := doUnbondingDelegation(t, f.stakingKeeper, f.bankKeeper, f.sdkCtx, bondDenom, addrDels, addrVals, &hookCalled) - - // PROVIDER CHAIN'S UNBONDING PERIOD ENDS - BUT UNBONDING CANNOT COMPLETE - f.sdkCtx = f.sdkCtx.WithHeaderInfo(header.Info{Time: completionTime}) - _, err := f.stakingKeeper.CompleteUnbonding(f.sdkCtx, addrDels[0], addrVals[0]) - assert.NilError(t, err) - - bondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - notBondedAmt3 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - - // Bonded and unbonded amounts are the same as before because the completionTime has not yet passed and so the - // unbondingDelegation has not completed - assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt3)) - assert.Assert(math.IntEq(t, notBondedAmt1, notBondedAmt3)) - - // CONSUMER CHAIN'S UNBONDING PERIOD ENDS - STOPPED UNBONDING CAN NOW COMPLETE - err = f.stakingKeeper.UnbondingCanComplete(f.sdkCtx, ubdeID) - assert.NilError(t, err) - - // Check that the unbonding was finally completed - bondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - notBondedAmt5 := f.bankKeeper.GetBalance(f.sdkCtx, f.stakingKeeper.GetNotBondedPool(f.sdkCtx).GetAddress(), bondDenom).Amount - - assert.Assert(math.IntEq(t, bondedAmt1, bondedAmt5)) - // Not bonded amount back to what it was originally - assert.Assert(math.IntEq(t, notBondedAmt1.SubRaw(1), notBondedAmt5)) -} diff --git a/tests/integration/staking/keeper/validator_bench_test.go b/tests/integration/staking/keeper/validator_bench_test.go deleted file mode 100644 index 8208bdb74683..000000000000 --- a/tests/integration/staking/keeper/validator_bench_test.go +++ /dev/null @@ -1,181 +0,0 @@ -package keeper_test - -import ( - "bytes" - "fmt" - "testing" - - "cosmossdk.io/collections" - "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/staking/types" - - sdk "github.com/cosmos/cosmos-sdk/types" -) - -func BenchmarkGetValidator(b *testing.B) { - // 900 is the max number we are allowed to use in order to avoid simtestutil.CreateTestPubKeys - // panic: encoding/hex: odd length hex string - powersNumber := 900 - - var totalPower int64 - powers := make([]int64, powersNumber) - for i := range powers { - powers[i] = int64(i) - totalPower += int64(i) - } - - f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) - - for _, validator := range vals { - if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { - panic(err) - } - } - - b.ResetTimer() - for n := 0; n < b.N; n++ { - for _, addr := range valAddrs { - _, _ = f.stakingKeeper.GetValidator(f.sdkCtx, addr) - } - } -} - -func BenchmarkGetValidatorDelegations(b *testing.B) { - var totalPower int64 - powersNumber := 10 - - powers := make([]int64, powersNumber) - for i := range powers { - powers[i] = int64(i) - totalPower += int64(i) - } - - f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) - for _, validator := range vals { - if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { - panic(err) - } - } - - delegationsNum := 1000 - for _, val := range valAddrs { - for i := 0; i < delegationsNum; i++ { - delegator := sdk.AccAddress(fmt.Sprintf("address%d", i)) - err := banktestutil.FundAccount(f.sdkCtx, f.bankKeeper, delegator, - sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(int64(i))))) - if err != nil { - panic(err) - } - NewDel := types.NewDelegation(delegator.String(), val.String(), math.LegacyNewDec(int64(i))) - - if err := f.stakingKeeper.SetDelegation(f.sdkCtx, NewDel); err != nil { - panic(err) - } - } - } - - b.ResetTimer() - for n := 0; n < b.N; n++ { - updateValidatorDelegations(f, valAddrs[0], sdk.ValAddress("val")) - } -} - -func BenchmarkGetValidatorDelegationsLegacy(b *testing.B) { - var totalPower int64 - powersNumber := 10 - - powers := make([]int64, powersNumber) - for i := range powers { - powers[i] = int64(i) - totalPower += int64(i) - } - - f, _, valAddrs, vals := initValidators(b, totalPower, len(powers), powers) - - for _, validator := range vals { - if err := f.stakingKeeper.SetValidator(f.sdkCtx, validator); err != nil { - panic(err) - } - } - - delegationsNum := 1000 - for _, val := range valAddrs { - for i := 0; i < delegationsNum; i++ { - delegator := sdk.AccAddress(fmt.Sprintf("address%d", i)) - err := banktestutil.FundAccount(f.sdkCtx, f.bankKeeper, delegator, - sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, math.NewInt(int64(i))))) - if err != nil { - panic(err) - } - NewDel := types.NewDelegation(delegator.String(), val.String(), math.LegacyNewDec(int64(i))) - if err := f.stakingKeeper.SetDelegation(f.sdkCtx, NewDel); err != nil { - panic(err) - } - } - } - - b.ResetTimer() - for n := 0; n < b.N; n++ { - updateValidatorDelegationsLegacy(f, valAddrs[0], sdk.ValAddress("val")) - } -} - -func updateValidatorDelegationsLegacy(f *fixture, existingValAddr, newValAddr sdk.ValAddress) { - storeKey := f.keys[types.StoreKey] - cdc, k := f.cdc, f.stakingKeeper - - store := f.sdkCtx.KVStore(storeKey) - - iterator := storetypes.KVStorePrefixIterator(store, types.DelegationKey) - defer iterator.Close() - - for ; iterator.Valid(); iterator.Next() { - delegation := types.MustUnmarshalDelegation(cdc, iterator.Value()) - valAddr, err := k.ValidatorAddressCodec().StringToBytes(delegation.GetValidatorAddr()) - if err != nil { - panic(err) - } - - if bytes.EqualFold(valAddr, existingValAddr) { - if err := k.RemoveDelegation(f.sdkCtx, delegation); err != nil { - panic(err) - } - delegation.ValidatorAddress = newValAddr.String() - if err := k.SetDelegation(f.sdkCtx, delegation); err != nil { - panic(err) - } - } - } -} - -func updateValidatorDelegations(f *fixture, existingValAddr, newValAddr sdk.ValAddress) { - k := f.stakingKeeper - - rng := collections.NewPrefixedPairRange[sdk.ValAddress, sdk.AccAddress](existingValAddr) - err := k.DelegationsByValidator.Walk(f.sdkCtx, rng, func(key collections.Pair[sdk.ValAddress, sdk.AccAddress], _ []byte) (stop bool, err error) { - valAddr, delAddr := key.K1(), key.K2() - - delegation, err := k.Delegations.Get(f.sdkCtx, collections.Join(delAddr, valAddr)) - if err != nil { - return true, err - } - - // remove old operator addr from delegation - if err := k.RemoveDelegation(f.sdkCtx, delegation); err != nil { - return true, err - } - - delegation.ValidatorAddress = newValAddr.String() - // add with new operator addr - if err := k.SetDelegation(f.sdkCtx, delegation); err != nil { - return true, err - } - - return false, nil - }) - if err != nil { - panic(err) - } -} diff --git a/tests/integration/staking/keeper/validator_test.go b/tests/integration/staking/keeper/validator_test.go deleted file mode 100644 index a19352f1cda6..000000000000 --- a/tests/integration/staking/keeper/validator_test.go +++ /dev/null @@ -1,887 +0,0 @@ -package keeper_test - -import ( - "fmt" - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/math" - banktestutil "cosmossdk.io/x/bank/testutil" - "cosmossdk.io/x/staking/keeper" - "cosmossdk.io/x/staking/testutil" - "cosmossdk.io/x/staking/types" - - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" -) - -func newMonikerValidator(tb testing.TB, operator sdk.ValAddress, pubKey cryptotypes.PubKey, moniker string) types.Validator { - tb.Helper() - v, err := types.NewValidator(operator.String(), pubKey, types.Description{Moniker: moniker}) - assert.NilError(tb, err) - return v -} - -func bootstrapValidatorTest(tb testing.TB, power int64, numAddrs int) (*fixture, []sdk.AccAddress, []sdk.ValAddress) { - tb.Helper() - f := initFixture(tb) - - addrDels, addrVals := generateAddresses(f, numAddrs) - - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(tb, err) - - amt := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - totalSupply := sdk.NewCoins(sdk.NewCoin(bondDenom, amt.MulRaw(int64(len(addrDels))))) - - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - // set bonded pool supply - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - - assert.NilError(tb, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), totalSupply)) - - return f, addrDels, addrVals -} - -func initValidators(tb testing.TB, power int64, numAddrs int, powers []int64) (*fixture, []sdk.AccAddress, []sdk.ValAddress, []types.Validator) { - tb.Helper() - f, addrs, valAddrs := bootstrapValidatorTest(tb, power, numAddrs) - pks := simtestutil.CreateTestPubKeys(numAddrs) - - vs := make([]types.Validator, len(powers)) - for i, power := range powers { - vs[i] = testutil.NewValidator(tb, sdk.ValAddress(addrs[i]), pks[i]) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - vs[i], _ = vs[i].AddTokensFromDel(tokens) - } - return f, addrs, valAddrs, vs -} - -func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { - numVals := 10 - maxVals := 5 - - // create context, keeper, and pool for tests - f, _, valAddrs := bootstrapValidatorTest(t, 1, 100) - - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - // create keeper parameters - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - params.MaxValidators = uint32(maxVals) - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) - - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - - // create a random pool - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1234))))) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10000))))) - - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - - validators := make([]types.Validator, numVals) - for i := 0; i < len(validators); i++ { - moniker := fmt.Sprintf("val#%d", int64(i)) - val := newMonikerValidator(t, valAddrs[i], PKs[i], moniker) - delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, int64((i+1)*10)) - val, _ = val.AddTokensFromDel(delTokens) - - val = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, val, true) - validators[i] = val - } - - nextCliffVal := validators[numVals-maxVals+1] - - // remove enough tokens to kick out the validator below the current cliff - // validator and next in line cliff validator - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, nextCliffVal)) - shares := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 21) - nextCliffVal, _ = nextCliffVal.RemoveDelShares(math.LegacyNewDecFromInt(shares)) - _ = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, nextCliffVal, true) - - expectedValStatus := map[int]sdk.BondStatus{ - 9: sdk.Bonded, 8: sdk.Bonded, 7: sdk.Bonded, 5: sdk.Bonded, 4: sdk.Bonded, - 0: sdk.Unbonding, 1: sdk.Unbonding, 2: sdk.Unbonding, 3: sdk.Unbonding, 6: sdk.Unbonding, - } - - // require all the validators have their respective statuses - for valIdx, status := range expectedValStatus { - valAddr := validators[valIdx].OperatorAddress - addr, err := sdk.ValAddressFromBech32(valAddr) - assert.NilError(t, err) - val, _ := f.stakingKeeper.GetValidator(f.sdkCtx, addr) - - assert.Equal( - t, status, val.GetStatus(), - fmt.Sprintf("expected validator at index %v to have status: %x", valIdx, status), - ) - } -} - -func TestSlashToZeroPowerRemoved(t *testing.T) { - // initialize setup - f, _, addrVals := bootstrapValidatorTest(t, 100, 20) - - // add a validator - validator := testutil.NewValidator(t, addrVals[0], PKs[0]) - valTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) - - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, valTokens)))) - - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - - validator, _ = validator.AddTokensFromDel(valTokens) - assert.Equal(t, types.Unbonded, validator.Status) - assert.DeepEqual(t, valTokens, validator.Tokens) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, validator)) - validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validator, true) - assert.DeepEqual(t, valTokens, validator.Tokens) - - // slash the validator by 100% - _, err = f.stakingKeeper.Slash(f.sdkCtx, sdk.ConsAddress(PKs[0].Address()), 0, 100, math.LegacyOneDec()) - assert.NilError(t, err) - // apply TM updates - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, -1) - // validator should be unbonding - validator, _ = f.stakingKeeper.GetValidator(f.sdkCtx, addrVals[0]) - assert.Equal(t, validator.GetStatus(), sdk.Unbonding) -} - -// test how the validators are sorted, tests GetBondedValidatorsByPower -func TestGetValidatorSortingUnmixed(t *testing.T) { - f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - - // initialize some validators into the state - amts := []math.Int{ - math.NewIntFromUint64(0), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(100), - f.stakingKeeper.PowerReduction(f.sdkCtx), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(400), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(200), - } - n := len(amts) - var validators [5]types.Validator - for i, amt := range amts { - validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - validators[i].Status = types.Bonded - validators[i].Tokens = amt - validators[i].DelegatorShares = math.LegacyNewDecFromInt(amt) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) - } - - // first make sure everything made it in to the gotValidator group - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, n, len(resValidators)) - assert.DeepEqual(t, math.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[0].BondedTokens()) - assert.DeepEqual(t, math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[1].BondedTokens()) - assert.DeepEqual(t, math.NewInt(100).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[2].BondedTokens()) - assert.DeepEqual(t, math.NewInt(1).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[3].BondedTokens()) - assert.DeepEqual(t, math.NewInt(0), resValidators[4].BondedTokens()) - assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators) - assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators) - assert.Equal(t, validators[1].OperatorAddress, resValidators[2].OperatorAddress, "%v", resValidators) - assert.Equal(t, validators[2].OperatorAddress, resValidators[3].OperatorAddress, "%v", resValidators) - assert.Equal(t, validators[0].OperatorAddress, resValidators[4].OperatorAddress, "%v", resValidators) - - // test a basic increase in voting power - validators[3].Tokens = math.NewInt(500).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, len(resValidators), n) - assert.Assert(ValEq(t, validators[3], resValidators[0])) - - // test a decrease in voting power - validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, len(resValidators), n) - assert.Assert(ValEq(t, validators[3], resValidators[0])) - assert.Assert(ValEq(t, validators[4], resValidators[1])) - - // test equal voting power, different age - validators[3].Tokens = math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - f.sdkCtx = f.sdkCtx.WithBlockHeight(10) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, len(resValidators), n) - assert.Assert(ValEq(t, validators[3], resValidators[0])) - assert.Assert(ValEq(t, validators[4], resValidators[1])) - - // no change in voting power - no change in sort - f.sdkCtx = f.sdkCtx.WithBlockHeight(20) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[4], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, len(resValidators), n) - assert.Assert(ValEq(t, validators[3], resValidators[0])) - assert.Assert(ValEq(t, validators[4], resValidators[1])) - - // change in voting power of both validators, both still in v-set, no age change - validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - validators[4].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, len(resValidators), n) - f.sdkCtx = f.sdkCtx.WithBlockHeight(30) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[4], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, len(resValidators), n, "%v", resValidators) - assert.Assert(ValEq(t, validators[3], resValidators[0])) - assert.Assert(ValEq(t, validators[4], resValidators[1])) -} - -func TestGetValidatorSortingMixed(t *testing.T) { - f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - bondDenom, err := f.stakingKeeper.BondDenom(f.sdkCtx) - assert.NilError(t, err) - - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 501))))) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(bondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 0))))) - - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - - // now 2 max resValidators - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - params.MaxValidators = 2 - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) - - // initialize some validators into the state - amts := []math.Int{ - math.NewIntFromUint64(0), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(100), - f.stakingKeeper.PowerReduction(f.sdkCtx), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(400), - f.stakingKeeper.PowerReduction(f.sdkCtx).MulRaw(200), - } - - var validators [5]types.Validator - for i, amt := range amts { - validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - validators[i].DelegatorShares = math.LegacyNewDecFromInt(amt) - validators[i].Status = types.Bonded - validators[i].Tokens = amt - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) - } - - val0, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[0])) - assert.Assert(t, found) - val1, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[1])) - assert.Assert(t, found) - val2, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[2])) - assert.Assert(t, found) - val3, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[3])) - assert.Assert(t, found) - val4, found := f.stakingKeeper.GetValidator(f.sdkCtx, sdk.ValAddress(addrs[4])) - assert.Assert(t, found) - assert.Equal(t, types.Bonded, val0.Status) - assert.Equal(t, types.Unbonding, val1.Status) - assert.Equal(t, types.Unbonding, val2.Status) - assert.Equal(t, types.Bonded, val3.Status) - assert.Equal(t, types.Bonded, val4.Status) - - // first make sure everything made it in to the gotValidator group - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - // The validators returned should match the max validators - assert.Equal(t, 2, len(resValidators)) - assert.DeepEqual(t, math.NewInt(400).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[0].BondedTokens()) - assert.DeepEqual(t, math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.sdkCtx)), resValidators[1].BondedTokens()) - assert.Equal(t, validators[3].OperatorAddress, resValidators[0].OperatorAddress, "%v", resValidators) - assert.Equal(t, validators[4].OperatorAddress, resValidators[1].OperatorAddress, "%v", resValidators) -} - -// TODO separate out into multiple tests -func TestGetValidatorsEdgeCases(t *testing.T) { - f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - - // set max validators to 2 - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - nMax := uint32(2) - params.MaxValidators = nMax - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) - // initialize some validators into the state - powers := []int64{0, 100, 400, 400} - var validators [4]types.Validator - for i, power := range powers { - moniker := fmt.Sprintf("val#%d", int64(i)) - validators[i] = newMonikerValidator(t, sdk.ValAddress(addrs[i]), PKs[i], moniker) - - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - validators[i] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) - } - - // ensure that the first two bonded validators are the largest validators - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, nMax, uint32(len(resValidators))) - assert.Assert(ValEq(t, validators[2], resValidators[0])) - assert.Assert(ValEq(t, validators[3], resValidators[1])) - - // delegate 500 tokens to validator 0 - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) - delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 500) - validators[0], _ = validators[0].AddTokensFromDel(delTokens) - notBondedPool := f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - - newTokens := sdk.NewCoins() - - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), newTokens)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - - // test that the two largest validators are - // a) validator 0 with 500 tokens - // b) validator 2 with 400 tokens (delegated before validator 3) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, nMax, uint32(len(resValidators))) - assert.Assert(ValEq(t, validators[0], resValidators[0])) - assert.Assert(ValEq(t, validators[2], resValidators[1])) - - // A validator which leaves the bonded validator set due to a decrease in voting power, - // then increases to the original voting power, does not get its spot back in the - // case of a tie. - // - // Order of operations for this test: - // - validator 3 enter validator set with 1 new token - // - validator 3 removed validator set by removing 201 tokens (validator 2 enters) - // - validator 3 adds 200 tokens (equal to validator 2 now) and does not get its spot back - - // validator 3 enters bonded validator set - f.sdkCtx = f.sdkCtx.WithBlockHeight(40) - - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[3].GetOperator()) - assert.NilError(t, err) - - validators[3], err = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) - assert.NilError(t, err) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) - validators[3], _ = validators[3].AddTokensFromDel(f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1)) - - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - newTokens = sdk.NewCoins(sdk.NewCoin(params.BondDenom, f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1))) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), newTokens)) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, nMax, uint32(len(resValidators))) - assert.Assert(ValEq(t, validators[0], resValidators[0])) - assert.Assert(ValEq(t, validators[3], resValidators[1])) - - // validator 3 kicked out temporarily - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) - rmTokens := validators[3].TokensFromShares(math.LegacyNewDec(201)).TruncateInt() - validators[3], _ = validators[3].RemoveDelShares(math.LegacyNewDec(201)) - - bondedPool := f.stakingKeeper.GetBondedPool(f.sdkCtx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, bondedPool) - - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, nMax, uint32(len(resValidators))) - assert.Assert(ValEq(t, validators[0], resValidators[0])) - assert.Assert(ValEq(t, validators[2], resValidators[1])) - - // validator 3 does not get spot back - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[3])) - validators[3], _ = validators[3].AddTokensFromDel(math.NewInt(200)) - - notBondedPool = f.stakingKeeper.GetNotBondedPool(f.sdkCtx) - assert.NilError(t, banktestutil.FundModuleAccount(f.sdkCtx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, math.NewInt(200))))) - f.accountKeeper.SetModuleAccount(f.sdkCtx, notBondedPool) - - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[3], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, nMax, uint32(len(resValidators))) - assert.Assert(ValEq(t, validators[0], resValidators[0])) - assert.Assert(ValEq(t, validators[2], resValidators[1])) - _, exists := f.stakingKeeper.GetValidator(f.sdkCtx, valbz) - assert.Assert(t, exists) -} - -func TestValidatorBondHeight(t *testing.T) { - f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - - // now 2 max resValidators - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - params.MaxValidators = 2 - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) - // initialize some validators into the state - var validators [3]types.Validator - validators[0] = testutil.NewValidator(t, sdk.ValAddress(PKs[0].Address().Bytes()), PKs[0]) - validators[1] = testutil.NewValidator(t, sdk.ValAddress(addrs[1]), PKs[1]) - validators[2] = testutil.NewValidator(t, sdk.ValAddress(addrs[2]), PKs[2]) - - tokens0 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 200) - tokens1 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) - tokens2 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 100) - validators[0], _ = validators[0].AddTokensFromDel(tokens0) - validators[1], _ = validators[1].AddTokensFromDel(tokens1) - validators[2], _ = validators[2].AddTokensFromDel(tokens2) - - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) - - //////////////////////////////////////// - // If two validators both increase to the same voting power in the same block, - // the one with the first transaction should become bonded - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], true) - validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], true) - - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, uint32(len(resValidators)), params.MaxValidators) - - assert.Assert(ValEq(t, validators[0], resValidators[0])) - assert.Assert(ValEq(t, validators[1], resValidators[1])) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[1])) - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[2])) - delTokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 50) - validators[1], _ = validators[1].AddTokensFromDel(delTokens) - validators[2], _ = validators[2].AddTokensFromDel(delTokens) - validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, params.MaxValidators, uint32(len(resValidators))) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], true) - assert.Assert(ValEq(t, validators[0], resValidators[0])) - assert.Assert(ValEq(t, validators[2], resValidators[1])) -} - -func TestFullValidatorSetPowerChange(t *testing.T) { - f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - max := 2 - params.MaxValidators = uint32(2) - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) - - // initialize some validators into the state - powers := []int64{0, 100, 400, 400, 200} - var validators [5]types.Validator - for i, power := range powers { - validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[i], true) - } - for i := range powers { - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[i].GetOperator()) - assert.NilError(t, err) - - validators[i], err = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) - assert.NilError(t, err) - } - assert.Equal(t, types.Unbonded, validators[0].Status) - assert.Equal(t, types.Unbonding, validators[1].Status) - assert.Equal(t, types.Bonded, validators[2].Status) - assert.Equal(t, types.Bonded, validators[3].Status) - assert.Equal(t, types.Unbonded, validators[4].Status) - resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, max, len(resValidators)) - assert.Assert(ValEq(t, validators[2], resValidators[0])) // in the order of txs - assert.Assert(ValEq(t, validators[3], resValidators[1])) - - // test a swap in voting power - - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 600) - validators[0], _ = validators[0].AddTokensFromDel(tokens) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], true) - resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.sdkCtx) - assert.NilError(t, err) - assert.Equal(t, max, len(resValidators)) - assert.Assert(ValEq(t, validators[0], resValidators[0])) - assert.Assert(ValEq(t, validators[2], resValidators[1])) -} - -func TestApplyAndReturnValidatorSetUpdatesAllNone(t *testing.T) { - f, _, _ := bootstrapValidatorTest(t, 1000, 20) - - powers := []int64{10, 20} - var validators [2]types.Validator - for i, power := range powers { - valPubKey := PKs[i+1] - valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) - - validators[i] = testutil.NewValidator(t, valAddr, valPubKey) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - } - - // test from nothing to something - // tendermintUpdate set: {} -> {c1, c3} - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[1])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[1])) - - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) - assert.NilError(t, err) - val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) - assert.NilError(t, err) - validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) - validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) -} - -func TestApplyAndReturnValidatorSetUpdatesIdentical(t *testing.T) { - f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - - powers := []int64{10, 20} - var validators [2]types.Validator - for i, power := range powers { - validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - - } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - - // test identical, - // tendermintUpdate set: {} -> {} - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) -} - -func TestApplyAndReturnValidatorSetUpdatesSingleValueChange(t *testing.T) { - f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - - powers := []int64{10, 20} - var validators [2]types.Validator - for i, power := range powers { - validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - - } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - - // test single value change - // tendermintUpdate set: {} -> {c1'} - validators[0].Status = types.Bonded - validators[0].Tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 600) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) -} - -func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) { - powers := []int64{10, 20} - // TODO: use it in other places - f, _, _, validators := initValidators(t, 1000, 20, powers) - - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - - // test multiple value change - // tendermintUpdate set: {c1, c3} -> {c1', c3'} - delTokens1 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 190) - delTokens2 := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 80) - validators[0], _ = validators[0].AddTokensFromDel(delTokens1) - validators[1], _ = validators[1].AddTokensFromDel(delTokens2) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) -} - -func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) { - powers := []int64{10, 20, 5, 15, 25} - f, _, _, validators := initValidators(t, 1000, 20, powers) - - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - - // test validator added at the beginning - // tendermintUpdate set: {} -> {c0} - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[2])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[2])) - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) - assert.NilError(t, err) - validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) - assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - - // test validator added at the beginning - // tendermintUpdate set: {} -> {c0} - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[3])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[3])) - updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - val3bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[3].GetOperator()) - assert.NilError(t, err) - validators[3], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val3bz) - assert.DeepEqual(t, validators[3].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - - // test validator added at the end - // tendermintUpdate set: {} -> {c0} - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[4])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[4])) - updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - val4bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[4].GetOperator()) - assert.NilError(t, err) - validators[4], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val4bz) - assert.DeepEqual(t, validators[4].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) -} - -func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) { - f, addrs, _ := bootstrapValidatorTest(t, 1000, 20) - params := types.DefaultParams() - params.MaxValidators = 2 - err := f.stakingKeeper.Params.Set(f.sdkCtx, params) - assert.NilError(t, err) - powers := []int64{10, 20, 5} - var validators [5]types.Validator - for i, power := range powers { - validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[1], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - - // test validator added at the end but not inserted in the valset - // tendermintUpdate set: {} -> {} - keeper.TestingUpdateValidator(f.stakingKeeper, f.sdkCtx, validators[2], false) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) - - // test validator change its power and become a gotValidator (pushing out an existing) - // tendermintUpdate set: {} -> {c0, c4} - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) - - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 10) - validators[2], _ = validators[2].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[2])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[2])) - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) - assert.NilError(t, err) - validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdateZero(), updates[1]) - assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) -} - -func TestApplyAndReturnValidatorSetUpdatesNewValidator(t *testing.T) { - f, _, _ := bootstrapValidatorTest(t, 1000, 20) - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - params.MaxValidators = uint32(3) - - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) - - powers := []int64{100, 100} - var validators [2]types.Validator - - // initialize some validators into the state - for i, power := range powers { - valPubKey := PKs[i+1] - valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) - - validators[i] = testutil.NewValidator(t, valAddr, valPubKey) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) - } - - // verify initial CometBFT updates are correct - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, len(validators)) - - val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) - assert.NilError(t, err) - val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) - assert.NilError(t, err) - validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) - validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) - - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) - - // update initial validator set - for i, power := range powers { - - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[i])) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) - } - - // add a new validator that goes from zero power, to non-zero power, back to - // zero power - valPubKey := PKs[len(validators)+1] - valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) - amt := math.NewInt(100) - - validator := testutil.NewValidator(t, valAddr, valPubKey) - validator, _ = validator.AddTokensFromDel(amt) - - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) - - validator, _ = validator.RemoveDelShares(math.LegacyNewDecFromInt(amt)) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validator)) - - // add a new validator that increases in power - valPubKey = PKs[len(validators)+2] - valAddr = sdk.ValAddress(valPubKey.Address().Bytes()) - - validator = testutil.NewValidator(t, valAddr, valPubKey) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 500) - validator, _ = validator.AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validator)) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validator)) - - // verify initial CometBFT updates are correct - updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, len(validators)+1) - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validator.GetOperator()) - assert.NilError(t, err) - validator, _ = f.stakingKeeper.GetValidator(f.sdkCtx, valbz) - validators[0], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) - validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.DeepEqual(t, validator.ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[2]) -} - -func TestApplyAndReturnValidatorSetUpdatesBondTransition(t *testing.T) { - f, _, _ := bootstrapValidatorTest(t, 1000, 20) - params, err := f.stakingKeeper.Params.Get(f.sdkCtx) - assert.NilError(t, err) - params.MaxValidators = uint32(2) - - assert.NilError(t, f.stakingKeeper.Params.Set(f.sdkCtx, params)) - - powers := []int64{100, 200, 300} - var validators [3]types.Validator - - // initialize some validators into the state - for i, power := range powers { - moniker := fmt.Sprintf("%d", i) - valPubKey := PKs[i+1] - valAddr := sdk.ValAddress(valPubKey.Address().Bytes()) - - validators[i] = newMonikerValidator(t, valAddr, valPubKey, moniker) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, power) - validators[i], _ = validators[i].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[i])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[i])) - } - - // verify initial CometBFT updates are correct - updates := applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 2) - val1bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[1].GetOperator()) - assert.NilError(t, err) - val2bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[2].GetOperator()) - assert.NilError(t, err) - validators[2], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val2bz) - validators[1], _ = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.DeepEqual(t, validators[2].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[1]) - - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) - - // delegate to validator with lowest power but not enough to bond - f.sdkCtx = f.sdkCtx.WithBlockHeight(1) - - val0bz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[0].GetOperator()) - assert.NilError(t, err) - validators[0], err = f.stakingKeeper.GetValidator(f.sdkCtx, val0bz) - assert.NilError(t, err) - - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) - tokens := f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 1) - validators[0], _ = validators[0].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) - - // verify initial CometBFT updates are correct - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) - - // create a series of events that will bond and unbond the validator with - // lowest power in a single block context (height) - f.sdkCtx = f.sdkCtx.WithBlockHeight(2) - - validators[1], err = f.stakingKeeper.GetValidator(f.sdkCtx, val1bz) - assert.NilError(t, err) - - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[0])) - validators[0], _ = validators[0].RemoveDelShares(validators[0].DelegatorShares) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[0])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[0])) - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) - - assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.sdkCtx, validators[1])) - tokens = f.stakingKeeper.TokensFromConsensusPower(f.sdkCtx, 250) - validators[1], _ = validators[1].AddTokensFromDel(tokens) - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, validators[1])) - assert.NilError(t, f.stakingKeeper.SetValidatorByPowerIndex(f.sdkCtx, validators[1])) - - // verify initial CometBFT updates are correct - updates = applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 1) - assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.sdkCtx)), updates[0]) - - applyValidatorSetUpdates(t, f.sdkCtx, f.stakingKeeper, 0) -} - -func applyValidatorSetUpdates(t *testing.T, ctx sdk.Context, k *keeper.Keeper, expectedUpdatesLen int) []module.ValidatorUpdate { - t.Helper() - updates, err := k.ApplyAndReturnValidatorSetUpdates(ctx) - assert.NilError(t, err) - if expectedUpdatesLen >= 0 { - assert.Equal(t, expectedUpdatesLen, len(updates), "%v", updates) - } - return updates -} diff --git a/tests/integration/staking/keeper/vote_extensions_test.go b/tests/integration/staking/keeper/vote_extensions_test.go deleted file mode 100644 index fc81126d7b44..000000000000 --- a/tests/integration/staking/keeper/vote_extensions_test.go +++ /dev/null @@ -1,153 +0,0 @@ -package keeper_test - -import ( - "bytes" - "sort" - "testing" - - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" - cmtproto "github.com/cometbft/cometbft/api/cometbft/types/v1" - protoio "github.com/cosmos/gogoproto/io" - "github.com/cosmos/gogoproto/proto" - gogotypes "github.com/cosmos/gogoproto/types" - "gotest.tools/v3/assert" - - "cosmossdk.io/core/comet" - "cosmossdk.io/core/header" - "cosmossdk.io/math" - "cosmossdk.io/x/staking/testutil" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/baseapp" - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - sdk "github.com/cosmos/cosmos-sdk/types" -) - -const chainID = "chain-id-123" - -// TestValidateVoteExtensions is a unit test function that tests the validation of vote extensions. -// It sets up the necessary fixtures and validators, generates vote extensions for each validator, -// and validates the vote extensions using the baseapp.ValidateVoteExtensions function. -func TestValidateVoteExtensions(t *testing.T) { - t.Parallel() - f := initFixture(t) - - // enable vote extensions - cp := simtestutil.DefaultConsensusParams - cp.Feature = &cmtproto.FeatureParams{VoteExtensionsEnableHeight: &gogotypes.Int64Value{Value: 1}} - f.sdkCtx = f.sdkCtx.WithConsensusParams(*cp).WithHeaderInfo(header.Info{Height: 2, ChainID: chainID}) - - // setup the validators - numVals := 1 - privKeys := []cryptotypes.PrivKey{} - for i := 0; i < numVals; i++ { - privKeys = append(privKeys, ed25519.GenPrivKey()) - } - - vals := []stakingtypes.Validator{} - for _, v := range privKeys { - valAddr := sdk.ValAddress(v.PubKey().Address()) - acc := f.accountKeeper.NewAccountWithAddress(f.sdkCtx, sdk.AccAddress(v.PubKey().Address())) - f.accountKeeper.SetAccount(f.sdkCtx, acc) - simtestutil.AddTestAddrsFromPubKeys(f.bankKeeper, f.stakingKeeper, f.sdkCtx, []cryptotypes.PubKey{v.PubKey()}, math.NewInt(100000000000)) - vals = append(vals, testutil.NewValidator(t, valAddr, v.PubKey())) - } - - votes := []abci.ExtendedVoteInfo{} - - for i, v := range vals { - v.Tokens = math.NewInt(1000000) - v.Status = stakingtypes.Bonded - assert.NilError(t, f.stakingKeeper.SetValidator(f.sdkCtx, v)) - assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.sdkCtx, v)) - assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.sdkCtx, v)) - _, err := f.stakingKeeper.Delegate(f.sdkCtx, sdk.AccAddress(privKeys[i].PubKey().Address()), v.Tokens, stakingtypes.Unbonded, v, true) - assert.NilError(t, err) - - // each val produces a vote - voteExt := []byte("something" + v.OperatorAddress) - cve := cmtproto.CanonicalVoteExtension{ - Extension: voteExt, - Height: f.sdkCtx.HeaderInfo().Height - 1, // the vote extension was signed in the previous height - Round: 0, - ChainId: chainID, - } - - extSignBytes, err := mashalVoteExt(&cve) - assert.NilError(t, err) - - sig, err := privKeys[i].Sign(extSignBytes) - assert.NilError(t, err) - - valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(v.GetOperator()) - assert.NilError(t, err) - ve := abci.ExtendedVoteInfo{ - Validator: abci.Validator{ - Address: valbz, - Power: 1000, - }, - VoteExtension: voteExt, - ExtensionSignature: sig, - BlockIdFlag: cmtproto.BlockIDFlagCommit, - } - votes = append(votes, ve) - } - - eci, ci := extendedCommitToLastCommit(abci.ExtendedCommitInfo{Round: 0, Votes: votes}) - f.sdkCtx = f.sdkCtx.WithCometInfo(ci) - - err := baseapp.ValidateVoteExtensions(f.sdkCtx, f.stakingKeeper, eci) - assert.NilError(t, err) -} - -func mashalVoteExt(msg proto.Message) ([]byte, error) { - var buf bytes.Buffer - if err := protoio.NewDelimitedWriter(&buf).WriteMsg(msg); err != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -func extendedCommitToLastCommit(ec abci.ExtendedCommitInfo) (abci.ExtendedCommitInfo, comet.Info) { - // sort the extended commit info - sort.Sort(extendedVoteInfos(ec.Votes)) - - // convert the extended commit info to last commit info - lastCommit := comet.CommitInfo{ - Round: ec.Round, - Votes: make([]comet.VoteInfo, len(ec.Votes)), - } - - for i, vote := range ec.Votes { - lastCommit.Votes[i] = comet.VoteInfo{ - Validator: comet.Validator{ - Address: vote.Validator.Address, - Power: vote.Validator.Power, - }, - } - } - - return ec, comet.Info{ - LastCommit: lastCommit, - } -} - -type extendedVoteInfos []abci.ExtendedVoteInfo - -func (v extendedVoteInfos) Len() int { - return len(v) -} - -func (v extendedVoteInfos) Less(i, j int) bool { - if v[i].Validator.Power == v[j].Validator.Power { - return bytes.Compare(v[i].Validator.Address, v[j].Validator.Address) == -1 - } - return v[i].Validator.Power > v[j].Validator.Power -} - -func (v extendedVoteInfos) Swap(i, j int) { - v[i], v[j] = v[j], v[i] -} diff --git a/tests/integration/staking/module_test.go b/tests/integration/staking/module_test.go deleted file mode 100644 index 4eaaefd0be3e..000000000000 --- a/tests/integration/staking/module_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package staking - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "cosmossdk.io/depinject" - "cosmossdk.io/log" - "cosmossdk.io/x/staking/types" - - simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" - authKeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -func TestItCreatesModuleAccountOnInitBlock(t *testing.T) { - var accountKeeper authKeeper.AccountKeeper - app, err := simtestutil.SetupAtGenesis( - depinject.Configs( - AppConfig, - depinject.Supply(log.NewNopLogger()), - ), &accountKeeper) - require.NoError(t, err) - - ctx := app.BaseApp.NewContext(false) - acc := accountKeeper.GetAccount(ctx, authtypes.NewModuleAddress(types.BondedPoolName)) - require.NotNil(t, acc) - - acc = accountKeeper.GetAccount(ctx, authtypes.NewModuleAddress(types.NotBondedPoolName)) - require.NotNil(t, acc) -} diff --git a/tests/integration/v2/staking/delegation_test.go b/tests/integration/v2/staking/delegation_test.go index 3f35beea7021..6653beca8e38 100644 --- a/tests/integration/v2/staking/delegation_test.go +++ b/tests/integration/v2/staking/delegation_test.go @@ -49,7 +49,7 @@ func TestUnbondingDelegationsMaxEntries(t *testing.T) { validator, issuedShares := validator.AddTokensFromDel(startTokens) assert.DeepEqual(t, startTokens, issuedShares.RoundInt()) - validator = keeper.TestingUpdateValidator(f.stakingKeeper, ctx, validator, true) + validator, _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, ctx, validator, true) assert.Assert(math.IntEq(t, startTokens, validator.BondedTokens())) assert.Assert(t, validator.IsBonded()) diff --git a/tests/integration/v2/staking/slash_test.go b/tests/integration/v2/staking/slash_test.go index 5ddba3ecb100..2567a9d9d225 100644 --- a/tests/integration/v2/staking/slash_test.go +++ b/tests/integration/v2/staking/slash_test.go @@ -57,7 +57,7 @@ func bootstrapSlashTest(t *testing.T, power int64) (*fixture, []sdk.AccAddress, for i := int64(0); i < numVals; i++ { validator := testutil.NewValidator(t, addrVals[i], PKs[i]) validator, _ = validator.AddTokensFromDel(amt) - validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validator, true) + validator, _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validator, true) assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, validator)) } diff --git a/tests/integration/v2/staking/unbonding_test.go b/tests/integration/v2/staking/unbonding_test.go index 761991d2c304..7f8303a1ec6c 100644 --- a/tests/integration/v2/staking/unbonding_test.go +++ b/tests/integration/v2/staking/unbonding_test.go @@ -71,7 +71,7 @@ func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uin validator1, issuedShares1 := validator1.AddTokensFromDel(valTokens) assert.DeepEqual(t, valTokens, issuedShares1.RoundInt()) - validator1 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validator1, true) + validator1, _ = stakingkeeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validator1, true) assert.Assert(math.IntEq(t, valTokens, validator1.BondedTokens())) assert.Assert(t, validator1.IsBonded()) @@ -84,7 +84,7 @@ func SetupUnbondingTests(t *testing.T, f *fixture, hookCalled *bool, ubdeID *uin validator2, issuedShares2 := validator2.AddTokensFromDel(valTokens) assert.DeepEqual(t, valTokens, issuedShares2.RoundInt()) - validator2 = stakingkeeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validator2, true) + validator2, _ = stakingkeeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validator2, true) assert.Equal(t, types.Bonded, validator2.Status) assert.Assert(t, validator2.IsBonded()) diff --git a/tests/integration/v2/staking/validator_test.go b/tests/integration/v2/staking/validator_test.go index 712b9f6ae621..791d1a1fb238 100644 --- a/tests/integration/v2/staking/validator_test.go +++ b/tests/integration/v2/staking/validator_test.go @@ -97,7 +97,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { delTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, int64((i+1)*10)) val, _ = val.AddTokensFromDel(delTokens) - val = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, val, true) + val, _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, val, true) validators[i] = val } @@ -108,7 +108,7 @@ func TestUpdateBondedValidatorsDecreaseCliff(t *testing.T) { assert.NilError(t, f.stakingKeeper.DeleteValidatorByPowerIndex(f.ctx, nextCliffVal)) shares := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 21) nextCliffVal, _ = nextCliffVal.RemoveDelShares(math.LegacyNewDecFromInt(shares)) - _ = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, nextCliffVal, true) + _, _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, nextCliffVal, true) expectedValStatus := map[int]sdk.BondStatus{ 9: sdk.Bonded, 8: sdk.Bonded, 7: sdk.Bonded, 5: sdk.Bonded, 4: sdk.Bonded, @@ -148,7 +148,7 @@ func TestSlashToZeroPowerRemoved(t *testing.T) { assert.Equal(t, types.Unbonded, validator.Status) assert.DeepEqual(t, valTokens, validator.Tokens) assert.NilError(t, f.stakingKeeper.SetValidatorByConsAddr(f.ctx, validator)) - validator = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validator, true) + validator, _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validator, true) assert.DeepEqual(t, valTokens, validator.Tokens) // slash the validator by 100% @@ -180,7 +180,7 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { validators[i].Status = types.Bonded validators[i].Tokens = amt validators[i].DelegatorShares = math.LegacyNewDecFromInt(amt) - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[i], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[i], true) } // first make sure everything made it in to the gotValidator group @@ -200,7 +200,7 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { // test a basic increase in voting power validators[3].Tokens = math.NewInt(500).Mul(f.stakingKeeper.PowerReduction(f.ctx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[3], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) @@ -208,7 +208,7 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { // test a decrease in voting power validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.ctx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[3], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) @@ -218,7 +218,7 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { // test equal voting power, different age validators[3].Tokens = math.NewInt(200).Mul(f.stakingKeeper.PowerReduction(f.ctx)) f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 10}) - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[3], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) @@ -227,7 +227,7 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { // no change in voting power - no change in sort f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 20}) - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[4], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[4], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) @@ -237,12 +237,12 @@ func TestGetValidatorSortingUnmixed(t *testing.T) { // change in voting power of both validators, both still in v-set, no age change validators[3].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.ctx)) validators[4].Tokens = math.NewInt(300).Mul(f.stakingKeeper.PowerReduction(f.ctx)) - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[3], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n) f.ctx = integration.SetHeaderInfo(f.ctx, header.Info{Height: 30}) - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[4], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[4], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, len(resValidators), n, "%v", resValidators) @@ -285,7 +285,7 @@ func TestGetValidatorSortingMixed(t *testing.T) { validators[i].DelegatorShares = math.LegacyNewDecFromInt(amt) validators[i].Status = types.Bonded validators[i].Tokens = amt - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[i], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[i], true) } val0, found := f.stakingKeeper.GetValidator(f.ctx, sdk.ValAddress(addrs[0])) @@ -338,7 +338,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { notBondedPool := f.stakingKeeper.GetNotBondedPool(f.ctx) assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, tokens)))) f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) - validators[i] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[i], true) + validators[i], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[i], true) } // ensure that the first two bonded validators are the largest validators @@ -362,7 +362,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { // test that the two largest validators are // a) validator 0 with 500 tokens // b) validator 2 with 400 tokens (delegated before validator 3) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], true) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) @@ -394,7 +394,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), newTokens)) f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + validators[3], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[3], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) @@ -410,7 +410,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, bondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, rmTokens)))) f.accountKeeper.SetModuleAccount(f.ctx, bondedPool) - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + validators[3], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[3], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) @@ -425,7 +425,7 @@ func TestGetValidatorsEdgeCases(t *testing.T) { assert.NilError(t, banktestutil.FundModuleAccount(f.ctx, f.bankKeeper, notBondedPool.GetName(), sdk.NewCoins(sdk.NewCoin(params.BondDenom, math.NewInt(200))))) f.accountKeeper.SetModuleAccount(f.ctx, notBondedPool) - validators[3] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[3], true) + validators[3], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[3], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, nMax, uint32(len(resValidators))) @@ -456,13 +456,13 @@ func TestValidatorBondHeight(t *testing.T) { validators[1], _ = validators[1].AddTokensFromDel(tokens1) validators[2], _ = validators[2].AddTokensFromDel(tokens2) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], true) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], true) //////////////////////////////////////// // If two validators both increase to the same voting power in the same block, // the one with the first transaction should become bonded - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], true) - validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[2], true) + validators[1], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], true) + validators[2], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[2], true) resValidators, err := f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) @@ -475,11 +475,11 @@ func TestValidatorBondHeight(t *testing.T) { delTokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 50) validators[1], _ = validators[1].AddTokensFromDel(delTokens) validators[2], _ = validators[2].AddTokensFromDel(delTokens) - validators[2] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[2], true) + validators[2], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[2], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, params.MaxValidators, uint32(len(resValidators))) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], true) + validators[1], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], true) assert.Assert(ValEq(t, validators[0], resValidators[0])) assert.Assert(ValEq(t, validators[2], resValidators[1])) } @@ -499,7 +499,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { validators[i] = testutil.NewValidator(t, sdk.ValAddress(addrs[i]), PKs[i]) tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[i], true) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[i], true) } for i := range powers { valbz, err := f.stakingKeeper.ValidatorAddressCodec().StringToBytes(validators[i].GetOperator()) @@ -523,7 +523,7 @@ func TestFullValidatorSetPowerChange(t *testing.T) { tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 600) validators[0], _ = validators[0].AddTokensFromDel(tokens) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], true) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], true) resValidators, err = f.stakingKeeper.GetBondedValidatorsByPower(f.ctx) assert.NilError(t, err) assert.Equal(t, max, len(resValidators)) @@ -576,14 +576,14 @@ func TestApplyAndReturnValidatorSetUpdatesIdentical(t *testing.T) { validators[i], _ = validators[i].AddTokensFromDel(tokens) } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], false) + validators[1], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], false) applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test identical, // tendermintUpdate set: {} -> {} - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], false) + validators[1], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], false) applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) } @@ -599,15 +599,15 @@ func TestApplyAndReturnValidatorSetUpdatesSingleValueChange(t *testing.T) { validators[i], _ = validators[i].AddTokensFromDel(tokens) } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], false) + validators[1], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], false) applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test single value change // tendermintUpdate set: {} -> {c1'} validators[0].Status = types.Bonded validators[0].Tokens = f.stakingKeeper.TokensFromConsensusPower(f.ctx, 600) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], false) updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 1) assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) @@ -618,8 +618,8 @@ func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) { // TODO: use it in other places f, _, _, validators := initValidators(t, 1000, 20, powers) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], false) + validators[1], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], false) applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test multiple value change @@ -628,10 +628,20 @@ func TestApplyAndReturnValidatorSetUpdatesMultipleValueChange(t *testing.T) { delTokens2 := f.stakingKeeper.TokensFromConsensusPower(f.ctx, 80) validators[0], _ = validators[0].AddTokensFromDel(delTokens1) validators[1], _ = validators[1].AddTokensFromDel(delTokens2) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) - updates := applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) + updates := []module.ValidatorUpdate{} + val1, val1Updates := keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], true) + assert.Equal(t, 1, len(val1Updates)) + validators[0] = val1 + updates = append(updates, val1Updates...) + + val2, val2Updates := keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], true) + assert.Equal(t, 1, len(val2Updates)) + validators[1] = val2 + updates = append(updates, val2Updates...) + + assert.Equal(t, 2, len(updates)) + assert.DeepEqual(t, validators[0].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[0]) assert.DeepEqual(t, validators[1].ModuleValidatorUpdate(f.stakingKeeper.PowerReduction(f.ctx)), updates[1]) } @@ -640,8 +650,8 @@ func TestApplyAndReturnValidatorSetUpdatesInserted(t *testing.T) { powers := []int64{10, 20, 5, 15, 25} f, _, _, validators := initValidators(t, 1000, 20, powers) - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], false) + validators[1], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], false) applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test validator added at the beginning @@ -688,13 +698,13 @@ func TestApplyAndReturnValidatorSetUpdatesWithCliffValidator(t *testing.T) { tokens := f.stakingKeeper.TokensFromConsensusPower(f.ctx, power) validators[i], _ = validators[i].AddTokensFromDel(tokens) } - validators[0] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[0], false) - validators[1] = keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[1], false) + validators[0], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[0], false) + validators[1], _ = keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[1], false) applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 2) // test validator added at the end but not inserted in the valset // tendermintUpdate set: {} -> {} - keeper.TestingUpdateValidator(f.stakingKeeper, f.ctx, validators[2], false) + keeper.TestingUpdateValidatorV2(f.stakingKeeper, f.ctx, validators[2], false) applyValidatorSetUpdates(t, f.ctx, f.stakingKeeper, 0) // test validator change its power and become a gotValidator (pushing out an existing) diff --git a/tests/integration/v2/staking/vote_extensions_test.go b/tests/integration/v2/staking/vote_extensions_test.go index 1695c27c93c6..52637558eead 100644 --- a/tests/integration/v2/staking/vote_extensions_test.go +++ b/tests/integration/v2/staking/vote_extensions_test.go @@ -32,7 +32,7 @@ const chainID = "chain-id-123" // and validates the vote extensions using the baseapp.ValidateVoteExtensions function. func TestValidateVoteExtensions(t *testing.T) { t.Parallel() - f := initFixture(t, false) + f := initFixture(t, true) // enable vote extensions cp := simtestutil.DefaultConsensusParams diff --git a/x/staking/keeper/test_common.go b/x/staking/keeper/test_common.go index 55453758ea88..a6e2fad5a202 100644 --- a/x/staking/keeper/test_common.go +++ b/x/staking/keeper/test_common.go @@ -4,10 +4,12 @@ import ( "bytes" "context" + appmodulev2 "cosmossdk.io/core/appmodule/v2" storetypes "cosmossdk.io/store/types" "cosmossdk.io/x/staking/types" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/types/module" ) // ValidatorByPowerIndexExists does a certain by-power index record exist @@ -21,7 +23,7 @@ func ValidatorByPowerIndexExists(ctx context.Context, keeper *Keeper, power []by } // TestingUpdateValidator updates a validator for testing -func TestingUpdateValidator(keeper *Keeper, ctx context.Context, validator types.Validator, apply bool) types.Validator { +func TestingUpdateValidator(keeper *Keeper, ctx sdk.Context, validator types.Validator, apply bool) types.Validator { err := keeper.SetValidator(ctx, validator) if err != nil { panic(err) @@ -62,8 +64,7 @@ func TestingUpdateValidator(keeper *Keeper, ctx context.Context, validator types } if !apply { - sdkCtx := sdk.UnwrapSDKContext(ctx) - ctx, _ = sdkCtx.CacheContext() + ctx, _ = ctx.CacheContext() } _, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx) if err != nil { @@ -77,3 +78,61 @@ func TestingUpdateValidator(keeper *Keeper, ctx context.Context, validator types return validator } + +// TestingUpdateValidatorV2 updates a validator in v2 for testing +func TestingUpdateValidatorV2(keeper *Keeper, ctx context.Context, validator types.Validator, apply bool) (types.Validator, []module.ValidatorUpdate) { + err := keeper.SetValidator(ctx, validator) + if err != nil { + panic(err) + } + + // Remove any existing power key for validator. + store := keeper.KVStoreService.OpenKVStore(ctx) + deleted := false + + iterator, err := store.Iterator(types.ValidatorsByPowerIndexKey, storetypes.PrefixEndBytes(types.ValidatorsByPowerIndexKey)) + if err != nil { + panic(err) + } + defer iterator.Close() + + bz, err := keeper.validatorAddressCodec.StringToBytes(validator.GetOperator()) + if err != nil { + panic(err) + } + + for ; iterator.Valid(); iterator.Next() { + valAddr := types.ParseValidatorPowerRankKey(iterator.Key()) + if bytes.Equal(valAddr, bz) { + if deleted { + panic("found duplicate power index key") + } else { + deleted = true + } + + if err = store.Delete(iterator.Key()); err != nil { + panic(err) + } + } + } + + if err = keeper.SetValidatorByPowerIndex(ctx, validator); err != nil { + panic(err) + } + + var updates []appmodulev2.ValidatorUpdate + + if apply { + updates, err = keeper.ApplyAndReturnValidatorSetUpdates(ctx) + if err != nil { + panic(err) + } + } + + validator, err = keeper.GetValidator(ctx, sdk.ValAddress(bz)) + if err != nil { + panic(err) + } + + return validator, updates +} From efedcde2109a0adbbc23b23fa1779f87936ddec8 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Fri, 13 Dec 2024 12:33:42 +0530 Subject: [PATCH 08/13] fix lint and remove unused --- tests/integration/v2/staking/common_test.go | 18 ++++++++---------- .../v2/staking/deterministic_test.go | 9 ++------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/tests/integration/v2/staking/common_test.go b/tests/integration/v2/staking/common_test.go index 4776cef7bc60..9880aa48b975 100644 --- a/tests/integration/v2/staking/common_test.go +++ b/tests/integration/v2/staking/common_test.go @@ -11,9 +11,16 @@ import ( "cosmossdk.io/log" "cosmossdk.io/math" storetypes "cosmossdk.io/store/types" + _ "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" + _ "cosmossdk.io/x/consensus" // import as blank for app wiring consensuskeeper "cosmossdk.io/x/consensus/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/staking" // import as blank for app wiring stakingkeeper "cosmossdk.io/x/staking/keeper" "cosmossdk.io/x/staking/testutil" "cosmossdk.io/x/staking/types" @@ -23,17 +30,8 @@ import ( "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" - - _ "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/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/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 ) diff --git a/tests/integration/v2/staking/deterministic_test.go b/tests/integration/v2/staking/deterministic_test.go index 973b48c1e569..b91a89416de8 100644 --- a/tests/integration/v2/staking/deterministic_test.go +++ b/tests/integration/v2/staking/deterministic_test.go @@ -7,26 +7,24 @@ import ( "testing" "time" + "github.com/cosmos/gogoproto/proto" "gotest.tools/v3/assert" "pgregory.net/rapid" "cosmossdk.io/core/gas" "cosmossdk.io/math" - storetypes "cosmossdk.io/store/types" bankkeeper "cosmossdk.io/x/bank/keeper" banktestutil "cosmossdk.io/x/bank/testutil" minttypes "cosmossdk.io/x/mint/types" stakingkeeper "cosmossdk.io/x/staking/keeper" stakingtypes "cosmossdk.io/x/staking/types" - "github.com/cosmos/cosmos-sdk/codec" codectypes "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" "github.com/cosmos/cosmos-sdk/tests/integration/v2" "github.com/cosmos/cosmos-sdk/testutil/testdata" sdk "github.com/cosmos/cosmos-sdk/types" authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" - "github.com/cosmos/gogoproto/proto" ) var ( @@ -43,9 +41,7 @@ var ( type deterministicFixture struct { app *integration.App - ctx context.Context - cdc codec.Codec - keys map[string]*storetypes.KVStoreKey + ctx context.Context accountKeeper authkeeper.AccountKeeper bankKeeper bankkeeper.Keeper @@ -94,7 +90,6 @@ func initDeterministicFixture(t *testing.T) *deterministicFixture { df := deterministicFixture{ app: f.app, ctx: ctx, - cdc: f.cdc, accountKeeper: f.accountKeeper, bankKeeper: f.bankKeeper, stakingKeeper: f.stakingKeeper, From f21a8394cf4395c98e8f64129aa393113a0faa9e Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Fri, 13 Dec 2024 12:37:28 +0530 Subject: [PATCH 09/13] revert comment --- tests/integration/v2/staking/genesis_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/v2/staking/genesis_test.go b/tests/integration/v2/staking/genesis_test.go index 35a0a92bec4d..9a5f13b575a1 100644 --- a/tests/integration/v2/staking/genesis_test.go +++ b/tests/integration/v2/staking/genesis_test.go @@ -81,7 +81,7 @@ func TestInitGenesis(t *testing.T) { // append new bonded validators to the list validators = append(validators, bondedVal1, bondedVal2) - // mint coins in the bonded pool representing the validators coins, ignore genesis validator + // mint coins in the bonded pool representing the validators coins i2 := len(validators) assert.NilError(t, banktestutil.FundModuleAccount( From 73be24a7e37b90f70fc6badaedaaaef58eda6fcc Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Fri, 13 Dec 2024 12:50:07 +0530 Subject: [PATCH 10/13] fix failing test --- tests/integration/v2/staking/msg_server_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/v2/staking/msg_server_test.go b/tests/integration/v2/staking/msg_server_test.go index 01577438235d..21012a47af30 100644 --- a/tests/integration/v2/staking/msg_server_test.go +++ b/tests/integration/v2/staking/msg_server_test.go @@ -199,7 +199,7 @@ func TestRotateConsPubKey(t *testing.T) { err = stakingKeeper.Params.Set(ctx, params) assert.NilError(t, err) - addrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 5, stakingKeeper.TokensFromConsensusPower(ctx, 100)) + addrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 5, stakingKeeper.TokensFromConsensusPower(ctx, 1000)) valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) // create 5 validators From de7a18bc272e4b289527ab94046492efdc99e2f2 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Fri, 13 Dec 2024 14:46:00 +0530 Subject: [PATCH 11/13] fix vote extensions test --- baseapp/abci_utils.go | 29 +++++++++++++++---- .../v2/staking/vote_extensions_test.go | 11 ++++--- x/staking/keeper/test_common.go | 3 +- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/baseapp/abci_utils.go b/baseapp/abci_utils.go index bc0cb9daccdd..7a2f8e8bd75d 100644 --- a/baseapp/abci_utils.go +++ b/baseapp/abci_utils.go @@ -15,6 +15,7 @@ import ( "github.com/cosmos/gogoproto/proto" "cosmossdk.io/core/comet" + "cosmossdk.io/core/header" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" @@ -46,11 +47,29 @@ func ValidateVoteExtensions( valStore ValidatorStore, extCommit abci.ExtendedCommitInfo, ) error { - // Get values from context - cp := ctx.ConsensusParams() //nolint:staticcheck // ignore linting error - currentHeight := ctx.HeaderInfo().Height - chainID := ctx.HeaderInfo().ChainID - commitInfo := ctx.CometInfo().LastCommit + return ValidateVoteExtensionsWithParams( + ctx, + ctx.ConsensusParams(), //nolint:staticcheck // ignore linting error + ctx.HeaderInfo(), + ctx.CometInfo(), + valStore, + extCommit, + ) +} + +// ValidateVoteExtensionsWithParams defines a helper function for verifying vote extension +// signatures with consensus params, header info and comet info taken as input +func ValidateVoteExtensionsWithParams( + ctx context.Context, + cp cmtproto.ConsensusParams, + headerInfo header.Info, + cometInfo comet.Info, + valStore ValidatorStore, + extCommit abci.ExtendedCommitInfo, +) error { + currentHeight := headerInfo.Height + chainID := headerInfo.ChainID + commitInfo := cometInfo.LastCommit // Check that both extCommit + commit are ordered in accordance with vp/address. if err := validateExtendedCommitAgainstLastCommit(extCommit, commitInfo); err != nil { diff --git a/tests/integration/v2/staking/vote_extensions_test.go b/tests/integration/v2/staking/vote_extensions_test.go index 52637558eead..0769b7e48cae 100644 --- a/tests/integration/v2/staking/vote_extensions_test.go +++ b/tests/integration/v2/staking/vote_extensions_test.go @@ -18,6 +18,7 @@ import ( "cosmossdk.io/x/staking/testutil" stakingtypes "cosmossdk.io/x/staking/types" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" "github.com/cosmos/cosmos-sdk/tests/integration/v2" @@ -98,14 +99,12 @@ func TestValidateVoteExtensions(t *testing.T) { votes = append(votes, ve) } - _, ci := extendedCommitToLastCommit(abci.ExtendedCommitInfo{Round: 0, Votes: votes}) + eci, ci := extendedCommitToLastCommit(abci.ExtendedCommitInfo{Round: 0, Votes: votes}) f.ctx = integration.SetCometInfo(f.ctx, ci) - t.Skip("cannot use integration app context in ValidateVoteExtensions") - - // TODO: uncomment below code once ValidateVoteExtensions supports app context - // err := baseapp.ValidateVoteExtensions(f.ctx, f.stakingKeeper, eci) - // assert.NilError(t, err) + err := baseapp.ValidateVoteExtensionsWithParams(f.ctx, *cp, + integration.HeaderInfoFromContext(f.ctx), ci, f.stakingKeeper, eci) + assert.NilError(t, err) } func mashalVoteExt(msg proto.Message) ([]byte, error) { diff --git a/x/staking/keeper/test_common.go b/x/staking/keeper/test_common.go index a6e2fad5a202..213c0d81e3dc 100644 --- a/x/staking/keeper/test_common.go +++ b/x/staking/keeper/test_common.go @@ -9,7 +9,6 @@ import ( "cosmossdk.io/x/staking/types" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" ) // ValidatorByPowerIndexExists does a certain by-power index record exist @@ -80,7 +79,7 @@ func TestingUpdateValidator(keeper *Keeper, ctx sdk.Context, validator types.Val } // TestingUpdateValidatorV2 updates a validator in v2 for testing -func TestingUpdateValidatorV2(keeper *Keeper, ctx context.Context, validator types.Validator, apply bool) (types.Validator, []module.ValidatorUpdate) { +func TestingUpdateValidatorV2(keeper *Keeper, ctx context.Context, validator types.Validator, apply bool) (types.Validator, []appmodulev2.ValidatorUpdate) { err := keeper.SetValidator(ctx, validator) if err != nil { panic(err) From c3c0b90d718f1b263b814c5d5d7be80b3a2adbf7 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Fri, 13 Dec 2024 15:02:06 +0530 Subject: [PATCH 12/13] fix flaky test --- tests/integration/v2/staking/msg_server_test.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/integration/v2/staking/msg_server_test.go b/tests/integration/v2/staking/msg_server_test.go index 21012a47af30..e43c01359c76 100644 --- a/tests/integration/v2/staking/msg_server_test.go +++ b/tests/integration/v2/staking/msg_server_test.go @@ -199,7 +199,7 @@ func TestRotateConsPubKey(t *testing.T) { err = stakingKeeper.Params.Set(ctx, params) assert.NilError(t, err) - addrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 5, stakingKeeper.TokensFromConsensusPower(ctx, 1000)) + addrs := simtestutil.AddTestAddrsIncremental(bankKeeper, stakingKeeper, ctx, 5, stakingKeeper.TokensFromConsensusPower(ctx, 100)) valAddrs := simtestutil.ConvertAddrsToValAddrs(addrs) // create 5 validators @@ -219,6 +219,10 @@ func TestRotateConsPubKey(t *testing.T) { _, err = stakingKeeper.EndBlocker(ctx) assert.NilError(t, err) + _, state := f.app.Deliver(t, ctx, nil) + _, err = f.app.Commit(state) + assert.NilError(t, err) + params, err = stakingKeeper.Params.Get(ctx) assert.NilError(t, err) From 837866770d297f60a8e5a5b83a85ef7b17ec05e3 Mon Sep 17 00:00:00 2001 From: akhilkumarpilli Date: Fri, 13 Dec 2024 16:26:23 +0530 Subject: [PATCH 13/13] fix flaky test --- tests/integration/v2/staking/msg_server_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/integration/v2/staking/msg_server_test.go b/tests/integration/v2/staking/msg_server_test.go index e43c01359c76..70b7d40df9a0 100644 --- a/tests/integration/v2/staking/msg_server_test.go +++ b/tests/integration/v2/staking/msg_server_test.go @@ -219,10 +219,6 @@ func TestRotateConsPubKey(t *testing.T) { _, err = stakingKeeper.EndBlocker(ctx) assert.NilError(t, err) - _, state := f.app.Deliver(t, ctx, nil) - _, err = f.app.Commit(state) - assert.NilError(t, err) - params, err = stakingKeeper.Params.Get(ctx) assert.NilError(t, err) @@ -230,6 +226,9 @@ func TestRotateConsPubKey(t *testing.T) { assert.NilError(t, err) assert.Equal(t, len(validators) >= 5, true) + // ignore genesis validator + validators = validators[1:] + testCases := []struct { name string malleate func() context.Context