diff --git a/runtime/v2/module.go b/runtime/v2/module.go index 8ef338f52c2a..fcbb671bcecb 100644 --- a/runtime/v2/module.go +++ b/runtime/v2/module.go @@ -18,6 +18,7 @@ import ( "cosmossdk.io/core/branch" "cosmossdk.io/core/comet" "cosmossdk.io/core/event" + "cosmossdk.io/core/gas" "cosmossdk.io/core/header" "cosmossdk.io/core/registry" "cosmossdk.io/core/router" @@ -214,6 +215,7 @@ func ProvideEnvironment( kvService store.KVStoreService, memKvService store.MemoryStoreService, headerService header.Service, + gasService gas.Service, eventService event.Service, branchService branch.Service, routerBuilder RouterServiceBuilder, @@ -222,7 +224,7 @@ func ProvideEnvironment( Logger: logger, BranchService: branchService, EventService: eventService, - GasService: stf.NewGasMeterService(), + GasService: gasService, HeaderService: headerService, QueryRouterService: routerBuilder.BuildQueryRouter(), MsgRouterService: routerBuilder.BuildMsgRouter([]byte(key.Name())), @@ -296,6 +298,7 @@ func DefaultServiceBindings() depinject.Config { eventService = services.NewGenesisEventService(stf.NewEventService()) storeBuilder = root.NewBuilder() branchService = stf.BranchService{} + gasService = stf.NewGasMeterService() ) return depinject.Supply( kvServiceFactory, @@ -305,5 +308,6 @@ func DefaultServiceBindings() depinject.Config { eventService, storeBuilder, branchService, + gasService, ) } diff --git a/tests/go.mod b/tests/go.mod index f5834232cb90..44a6bbc9e160 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -51,6 +51,7 @@ require ( cosmossdk.io/x/staking v0.0.0-20240226161501-23359a0b6d91 github.com/cometbft/cometbft/api v1.0.0-rc2 github.com/cosmos/cosmos-db v1.1.0 + github.com/gogo/protobuf v1.3.2 // indirect github.com/google/go-cmp v0.6.0 github.com/google/gofuzz v1.2.0 github.com/jhump/protoreflect v1.17.0 @@ -126,7 +127,6 @@ require ( github.com/go-logr/stdr v1.2.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gogo/googleapis v1.4.1 // indirect - github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/golang/snappy v0.0.4 // indirect diff --git a/tests/integration/gov/common_test.go b/tests/integration/gov/common_test.go deleted file mode 100644 index b2fe831877ee..000000000000 --- a/tests/integration/gov/common_test.go +++ /dev/null @@ -1,126 +0,0 @@ -package gov_test - -import ( - "bytes" - "log" - "sort" - "testing" - - "github.com/stretchr/testify/require" - "gotest.tools/v3/assert" - - "cosmossdk.io/depinject" - sdklog "cosmossdk.io/log" - "cosmossdk.io/math" - _ "cosmossdk.io/x/accounts" - _ "cosmossdk.io/x/bank" - _ "cosmossdk.io/x/consensus" - "cosmossdk.io/x/gov/types" - v1 "cosmossdk.io/x/gov/types/v1" - "cosmossdk.io/x/gov/types/v1beta1" - _ "cosmossdk.io/x/protocolpool" - _ "cosmossdk.io/x/staking" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" - cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" - "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" - authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" -) - -var ( - valTokens = sdk.TokensFromConsensusPower(42, sdk.DefaultPowerReduction) - TestProposal = v1beta1.NewTextProposal("Test", "description") - TestDescription = stakingtypes.NewDescription("T", "E", "S", "T", "Z", &stakingtypes.Metadata{}) - TestCommissionRates = stakingtypes.NewCommissionRates(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) -) - -// mkTestLegacyContent creates a MsgExecLegacyContent for testing purposes. -func mkTestLegacyContent(t *testing.T) *v1.MsgExecLegacyContent { - t.Helper() - msgContent, err := v1.NewLegacyContent(TestProposal, authtypes.NewModuleAddress(types.ModuleName).String()) - assert.NilError(t, err) - - return msgContent -} - -var pubkeys = []cryptotypes.PubKey{ - ed25519.GenPrivKey().PubKey(), - ed25519.GenPrivKey().PubKey(), - ed25519.GenPrivKey().PubKey(), -} - -// SortAddresses - Sorts Addresses -func SortAddresses(addrs []sdk.AccAddress) { - byteAddrs := make([][]byte, len(addrs)) - - for i, addr := range addrs { - byteAddrs[i] = addr.Bytes() - } - - SortByteArrays(byteAddrs) - - for i, byteAddr := range byteAddrs { - addrs[i] = byteAddr - } -} - -// implement `Interface` in sort package. -type sortByteArrays [][]byte - -func (b sortByteArrays) Len() int { - return len(b) -} - -func (b sortByteArrays) Less(i, j int) bool { - // bytes package already implements Comparable for []byte. - switch bytes.Compare(b[i], b[j]) { - case -1: - return true - case 0, 1: - return false - default: - log.Panic("not fail-able with `bytes.Comparable` bounded [-1, 1].") - return false - } -} - -func (b sortByteArrays) Swap(i, j int) { - b[j], b[i] = b[i], b[j] -} - -// SortByteArrays - sorts the provided byte array -func SortByteArrays(src [][]byte) [][]byte { - sorted := sortByteArrays(src) - sort.Sort(sorted) - return sorted -} - -func createTestSuite(t *testing.T) suite { - t.Helper() - res := suite{} - - app, err := simtestutil.SetupWithConfiguration( - depinject.Configs( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.StakingModule(), - configurator.BankModule(), - configurator.GovModule(), - configurator.ConsensusModule(), - configurator.ProtocolPoolModule(), - ), - depinject.Supply(sdklog.NewNopLogger()), - ), - simtestutil.DefaultStartUpConfig(), - &res.AccountKeeper, &res.BankKeeper, &res.GovKeeper, &res.StakingKeeper, - ) - require.NoError(t, err) - - res.app = app - return res -} diff --git a/tests/integration/gov/keeper/keeper_test.go b/tests/integration/gov/keeper/keeper_test.go deleted file mode 100644 index c40e847cc632..000000000000 --- a/tests/integration/gov/keeper/keeper_test.go +++ /dev/null @@ -1,180 +0,0 @@ -package keeper_test - -import ( - "context" - "testing" - - "go.uber.org/mock/gomock" - - "cosmossdk.io/core/appmodule" - "cosmossdk.io/log" - storetypes "cosmossdk.io/store/types" - "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" - banktypes "cosmossdk.io/x/bank/types" - "cosmossdk.io/x/consensus" - consensusparamkeeper "cosmossdk.io/x/consensus/keeper" - consensusparamtypes "cosmossdk.io/x/consensus/types" - "cosmossdk.io/x/gov" - "cosmossdk.io/x/gov/keeper" - "cosmossdk.io/x/gov/types" - v1 "cosmossdk.io/x/gov/types/v1" - "cosmossdk.io/x/gov/types/v1beta1" - minttypes "cosmossdk.io/x/mint/types" - poolkeeper "cosmossdk.io/x/protocolpool/keeper" - pooltypes "cosmossdk.io/x/protocolpool/types" - "cosmossdk.io/x/staking" - stakingkeeper "cosmossdk.io/x/staking/keeper" - stakingtypes "cosmossdk.io/x/staking/types" - - "github.com/cosmos/cosmos-sdk/baseapp" - 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" - 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" -) - -type fixture struct { - ctx sdk.Context - - queryClient v1.QueryClient - legacyQueryClient v1beta1.QueryClient - - accountKeeper authkeeper.AccountKeeper - bankKeeper bankkeeper.Keeper - stakingKeeper *stakingkeeper.Keeper - govKeeper *keeper.Keeper -} - -func initFixture(tb testing.TB) *fixture { - tb.Helper() - keys := storetypes.NewKVStoreKeys( - authtypes.StoreKey, banktypes.StoreKey, stakingtypes.StoreKey, pooltypes.StoreKey, types.StoreKey, consensusparamtypes.StoreKey, - ) - encodingCfg := moduletestutil.MakeTestEncodingConfig(codectestutil.CodecOptions{}, auth.AppModule{}, bank.AppModule{}, gov.AppModule{}) - cdc := encodingCfg.Codec - - logger := log.NewTestLogger(tb) - authority := authtypes.NewModuleAddress(types.ModuleName) - - maccPerms := map[string][]string{ - pooltypes.ModuleName: {}, - pooltypes.StreamAccount: {}, - pooltypes.ProtocolPoolDistrAccount: {}, - minttypes.ModuleName: {authtypes.Minter}, - stakingtypes.BondedPoolName: {authtypes.Burner, authtypes.Staking}, - stakingtypes.NotBondedPoolName: {authtypes.Burner, authtypes.Staking}, - types.ModuleName: {authtypes.Burner}, - } - - // gomock initializations - ctrl := gomock.NewController(tb) - acctsModKeeper := authtestutil.NewMockAccountsModKeeper(ctrl) - accNum := uint64(0) - acctsModKeeper.EXPECT().NextAccountNumber(gomock.Any()).AnyTimes().DoAndReturn(func(ctx context.Context) (uint64, error) { - currentNum := accNum - accNum++ - return currentNum, nil - }) - - accountKeeper := authkeeper.NewAccountKeeper( - runtime.NewEnvironment(runtime.NewKVStoreService(keys[authtypes.StoreKey]), log.NewNopLogger()), - 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(), - ) - - router := baseapp.NewMsgServiceRouter() - queryRouter := baseapp.NewGRPCQueryRouter() - consensusParamsKeeper := consensusparamkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[consensusparamtypes.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(router)), 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()) - - poolKeeper := poolkeeper.NewKeeper(cdc, runtime.NewEnvironment(runtime.NewKVStoreService(keys[pooltypes.StoreKey]), log.NewNopLogger()), accountKeeper, bankKeeper, authority.String()) - - // Create MsgServiceRouter, but don't populate it before creating the gov - // keeper. - router.SetInterfaceRegistry(cdc.InterfaceRegistry()) - queryRouter.SetInterfaceRegistry(cdc.InterfaceRegistry()) - - govKeeper := keeper.NewKeeper( - cdc, - runtime.NewEnvironment(runtime.NewKVStoreService(keys[types.StoreKey]), log.NewNopLogger(), runtime.EnvWithQueryRouterService(queryRouter), runtime.EnvWithMsgRouterService(router)), - accountKeeper, - bankKeeper, - stakingKeeper, - poolKeeper, - keeper.DefaultConfig(), - authority.String(), - ) - govRouter := v1beta1.NewRouter() - govRouter.AddRoute(types.RouterKey, v1beta1.ProposalHandler) - govKeeper.SetLegacyRouter(govRouter) - - authModule := auth.NewAppModule(cdc, accountKeeper, acctsModKeeper, authsims.RandomGenesisAccounts, nil) - bankModule := bank.NewAppModule(cdc, bankKeeper, accountKeeper) - stakingModule := staking.NewAppModule(cdc, stakingKeeper) - govModule := gov.NewAppModule(cdc, govKeeper, accountKeeper, bankKeeper, poolKeeper) - 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, - types.ModuleName: govModule, - consensusparamtypes.ModuleName: consensusModule, - }, - baseapp.NewMsgServiceRouter(), - baseapp.NewGRPCQueryRouter(), - ) - - sdkCtx := sdk.UnwrapSDKContext(integrationApp.Context()) - - msgSrvr := keeper.NewMsgServerImpl(govKeeper) - legacyMsgSrvr := keeper.NewLegacyMsgServerImpl(authority.String(), msgSrvr) - - // Register MsgServer and QueryServer - v1.RegisterMsgServer(router, msgSrvr) - v1beta1.RegisterMsgServer(router, legacyMsgSrvr) - - v1.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewQueryServer(govKeeper)) - v1beta1.RegisterQueryServer(integrationApp.QueryHelper(), keeper.NewLegacyQueryServer(govKeeper)) - - queryClient := v1.NewQueryClient(integrationApp.QueryHelper()) - legacyQueryClient := v1beta1.NewQueryClient(integrationApp.QueryHelper()) - - return &fixture{ - ctx: sdkCtx, - queryClient: queryClient, - legacyQueryClient: legacyQueryClient, - accountKeeper: accountKeeper, - bankKeeper: bankKeeper, - stakingKeeper: stakingKeeper, - govKeeper: govKeeper, - } -} diff --git a/tests/integration/gov/module_test.go b/tests/integration/gov/module_test.go deleted file mode 100644 index 826f6a7d68d6..000000000000 --- a/tests/integration/gov/module_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package gov_test - -import ( - "testing" - - "gotest.tools/v3/assert" - - "cosmossdk.io/depinject" - "cosmossdk.io/log" - _ "cosmossdk.io/x/accounts" - "cosmossdk.io/x/gov/types" - _ "cosmossdk.io/x/mint" - _ "cosmossdk.io/x/protocolpool" - - "github.com/cosmos/cosmos-sdk/testutil/configurator" - 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( - configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.StakingModule(), - configurator.BankModule(), - configurator.GovModule(), - configurator.ConsensusModule(), - configurator.ProtocolPoolModule(), - ), - depinject.Supply(log.NewNopLogger()), - ), - &accountKeeper, - ) - assert.NilError(t, err) - - ctx := app.BaseApp.NewContext(false) - acc := accountKeeper.GetAccount(ctx, authtypes.NewModuleAddress(types.ModuleName)) - assert.Assert(t, acc != nil) -} diff --git a/tests/integration/v2/app.go b/tests/integration/v2/app.go index 72a4873cba6b..abb55a748082 100644 --- a/tests/integration/v2/app.go +++ b/tests/integration/v2/app.go @@ -17,6 +17,7 @@ import ( corebranch "cosmossdk.io/core/branch" "cosmossdk.io/core/comet" corecontext "cosmossdk.io/core/context" + "cosmossdk.io/core/gas" "cosmossdk.io/core/header" "cosmossdk.io/core/server" corestore "cosmossdk.io/core/store" @@ -99,6 +100,8 @@ type StartupConfig struct { RouterServiceBuilder runtime.RouterServiceBuilder // HeaderService defines the custom header service to be used in the app. HeaderService header.Service + + GasService gas.Service } func DefaultStartUpConfig(t *testing.T) StartupConfig { @@ -129,6 +132,7 @@ func DefaultStartUpConfig(t *testing.T) StartupConfig { stf.NewMsgRouterService, stf.NewQueryRouterService(), ), HeaderService: services.NewGenesisHeaderService(stf.HeaderService{}), + GasService: stf.NewGasMeterService(), } } @@ -193,9 +197,11 @@ func NewApp( startupConfig.BranchService, startupConfig.RouterServiceBuilder, startupConfig.HeaderService, + startupConfig.GasService, ), depinject.Invoke( std.RegisterInterfaces, + std.RegisterLegacyAminoCodec, ), ), append(extraOutputs, &appBuilder, &cdc, &txConfigOptions, &txConfig, &storeBuilder)...); err != nil { @@ -336,7 +342,7 @@ func (a *App) Deliver( require.NoError(t, err) a.lastHeight++ - // update block height if integration context is present + // update block height and block time if integration context is present iCtx, ok := ctx.Value(contextKey).(*integrationContext) if ok { iCtx.header.Height = int64(a.lastHeight) diff --git a/tests/integration/v2/genesis.go b/tests/integration/v2/genesis.go index d101ce3e8672..13d37be9b770 100644 --- a/tests/integration/v2/genesis.go +++ b/tests/integration/v2/genesis.go @@ -147,6 +147,12 @@ type genesisTxCodec struct { tx.ConfigOptions } +func NewGenesisTxCodec(txConfigOptions tx.ConfigOptions) *genesisTxCodec { + return &genesisTxCodec{ + txConfigOptions, + } +} + // Decode implements transaction.Codec. func (t *genesisTxCodec) Decode(bz []byte) (stateMachineTx, error) { var out stateMachineTx diff --git a/tests/integration/gov/abci_test.go b/tests/integration/v2/gov/abci_test.go similarity index 81% rename from tests/integration/gov/abci_test.go rename to tests/integration/v2/gov/abci_test.go index ff1664ed4f0d..24d7c7d497ab 100644 --- a/tests/integration/gov/abci_test.go +++ b/tests/integration/v2/gov/abci_test.go @@ -1,6 +1,7 @@ -package gov_test +package gov import ( + "context" "testing" "time" @@ -16,20 +17,21 @@ import ( stakingtypes "cosmossdk.io/x/staking/types" addresscodec "github.com/cosmos/cosmos-sdk/codec/address" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) func TestUnregisteredProposal_InactiveProposalFails(t *testing.T) { - suite := createTestSuite(t) - ctx := suite.app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 10, valTokens) - addr0Str, err := suite.AccountKeeper.AddressCodec().BytesToString(addrs[0]) + addr0Str, err := suite.AuthKeeper.AddressCodec().BytesToString(addrs[0]) require.NoError(t, err) // manually set proposal in store - startTime, endTime := time.Now().Add(-4*time.Hour), ctx.BlockHeader().Time + startTime, endTime := time.Now().Add(-4*time.Hour), time.Now() proposal, err := v1.NewProposal([]sdk.Msg{ &v1.Proposal{}, // invalid proposal message }, 1, startTime, startTime, "", "Unsupported proposal", "Unsupported proposal", addr0Str, v1.ProposalType_PROPOSAL_TYPE_STANDARD) @@ -50,13 +52,14 @@ func TestUnregisteredProposal_InactiveProposalFails(t *testing.T) { } func TestUnregisteredProposal_ActiveProposalFails(t *testing.T) { - suite := createTestSuite(t) - ctx := suite.app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 10, valTokens) - addr0Str, err := suite.AccountKeeper.AddressCodec().BytesToString(addrs[0]) + addr0Str, err := suite.AuthKeeper.AddressCodec().BytesToString(addrs[0]) require.NoError(t, err) // manually set proposal in store - startTime, endTime := time.Now().Add(-4*time.Hour), ctx.BlockHeader().Time + header := integration.HeaderInfoFromContext(ctx) + startTime, endTime := time.Now().Add(-4*time.Hour), header.Time proposal, err := v1.NewProposal([]sdk.Msg{ &v1.Proposal{}, // invalid proposal message }, 1, startTime, startTime, "", "Unsupported proposal", "Unsupported proposal", addr0Str, v1.ProposalType_PROPOSAL_TYPE_STANDARD) @@ -80,9 +83,8 @@ func TestUnregisteredProposal_ActiveProposalFails(t *testing.T) { } func TestTickExpiredDepositPeriod(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 10, valTokens) govMsgSvr := keeper.NewMsgServerImpl(suite.GovKeeper) @@ -102,23 +104,22 @@ func TestTickExpiredDepositPeriod(t *testing.T) { require.NoError(t, err) require.NotNil(t, res) - newHeader := ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader := integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(time.Duration(1) * time.Second) + ctx = integration.SetHeaderInfo(ctx, newHeader) params, _ := suite.GovKeeper.Params.Get(ctx) - newHeader = ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(*params.MaxDepositPeriod) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader = integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(*params.MaxDepositPeriod) + ctx = integration.SetHeaderInfo(ctx, newHeader) err = suite.GovKeeper.EndBlocker(ctx) require.NoError(t, err) } func TestTickMultipleExpiredDepositPeriod(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 10, valTokens) govMsgSvr := keeper.NewMsgServerImpl(suite.GovKeeper) @@ -137,9 +138,9 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.NoError(t, err) require.NotNil(t, res) - newHeader := ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(time.Duration(2) * time.Second) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader := integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(time.Duration(2) * time.Second) + ctx = integration.SetHeaderInfo(ctx, newHeader) newProposalMsg2, err := v1.NewMsgSubmitProposal( []sdk.Msg{mkTestLegacyContent(t)}, @@ -156,23 +157,22 @@ func TestTickMultipleExpiredDepositPeriod(t *testing.T) { require.NoError(t, err) require.NotNil(t, res) - newHeader = ctx.HeaderInfo() + newHeader = integration.HeaderInfoFromContext(ctx) params, _ := suite.GovKeeper.Params.Get(ctx) - newHeader.Time = ctx.HeaderInfo().Time.Add(*params.MaxDepositPeriod).Add(time.Duration(-1) * time.Second) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader.Time = newHeader.Time.Add(*params.MaxDepositPeriod).Add(time.Duration(-1) * time.Second) + ctx = integration.SetHeaderInfo(ctx, newHeader) require.NoError(t, suite.GovKeeper.EndBlocker(ctx)) - newHeader = ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(time.Duration(5) * time.Second) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader = integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(time.Duration(5) * time.Second) + ctx = integration.SetHeaderInfo(ctx, newHeader) require.NoError(t, suite.GovKeeper.EndBlocker(ctx)) } func TestTickPassedDepositPeriod(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 10, valTokens) govMsgSvr := keeper.NewMsgServerImpl(suite.GovKeeper) @@ -193,11 +193,11 @@ func TestTickPassedDepositPeriod(t *testing.T) { proposalID := res.ProposalId - newHeader := ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader := integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(time.Duration(1) * time.Second) + ctx = integration.SetHeaderInfo(ctx, newHeader) - addr1Str, err := suite.AccountKeeper.AddressCodec().BytesToString(addrs[1]) + addr1Str, err := suite.AuthKeeper.AddressCodec().BytesToString(addrs[1]) require.NoError(t, err) newDepositMsg := v1.NewMsgDeposit(addr1Str, proposalID, sdk.Coins{sdk.NewInt64Coin(sdk.DefaultBondDenom, 100000)}) @@ -207,9 +207,8 @@ func TestTickPassedDepositPeriod(t *testing.T) { } func TestProposalDepositRefundFailEndBlocker(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 10, valTokens) govMsgSvr := keeper.NewMsgServerImpl(suite.GovKeeper) @@ -246,15 +245,15 @@ func TestProposalDepositRefundFailEndBlocker(t *testing.T) { require.NoError(t, err) // fast forward to the end of the voting period - newHeader := ctx.HeaderInfo() + newHeader := integration.HeaderInfoFromContext(ctx) newHeader.Time = proposal.VotingEndTime.Add(time.Duration(100) * time.Second) - ctx = ctx.WithHeaderInfo(newHeader) + ctx = integration.SetHeaderInfo(ctx, newHeader) err = suite.GovKeeper.EndBlocker(ctx) require.NoError(t, err) // no error, means does not halt the chain - events := ctx.EventManager().Events() - attr, ok := events.GetAttributes(types.AttributeKeyProposalDepositError) + events := integration.EventsFromContext(ctx) + attr, ok := integration.GetAttributes(events, types.AttributeKeyProposalDepositError) require.True(t, ok) require.Contains(t, attr[0].Value, "failed to refund or burn deposits") } @@ -275,9 +274,8 @@ func TestTickPassedVotingPeriod(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx depositMultiplier := getDepositMultiplier(tc.proposalType) addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 10, valTokens.Mul(math.NewInt(depositMultiplier))) @@ -294,11 +292,11 @@ func TestTickPassedVotingPeriod(t *testing.T) { proposalID := res.ProposalId - newHeader := ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader := integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(time.Duration(1) * time.Second) + ctx = integration.SetHeaderInfo(ctx, newHeader) - addr1Str, err := suite.AccountKeeper.AddressCodec().BytesToString(addrs[1]) + addr1Str, err := suite.AuthKeeper.AddressCodec().BytesToString(addrs[1]) require.NoError(t, err) newDepositMsg := v1.NewMsgDeposit(addr1Str, proposalID, proposalCoins) @@ -312,9 +310,9 @@ func TestTickPassedVotingPeriod(t *testing.T) { votingPeriod = params.ExpeditedVotingPeriod } - newHeader = ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(*params.MaxDepositPeriod).Add(*votingPeriod) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader = integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(*params.MaxDepositPeriod).Add(*votingPeriod) + ctx = integration.SetHeaderInfo(ctx, newHeader) proposal, err := suite.GovKeeper.Proposals.Get(ctx, res.ProposalId) require.NoError(t, err) @@ -354,9 +352,8 @@ func TestProposalPassedEndblocker(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx depositMultiplier := getDepositMultiplier(tc.proposalType) addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 10, valTokens.Mul(math.NewInt(depositMultiplier))) @@ -366,8 +363,8 @@ func TestProposalPassedEndblocker(t *testing.T) { stakingMsgSvr := stakingkeeper.NewMsgServerImpl(suite.StakingKeeper) valAddr := sdk.ValAddress(addrs[0]) proposer := addrs[0] - acc := suite.AccountKeeper.NewAccountWithAddress(ctx, addrs[0]) - suite.AccountKeeper.SetAccount(ctx, acc) + acc := suite.AuthKeeper.NewAccountWithAddress(ctx, addrs[0]) + suite.AuthKeeper.SetAccount(ctx, acc) createValidators(t, stakingMsgSvr, ctx, []sdk.ValAddress{valAddr}, []int64{10}) _, err := suite.StakingKeeper.EndBlocker(ctx) @@ -380,7 +377,7 @@ func TestProposalPassedEndblocker(t *testing.T) { require.NoError(t, err) proposalCoins := sdk.Coins{sdk.NewCoin(sdk.DefaultBondDenom, suite.StakingKeeper.TokensFromConsensusPower(ctx, 10*depositMultiplier))} - addr0Str, err := suite.AccountKeeper.AddressCodec().BytesToString(addrs[0]) + addr0Str, err := suite.AuthKeeper.AddressCodec().BytesToString(addrs[0]) require.NoError(t, err) newDepositMsg := v1.NewMsgDeposit(addr0Str, proposal.Id, proposalCoins) @@ -398,10 +395,10 @@ func TestProposalPassedEndblocker(t *testing.T) { err = suite.GovKeeper.AddVote(ctx, proposal.Id, addrs[0], v1.NewNonSplitVoteOption(v1.OptionYes), "") require.NoError(t, err) - newHeader := ctx.HeaderInfo() + newHeader := integration.HeaderInfoFromContext(ctx) params, _ := suite.GovKeeper.Params.Get(ctx) - newHeader.Time = ctx.HeaderInfo().Time.Add(*params.MaxDepositPeriod).Add(*params.VotingPeriod) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader.Time = newHeader.Time.Add(*params.MaxDepositPeriod).Add(*params.VotingPeriod) + ctx = integration.SetHeaderInfo(ctx, newHeader) err = suite.GovKeeper.EndBlocker(ctx) require.NoError(t, err) @@ -413,9 +410,8 @@ func TestProposalPassedEndblocker(t *testing.T) { } func TestEndBlockerProposalHandlerFailed(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 1, valTokens) SortAddresses(addrs) @@ -431,8 +427,8 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) { toAddrStr, err := ac.BytesToString(addrs[0]) require.NoError(t, err) - acc := suite.AccountKeeper.NewAccountWithAddress(ctx, addrs[0]) - suite.AccountKeeper.SetAccount(ctx, acc) + acc := suite.AuthKeeper.NewAccountWithAddress(ctx, addrs[0]) + suite.AuthKeeper.SetAccount(ctx, acc) createValidators(t, stakingMsgSvr, ctx, []sdk.ValAddress{valAddr}, []int64{10}) _, err = suite.StakingKeeper.EndBlocker(ctx) @@ -442,7 +438,7 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) { require.NoError(t, err) proposalCoins := sdk.NewCoins(sdk.NewCoin(sdk.DefaultBondDenom, suite.StakingKeeper.TokensFromConsensusPower(ctx, 10))) - addr0Str, err := suite.AccountKeeper.AddressCodec().BytesToString(addrs[0]) + addr0Str, err := suite.AuthKeeper.AddressCodec().BytesToString(addrs[0]) require.NoError(t, err) newDepositMsg := v1.NewMsgDeposit(addr0Str, proposal.Id, proposalCoins) @@ -455,16 +451,16 @@ func TestEndBlockerProposalHandlerFailed(t *testing.T) { require.NoError(t, err) params, _ := suite.GovKeeper.Params.Get(ctx) - newHeader := ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(*params.MaxDepositPeriod).Add(*params.VotingPeriod) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader := integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(*params.MaxDepositPeriod).Add(*params.VotingPeriod) + ctx = integration.SetHeaderInfo(ctx, newHeader) // validate that the proposal fails/has been rejected err = suite.GovKeeper.EndBlocker(ctx) require.NoError(t, err) // check proposal events - events := ctx.EventManager().Events() - attr, eventOk := events.GetAttributes(types.AttributeKeyProposalLog) + events := integration.EventsFromContext(ctx) + attr, eventOk := integration.GetAttributes(events, types.AttributeKeyProposalLog) require.True(t, eventOk) require.Contains(t, attr[0].Value, "failed on execution") @@ -499,9 +495,8 @@ func TestExpeditedProposal_PassAndConversionToRegular(t *testing.T) { for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx depositMultiplier := getDepositMultiplier(v1.ProposalType_PROPOSAL_TYPE_EXPEDITED) addrs := simtestutil.AddTestAddrs(suite.BankKeeper, suite.StakingKeeper, ctx, 3, valTokens.Mul(math.NewInt(depositMultiplier))) params, err := suite.GovKeeper.Params.Get(ctx) @@ -514,8 +509,8 @@ func TestExpeditedProposal_PassAndConversionToRegular(t *testing.T) { valAddr := sdk.ValAddress(addrs[0]) proposer := addrs[0] - acc := suite.AccountKeeper.NewAccountWithAddress(ctx, addrs[0]) - suite.AccountKeeper.SetAccount(ctx, acc) + acc := suite.AuthKeeper.NewAccountWithAddress(ctx, addrs[0]) + suite.AuthKeeper.SetAccount(ctx, acc) // Create a validator so that able to vote on proposal. createValidators(t, stakingMsgSvr, ctx, []sdk.ValAddress{valAddr}, []int64{10}) _, err = suite.StakingKeeper.EndBlocker(ctx) @@ -538,11 +533,11 @@ func TestExpeditedProposal_PassAndConversionToRegular(t *testing.T) { proposalID := res.ProposalId - newHeader := ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(time.Duration(1) * time.Second) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader := integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(time.Duration(1) * time.Second) + ctx = integration.SetHeaderInfo(ctx, newHeader) - addr1Str, err := suite.AccountKeeper.AddressCodec().BytesToString(addrs[1]) + addr1Str, err := suite.AuthKeeper.AddressCodec().BytesToString(addrs[1]) require.NoError(t, err) newDepositMsg := v1.NewMsgDeposit(addr1Str, proposalID, proposalCoins) @@ -550,9 +545,9 @@ func TestExpeditedProposal_PassAndConversionToRegular(t *testing.T) { require.NoError(t, err) require.NotNil(t, res1) - newHeader = ctx.HeaderInfo() - newHeader.Time = ctx.HeaderInfo().Time.Add(*params.MaxDepositPeriod).Add(*params.ExpeditedVotingPeriod) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader = integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(*params.MaxDepositPeriod).Add(*params.ExpeditedVotingPeriod) + ctx = integration.SetHeaderInfo(ctx, newHeader) proposal, err := suite.GovKeeper.Proposals.Get(ctx, res.ProposalId) require.Nil(t, err) @@ -604,8 +599,9 @@ func TestExpeditedProposal_PassAndConversionToRegular(t *testing.T) { require.Equal(t, expectedIntermediateMofuleAccCoings, intermediateModuleAccCoins) // block header time at the voting period - newHeader.Time = ctx.HeaderInfo().Time.Add(*params.MaxDepositPeriod).Add(*params.VotingPeriod) - ctx = ctx.WithHeaderInfo(newHeader) + newHeader = integration.HeaderInfoFromContext(ctx) + newHeader.Time = newHeader.Time.Add(*params.MaxDepositPeriod).Add(*params.VotingPeriod) + ctx = integration.SetHeaderInfo(ctx, newHeader) if tc.regularEventuallyPassing { // Validator votes YES, letting the converted regular proposal pass. @@ -646,7 +642,7 @@ func TestExpeditedProposal_PassAndConversionToRegular(t *testing.T) { } } -func createValidators(t *testing.T, stakingMsgSvr stakingtypes.MsgServer, ctx sdk.Context, addrs []sdk.ValAddress, powerAmt []int64) { +func createValidators(t *testing.T, stakingMsgSvr stakingtypes.MsgServer, ctx context.Context, addrs []sdk.ValAddress, powerAmt []int64) { t.Helper() require.True(t, len(addrs) <= len(pubkeys), "Not enough pubkeys specified at top of file.") diff --git a/tests/integration/v2/gov/common_test.go b/tests/integration/v2/gov/common_test.go new file mode 100644 index 000000000000..c630f8602f85 --- /dev/null +++ b/tests/integration/v2/gov/common_test.go @@ -0,0 +1,207 @@ +package gov + +import ( + "bytes" + "context" + "log" + "sort" + "testing" + + "github.com/stretchr/testify/require" + "gotest.tools/v3/assert" + + "cosmossdk.io/core/router" + "cosmossdk.io/core/transaction" + "cosmossdk.io/depinject" + sdklog "cosmossdk.io/log" + "cosmossdk.io/math" + "cosmossdk.io/runtime/v2" + _ "cosmossdk.io/x/accounts" + _ "cosmossdk.io/x/bank" + bankkeeper "cosmossdk.io/x/bank/keeper" + banktypes "cosmossdk.io/x/bank/types" + _ "cosmossdk.io/x/consensus" + _ "cosmossdk.io/x/gov" + "cosmossdk.io/x/gov/keeper" + "cosmossdk.io/x/gov/types" + v1 "cosmossdk.io/x/gov/types/v1" + "cosmossdk.io/x/gov/types/v1beta1" + _ "cosmossdk.io/x/mint" + _ "cosmossdk.io/x/protocolpool" + _ "cosmossdk.io/x/staking" + stakingkeeper "cosmossdk.io/x/staking/keeper" + stakingtypes "cosmossdk.io/x/staking/types" + + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/crypto/keys/ed25519" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + "github.com/cosmos/cosmos-sdk/tests/integration/v2" + "github.com/cosmos/cosmos-sdk/testutil/configurator" + sdk "github.com/cosmos/cosmos-sdk/types" + _ "github.com/cosmos/cosmos-sdk/x/auth" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" + "github.com/cosmos/cosmos-sdk/x/auth/tx" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +var ( + valTokens = sdk.TokensFromConsensusPower(42, sdk.DefaultPowerReduction) + TestProposal = v1beta1.NewTextProposal("Test", "description") + TestDescription = stakingtypes.NewDescription("T", "E", "S", "T", "Z", &stakingtypes.Metadata{}) + TestCommissionRates = stakingtypes.NewCommissionRates(math.LegacyZeroDec(), math.LegacyZeroDec(), math.LegacyZeroDec()) +) + +// mkTestLegacyContent creates a MsgExecLegacyContent for testing purposes. +func mkTestLegacyContent(t *testing.T) *v1.MsgExecLegacyContent { + t.Helper() + msgContent, err := v1.NewLegacyContent(TestProposal, authtypes.NewModuleAddress(types.ModuleName).String()) + assert.NilError(t, err) + + return msgContent +} + +var pubkeys = []cryptotypes.PubKey{ + ed25519.GenPrivKey().PubKey(), + ed25519.GenPrivKey().PubKey(), + ed25519.GenPrivKey().PubKey(), +} + +// SortAddresses - Sorts Addresses +func SortAddresses(addrs []sdk.AccAddress) { + byteAddrs := make([][]byte, len(addrs)) + + for i, addr := range addrs { + byteAddrs[i] = addr.Bytes() + } + + SortByteArrays(byteAddrs) + + for i, byteAddr := range byteAddrs { + addrs[i] = byteAddr + } +} + +// implement `Interface` in sort package. +type sortByteArrays [][]byte + +func (b sortByteArrays) Len() int { + return len(b) +} + +func (b sortByteArrays) Less(i, j int) bool { + // bytes package already implements Comparable for []byte. + switch bytes.Compare(b[i], b[j]) { + case -1: + return true + case 0, 1: + return false + default: + log.Panic("not fail-able with `bytes.Comparable` bounded [-1, 1].") + return false + } +} + +func (b sortByteArrays) Swap(i, j int) { + b[j], b[i] = b[i], b[j] +} + +// SortByteArrays - sorts the provided byte array +func SortByteArrays(src [][]byte) [][]byte { + sorted := sortByteArrays(src) + sort.Sort(sorted) + return sorted +} + +type suite struct { + cdc codec.Codec + app *integration.App + + ctx context.Context + + AuthKeeper authkeeper.AccountKeeper + BankKeeper bankkeeper.Keeper + GovKeeper *keeper.Keeper + StakingKeeper *stakingkeeper.Keeper + + txConfigOptions tx.ConfigOptions +} + +func createTestSuite(t *testing.T, genesisBehavior int) suite { + t.Helper() + res := suite{} + + moduleConfigs := []configurator.ModuleOption{ + configurator.AccountsModule(), + configurator.AuthModule(), + configurator.StakingModule(), + configurator.TxModule(), + configurator.BankModule(), + configurator.GovModule(), + configurator.MintModule(), + configurator.ConsensusModule(), + configurator.ProtocolPoolModule(), + } + + startupCfg := integration.DefaultStartUpConfig(t) + + msgRouterService := integration.NewRouterService() + res.registerMsgRouterService(msgRouterService) + + var routerFactory runtime.RouterServiceFactory = func(_ []byte) router.Service { + return msgRouterService + } + + queryRouterService := integration.NewRouterService() + res.registerQueryRouterService(queryRouterService) + serviceBuilder := runtime.NewRouterBuilder(routerFactory, queryRouterService) + + startupCfg.BranchService = &integration.BranchService{} + startupCfg.RouterServiceBuilder = serviceBuilder + startupCfg.HeaderService = &integration.HeaderService{} + startupCfg.GasService = &integration.GasService{} + startupCfg.GenesisBehavior = genesisBehavior + + app, err := integration.NewApp( + depinject.Configs(configurator.NewAppV2Config(moduleConfigs...), depinject.Supply(sdklog.NewNopLogger())), + startupCfg, + &res.AuthKeeper, &res.BankKeeper, &res.GovKeeper, &res.StakingKeeper, &res.cdc, &res.txConfigOptions, + ) + require.NoError(t, err) + + res.ctx = app.StateLatestContext(t) + res.app = app + return res +} + +func (s *suite) registerMsgRouterService(router *integration.RouterService) { + // register custom router service + bankSendHandler := func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { + msg, ok := req.(*banktypes.MsgSend) + if !ok { + return nil, integration.ErrInvalidMsgType + } + msgServer := bankkeeper.NewMsgServerImpl(s.BankKeeper) + resp, err := msgServer.Send(ctx, msg) + return resp, err + } + + router.RegisterHandler(bankSendHandler, "/cosmos.bank.v1beta1.MsgSend") + + // register custom router service + + govSubmitProposalHandler := func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { + msg, ok := req.(*v1.MsgExecLegacyContent) + if !ok { + return nil, integration.ErrInvalidMsgType + } + msgServer := keeper.NewMsgServerImpl(s.GovKeeper) + resp, err := msgServer.ExecLegacyContent(ctx, msg) + return resp, err + } + + router.RegisterHandler(govSubmitProposalHandler, "/cosmos.gov.v1.MsgExecLegacyContent") +} + +func (f *suite) registerQueryRouterService(router *integration.RouterService) { + +} diff --git a/tests/integration/gov/genesis_test.go b/tests/integration/v2/gov/genesis_test.go similarity index 54% rename from tests/integration/gov/genesis_test.go rename to tests/integration/v2/gov/genesis_test.go index 5f512be92a85..3149aad4c2c2 100644 --- a/tests/integration/gov/genesis_test.go +++ b/tests/integration/v2/gov/genesis_test.go @@ -1,86 +1,43 @@ -package gov_test +package gov import ( + "crypto/sha256" "encoding/json" "testing" + "time" - abci "github.com/cometbft/cometbft/api/cometbft/abci/v1" "github.com/stretchr/testify/require" "gotest.tools/v3/assert" "cosmossdk.io/core/header" - corestore "cosmossdk.io/core/store" - coretesting "cosmossdk.io/core/testing" - "cosmossdk.io/depinject" - "cosmossdk.io/log" + "cosmossdk.io/core/server" + "cosmossdk.io/core/transaction" sdkmath "cosmossdk.io/math" _ "cosmossdk.io/x/accounts" _ "cosmossdk.io/x/bank" - bankkeeper "cosmossdk.io/x/bank/keeper" banktypes "cosmossdk.io/x/bank/types" _ "cosmossdk.io/x/consensus" "cosmossdk.io/x/gov" - "cosmossdk.io/x/gov/keeper" "cosmossdk.io/x/gov/types" v1 "cosmossdk.io/x/gov/types/v1" _ "cosmossdk.io/x/staking" - stakingkeeper "cosmossdk.io/x/staking/keeper" stakingtypes "cosmossdk.io/x/staking/types" - "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/runtime" - "github.com/cosmos/cosmos-sdk/testutil/configurator" + "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/x/auth" - authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" ) -type suite struct { - cdc codec.Codec - app *runtime.App - AccountKeeper authkeeper.AccountKeeper - BankKeeper bankkeeper.Keeper - GovKeeper *keeper.Keeper - StakingKeeper *stakingkeeper.Keeper - appBuilder *runtime.AppBuilder -} - -var appConfig = configurator.NewAppConfig( - configurator.AccountsModule(), - configurator.AuthModule(), - configurator.StakingModule(), - configurator.BankModule(), - configurator.GovModule(), - configurator.MintModule(), - configurator.ConsensusModule(), - configurator.ProtocolPoolModule(), -) - func TestImportExportQueues(t *testing.T) { var err error - s1 := suite{} - s1.app, err = simtestutil.SetupWithConfiguration( - depinject.Configs( - appConfig, - depinject.Supply(log.NewNopLogger()), - ), - simtestutil.DefaultStartUpConfig(), - &s1.AccountKeeper, &s1.BankKeeper, &s1.GovKeeper, &s1.StakingKeeper, &s1.cdc, &s1.appBuilder, - ) - assert.NilError(t, err) + s1 := createTestSuite(t, integration.Genesis_COMMIT) + ctx := s1.ctx - ctx := s1.app.BaseApp.NewContext(false) addrs := simtestutil.AddTestAddrs(s1.BankKeeper, s1.StakingKeeper, ctx, 1, valTokens) - _, err = s1.app.FinalizeBlock(&abci.FinalizeBlockRequest{ - Height: s1.app.LastBlockHeight() + 1, - }) - assert.NilError(t, err) - - ctx = s1.app.BaseApp.NewContext(false) // Create two proposals, put the second into the voting period proposal1, err := s1.GovKeeper.SubmitProposal(ctx, []sdk.Msg{mkTestLegacyContent(t)}, "", "test", "description", addrs[0], v1.ProposalType_PROPOSAL_TYPE_STANDARD) assert.NilError(t, err) @@ -103,7 +60,7 @@ func TestImportExportQueues(t *testing.T) { assert.Assert(t, proposal1.Status == v1.StatusDepositPeriod) assert.Assert(t, proposal2.Status == v1.StatusVotingPeriod) - authGenState, err := s1.AccountKeeper.ExportGenesis(ctx) + authGenState, err := s1.AuthKeeper.ExportGenesis(ctx) require.NoError(t, err) bankGenState, err := s1.BankKeeper.ExportGenesis(ctx) require.NoError(t, err) @@ -111,8 +68,10 @@ func TestImportExportQueues(t *testing.T) { require.NoError(t, err) // export the state and import it into a new app - govGenState, _ := gov.ExportGenesis(ctx, s1.GovKeeper) - genesisState := s1.appBuilder.DefaultGenesis() + govGenState, err := gov.ExportGenesis(ctx, s1.GovKeeper) + require.NoError(t, err) + + genesisState := s1.app.DefaultGenesis() genesisState[authtypes.ModuleName] = s1.cdc.MustMarshalJSON(authGenState) genesisState[banktypes.ModuleName] = s1.cdc.MustMarshalJSON(bankGenState) @@ -122,49 +81,34 @@ func TestImportExportQueues(t *testing.T) { stateBytes, err := json.MarshalIndent(genesisState, "", " ") assert.NilError(t, err) - s2 := suite{} - db := coretesting.NewMemDB() - conf2 := simtestutil.DefaultStartUpConfig() - conf2.DB = db - s2.app, err = simtestutil.SetupWithConfiguration( - depinject.Configs( - appConfig, - depinject.Supply(log.NewNopLogger()), - ), - conf2, - &s2.AccountKeeper, &s2.BankKeeper, &s2.GovKeeper, &s2.StakingKeeper, &s2.cdc, &s2.appBuilder, - ) - assert.NilError(t, err) - - clearDB(t, db) - err = s2.app.CommitMultiStore().LoadLatestVersion() - assert.NilError(t, err) + s2 := createTestSuite(t, integration.Genesis_SKIP) - _, err = s2.app.InitChain( - &abci.InitChainRequest{ - Validators: []abci.ValidatorUpdate{}, - ConsensusParams: simtestutil.DefaultConsensusParams, - AppStateBytes: stateBytes, + emptyHash := sha256.Sum256(nil) + _, newstate, err := s2.app.InitGenesis( + ctx, + &server.BlockRequest[transaction.Tx]{ + Height: 1, + Time: time.Now(), + Hash: emptyHash[:], + ChainId: "test-chain", + AppHash: emptyHash[:], + IsGenesis: true, }, + stateBytes, + integration.NewGenesisTxCodec(s2.txConfigOptions), ) assert.NilError(t, err) - _, err = s2.app.FinalizeBlock(&abci.FinalizeBlockRequest{ - Height: s2.app.LastBlockHeight() + 1, - }) - assert.NilError(t, err) - - _, err = s2.app.FinalizeBlock(&abci.FinalizeBlockRequest{ - Height: s2.app.LastBlockHeight() + 1, - }) + _, err = s2.app.Commit(newstate) assert.NilError(t, err) - ctx2 := s2.app.BaseApp.NewContext(false) + ctx2 := s2.app.StateLatestContext(t) params, err = s2.GovKeeper.Params.Get(ctx2) assert.NilError(t, err) // Jump the time forward past the DepositPeriod and VotingPeriod - ctx2 = ctx2.WithHeaderInfo(header.Info{Time: ctx2.BlockHeader().Time.Add(*params.MaxDepositPeriod).Add(*params.VotingPeriod)}) + h := integration.HeaderInfoFromContext(ctx2) + ctx2 = integration.SetHeaderInfo(ctx2, header.Info{Time: h.Time.Add(*params.MaxDepositPeriod).Add(*params.VotingPeriod)}) // Make sure that they are still in the DepositPeriod and VotingPeriod respectively proposal1, err = s2.GovKeeper.Proposals.Get(ctx2, proposalID1) @@ -189,29 +133,12 @@ func TestImportExportQueues(t *testing.T) { assert.Assert(t, proposal2.Status == v1.StatusRejected) } -func clearDB(t *testing.T, db corestore.KVStoreWithBatch) { - t.Helper() - iter, err := db.Iterator(nil, nil) - assert.NilError(t, err) - defer iter.Close() - - var keys [][]byte - for ; iter.Valid(); iter.Next() { - keys = append(keys, iter.Key()) - } - - for _, k := range keys { - assert.NilError(t, db.Delete(k)) - } -} - func TestImportExportQueues_ErrorUnconsistentState(t *testing.T) { - suite := createTestSuite(t) - app := suite.app - ctx := app.BaseApp.NewContext(false) + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx params := v1.DefaultParams() - err := gov.InitGenesis(ctx, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, &v1.GenesisState{ + err := gov.InitGenesis(ctx, suite.AuthKeeper, suite.BankKeeper, suite.GovKeeper, &v1.GenesisState{ Deposits: v1.Deposits{ { ProposalId: 1234, @@ -227,7 +154,7 @@ func TestImportExportQueues_ErrorUnconsistentState(t *testing.T) { Params: ¶ms, }) require.Error(t, err) - err = gov.InitGenesis(ctx, suite.AccountKeeper, suite.BankKeeper, suite.GovKeeper, v1.DefaultGenesisState()) + err = gov.InitGenesis(ctx, suite.AuthKeeper, suite.BankKeeper, suite.GovKeeper, v1.DefaultGenesisState()) require.NoError(t, err) genState, err := gov.ExportGenesis(ctx, suite.GovKeeper) require.NoError(t, err) diff --git a/tests/integration/gov/keeper/common_test.go b/tests/integration/v2/gov/keeper/common_test.go similarity index 96% rename from tests/integration/gov/keeper/common_test.go rename to tests/integration/v2/gov/keeper/common_test.go index 51b84406c141..2e5289ddb8d5 100644 --- a/tests/integration/gov/keeper/common_test.go +++ b/tests/integration/v2/gov/keeper/common_test.go @@ -1,4 +1,4 @@ -package keeper_test +package keeper import ( "testing" @@ -59,7 +59,7 @@ func createValidators(t *testing.T, f *fixture, powers []int64) ([]sdk.AccAddres assert.NilError(t, f.stakingKeeper.SetNewValidatorByPowerIndex(f.ctx, val3)) for _, addr := range addrs { - f.accountKeeper.SetAccount(f.ctx, f.accountKeeper.NewAccountWithAddress(f.ctx, addr)) + f.authKeeper.SetAccount(f.ctx, f.authKeeper.NewAccountWithAddress(f.ctx, addr)) } _, _ = f.stakingKeeper.Delegate(f.ctx, addrs[0], f.stakingKeeper.TokensFromConsensusPower(f.ctx, powers[0]), stakingtypes.Unbonded, val1, true) diff --git a/tests/integration/v2/gov/keeper/fixture_test.go b/tests/integration/v2/gov/keeper/fixture_test.go new file mode 100644 index 000000000000..d9ed3e807a5d --- /dev/null +++ b/tests/integration/v2/gov/keeper/fixture_test.go @@ -0,0 +1,109 @@ +package keeper + +import ( + "context" + "testing" + + "github.com/stretchr/testify/require" + + "cosmossdk.io/core/router" + "cosmossdk.io/core/transaction" + "cosmossdk.io/depinject" + "cosmossdk.io/log" + "cosmossdk.io/runtime/v2" + _ "cosmossdk.io/x/accounts" + _ "cosmossdk.io/x/bank" + bankkeeper "cosmossdk.io/x/bank/keeper" + _ "cosmossdk.io/x/consensus" + _ "cosmossdk.io/x/gov" + govkeeper "cosmossdk.io/x/gov/keeper" + v1 "cosmossdk.io/x/gov/types/v1" + "cosmossdk.io/x/gov/types/v1beta1" + _ "cosmossdk.io/x/protocolpool" + _ "cosmossdk.io/x/staking" + stakingkeeper "cosmossdk.io/x/staking/keeper" + + "github.com/cosmos/cosmos-sdk/tests/integration/v2" + "github.com/cosmos/cosmos-sdk/testutil/configurator" + _ "github.com/cosmos/cosmos-sdk/x/auth" + authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper" +) + +type fixture struct { + ctx context.Context + app *integration.App + + queryServer v1.QueryServer + legacyQueryServer v1beta1.QueryServer + + authKeeper authkeeper.AccountKeeper + bankKeeper bankkeeper.Keeper + stakingKeeper *stakingkeeper.Keeper + govKeeper *govkeeper.Keeper +} + +func initFixture(t *testing.T) *fixture { + t.Helper() + res := fixture{} + + moduleConfigs := []configurator.ModuleOption{ + configurator.AccountsModule(), + configurator.AuthModule(), + configurator.StakingModule(), + configurator.BankModule(), + configurator.TxModule(), + configurator.GovModule(), + configurator.ConsensusModule(), + configurator.ProtocolPoolModule(), + } + + startupCfg := integration.DefaultStartUpConfig(t) + + msgRouterService := integration.NewRouterService() + res.registerMsgRouterService(msgRouterService) + + var routerFactory runtime.RouterServiceFactory = func(_ []byte) router.Service { + return msgRouterService + } + + queryRouterService := integration.NewRouterService() + res.registerQueryRouterService(queryRouterService) + serviceBuilder := runtime.NewRouterBuilder(routerFactory, queryRouterService) + + startupCfg.BranchService = &integration.BranchService{} + startupCfg.RouterServiceBuilder = serviceBuilder + startupCfg.HeaderService = &integration.HeaderService{} + + app, err := integration.NewApp( + depinject.Configs(configurator.NewAppV2Config(moduleConfigs...), depinject.Supply(log.NewNopLogger())), + startupCfg, + &res.authKeeper, &res.bankKeeper, &res.govKeeper, &res.stakingKeeper) + require.NoError(t, err) + + res.app = app + res.ctx = app.StateLatestContext(t) + + res.queryServer = govkeeper.NewQueryServer(res.govKeeper) + res.legacyQueryServer = govkeeper.NewLegacyQueryServer(res.govKeeper) + return &res +} + +func (f *fixture) registerMsgRouterService(router *integration.RouterService) { + // register custom router service + + govSubmitProposalHandler := func(ctx context.Context, req transaction.Msg) (transaction.Msg, error) { + msg, ok := req.(*v1.MsgExecLegacyContent) + if !ok { + return nil, integration.ErrInvalidMsgType + } + msgServer := govkeeper.NewMsgServerImpl(f.govKeeper) + resp, err := msgServer.ExecLegacyContent(ctx, msg) + return resp, err + } + + router.RegisterHandler(govSubmitProposalHandler, "/cosmos.gov.v1.MsgExecLegacyContent") +} + +func (f *fixture) registerQueryRouterService(router *integration.RouterService) { + +} diff --git a/tests/integration/gov/keeper/grpc_query_test.go b/tests/integration/v2/gov/keeper/grpc_test.go similarity index 92% rename from tests/integration/gov/keeper/grpc_query_test.go rename to tests/integration/v2/gov/keeper/grpc_test.go index 44fc1ccc103e..c8a9be23d781 100644 --- a/tests/integration/gov/keeper/grpc_query_test.go +++ b/tests/integration/v2/gov/keeper/grpc_test.go @@ -1,7 +1,6 @@ -package keeper_test +package keeper import ( - gocontext "context" "fmt" "testing" @@ -16,7 +15,7 @@ func TestLegacyGRPCQueryTally(t *testing.T) { t.Parallel() f := initFixture(t) - ctx, queryClient := f.ctx, f.legacyQueryClient + ctx, queryServer := f.ctx, f.legacyQueryServer addrs, _ := createValidators(t, f, []int64{5, 5, 5}) var ( @@ -62,7 +61,7 @@ func TestLegacyGRPCQueryTally(t *testing.T) { t.Run(fmt.Sprintf("Case %s", testCase.msg), func(t *testing.T) { testCase.malleate() - tally, err := queryClient.TallyResult(gocontext.Background(), req) + tally, err := queryServer.TallyResult(f.ctx, req) if testCase.expPass { assert.NilError(t, err) diff --git a/tests/integration/gov/keeper/tally_test.go b/tests/integration/v2/gov/keeper/tally_test.go similarity index 99% rename from tests/integration/gov/keeper/tally_test.go rename to tests/integration/v2/gov/keeper/tally_test.go index f2b952076285..65f811bd7616 100644 --- a/tests/integration/gov/keeper/tally_test.go +++ b/tests/integration/v2/gov/keeper/tally_test.go @@ -1,4 +1,4 @@ -package keeper_test +package keeper import ( "testing" @@ -6,6 +6,7 @@ import ( "gotest.tools/v3/assert" "cosmossdk.io/math" + _ "cosmossdk.io/x/gov" v1 "cosmossdk.io/x/gov/types/v1" stakingtypes "cosmossdk.io/x/staking/types" diff --git a/tests/integration/v2/gov/module_test.go b/tests/integration/v2/gov/module_test.go new file mode 100644 index 000000000000..338e11f32310 --- /dev/null +++ b/tests/integration/v2/gov/module_test.go @@ -0,0 +1,23 @@ +package gov + +import ( + "testing" + + "gotest.tools/v3/assert" + + _ "cosmossdk.io/x/accounts" + "cosmossdk.io/x/gov/types" + _ "cosmossdk.io/x/mint" + _ "cosmossdk.io/x/protocolpool" + + "github.com/cosmos/cosmos-sdk/tests/integration/v2" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" +) + +func TestItCreatesModuleAccountOnInitBlock(t *testing.T) { + suite := createTestSuite(t, integration.Genesis_COMMIT) + ctx := suite.ctx + + acc := suite.AuthKeeper.GetAccount(ctx, authtypes.NewModuleAddress(types.ModuleName)) + assert.Assert(t, acc != nil) +} diff --git a/tests/integration/v2/services.go b/tests/integration/v2/services.go index 241a07cdd82f..f608fd65fdb0 100644 --- a/tests/integration/v2/services.go +++ b/tests/integration/v2/services.go @@ -1,10 +1,13 @@ package integration import ( + "bytes" "context" + "encoding/json" "errors" "fmt" + "github.com/cosmos/gogoproto/jsonpb" gogoproto "github.com/cosmos/gogoproto/proto" "cosmossdk.io/core/branch" @@ -17,6 +20,7 @@ import ( "cosmossdk.io/core/server" corestore "cosmossdk.io/core/store" "cosmossdk.io/core/transaction" + "cosmossdk.io/server/v2/stf" stfgas "cosmossdk.io/server/v2/stf/gas" ) @@ -72,6 +76,7 @@ type integrationContext struct { state corestore.WriterMap gasMeter gas.Meter header header.Info + events []event.Event } func SetHeaderInfo(ctx context.Context, h header.Info) context.Context { @@ -95,6 +100,31 @@ func SetCometInfo(ctx context.Context, c comet.Info) context.Context { return context.WithValue(ctx, corecontext.CometInfoKey, c) } +func EventsFromContext(ctx context.Context) []event.Event { + iCtx, ok := ctx.Value(contextKey).(*integrationContext) + if !ok { + return nil + } + return iCtx.events +} + +func GetAttributes(e []event.Event, key string) ([]event.Attribute, bool) { + attrs := make([]event.Attribute, 0) + for _, event := range e { + attributes, err := event.Attributes() + if err != nil { + return nil, false + } + for _, attr := range attributes { + if attr.Key == key { + attrs = append(attrs, attr) + } + } + } + + return attrs, len(attrs) > 0 +} + func GasMeterFromContext(ctx context.Context) gas.Meter { iCtx, ok := ctx.Value(contextKey).(*integrationContext) if !ok { @@ -130,22 +160,63 @@ var ( _ event.Manager = &eventManager{} ) -type eventService struct{} +type eventService struct { +} // EventManager implements event.Service. -func (e *eventService) EventManager(context.Context) event.Manager { - return &eventManager{} +func (e *eventService) EventManager(ctx context.Context) event.Manager { + iCtx, ok := ctx.Value(contextKey).(*integrationContext) + if !ok { + panic("context is not an integration context") + } + + return &eventManager{ctx: iCtx} } -type eventManager struct{} +type eventManager struct { + ctx *integrationContext +} // Emit implements event.Manager. -func (e *eventManager) Emit(event transaction.Msg) error { +func (e *eventManager) Emit(tev transaction.Msg) error { + ev := event.Event{ + Type: gogoproto.MessageName(tev), + Attributes: func() ([]event.Attribute, error) { + outerEvent, err := stf.TypedEventToEvent(tev) + if err != nil { + return nil, err + } + + return outerEvent.Attributes() + }, + Data: func() (json.RawMessage, error) { + buf := new(bytes.Buffer) + jm := &jsonpb.Marshaler{OrigName: true, EmitDefaults: true, AnyResolver: nil} + if err := jm.Marshal(buf, tev); err != nil { + return nil, err + } + + return buf.Bytes(), nil + }, + } + + e.ctx.events = append(e.ctx.events, ev) return nil } // EmitKV implements event.Manager. func (e *eventManager) EmitKV(eventType string, attrs ...event.Attribute) error { + ev := event.Event{ + Type: eventType, + Attributes: func() ([]event.Attribute, error) { + return attrs, nil + }, + Data: func() (json.RawMessage, error) { + return json.Marshal(attrs) + }, + } + + e.ctx.events = append(e.ctx.events, ev) return nil } @@ -232,3 +303,15 @@ func (h *HeaderService) HeaderInfo(ctx context.Context) header.Info { } return iCtx.header } + +var _ gas.Service = &GasService{} + +type GasService struct{} + +func (g *GasService) GasMeter(ctx context.Context) gas.Meter { + return GasMeterFromContext(ctx) +} + +func (g *GasService) GasConfig(ctx context.Context) gas.GasConfig { + return gas.GasConfig{} +} diff --git a/testutil/sims/address_helpers.go b/testutil/sims/address_helpers.go index f90225502b80..3254a2158290 100644 --- a/testutil/sims/address_helpers.go +++ b/testutil/sims/address_helpers.go @@ -35,7 +35,7 @@ func AddTestAddrsFromPubKeys(bankKeeper BankKeeper, stakingKeeper StakingKeeper, // AddTestAddrs constructs and returns accNum amount of accounts with an // initial balance of accAmt in random order -func AddTestAddrs(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx sdk.Context, accNum int, accAmt math.Int) []sdk.AccAddress { +func AddTestAddrs(bankKeeper BankKeeper, stakingKeeper StakingKeeper, ctx context.Context, accNum int, accAmt math.Int) []sdk.AccAddress { return addTestAddrs(bankKeeper, stakingKeeper, ctx, accNum, accAmt, CreateRandomAccounts) }