diff --git a/runtime/app.go b/runtime/app.go index 2ceb7cd3eeb3..79fd23709d77 100644 --- a/runtime/app.go +++ b/runtime/app.go @@ -157,7 +157,7 @@ func (a *App) Configurator() module.Configurator { return a.configurator } -// UnsafeFindStoreKey FindStoreKey fetches a registered StoreKey from the App in linear time. +// UnsafeFindStoreKey fetches a registered StoreKey from the App in linear time. // // NOTE: This should only be used in testing. func (a *App) UnsafeFindStoreKey(storeKey string) storetypes.StoreKey { diff --git a/simapp/app.go b/simapp/app.go index e3e7cfa5def7..25724263dd13 100644 --- a/simapp/app.go +++ b/simapp/app.go @@ -159,9 +159,7 @@ type SimApp struct { invCheckPeriod uint // keys to access the substores - keys map[string]*storetypes.KVStoreKey - tkeys map[string]*storetypes.TransientStoreKey - memKeys map[string]*storetypes.MemoryStoreKey + keys map[string]*storetypes.KVStoreKey // keepers AccountKeeper authkeeper.AccountKeeper @@ -239,9 +237,6 @@ func NewSimApp( govtypes.StoreKey, upgradetypes.StoreKey, ) - // NOTE: The testingkey is just mounted for testing purposes. Actual applications should - // not include this key. - app.memKeys = sdk.NewMemoryStoreKeys("testingkey") // configure state listening capabilities using AppOptions // we are doing nothing with the returned streamingServices and waitGroup in this case @@ -322,13 +317,13 @@ func NewSimApp( app.ModuleManager.SetOrderExportGenesis(genesisModuleOrder...) // Uncomment if you want to set a custom migration order here. - // app.mm.SetOrderMigrations(custom order) + // app.ModuleManager.SetOrderMigrations(custom order) app.ModuleManager.RegisterInvariants(&app.CrisisKeeper) app.ModuleManager.RegisterRoutes(app.Router(), app.QueryRouter(), encodingConfig.Amino) // RegisterUpgradeHandlers is used for registering any on-chain upgrades. - // Make sure it's called after `app.mm` and `app.configurator` are set. + // Make sure it's called after `app.ModuleManager` and `app.configurator` are set. app.RegisterUpgradeHandlers() // add test gRPC service for testing gRPC queries in isolation @@ -347,7 +342,6 @@ func NewSimApp( // initialize stores app.MountKVStores(app.keys) - app.MountMemoryStores(app.memKeys) // initialize BaseApp app.SetInitChainer(app.InitChainer) @@ -411,31 +405,6 @@ func (app *SimApp) GetKey(storeKey string) *storetypes.KVStoreKey { return kvStoreKey } -// GetTKey returns the TransientStoreKey for the provided store key. -// -// NOTE: This is solely to be used for testing purposes. -func (app *SimApp) GetTKey(storeKey string) *storetypes.TransientStoreKey { - return app.tkeys[storeKey] -} - -// GetMemKey returns the MemStoreKey for the provided mem key. -// -// NOTE: This is solely used for testing purposes. -func (app *SimApp) GetMemKey(storeKey string) *storetypes.MemoryStoreKey { - msk := app.memKeys[storeKey] - if msk != nil { - return msk - } - - sk := app.UnsafeFindStoreKey(storeKey) - memStoreKey, ok := sk.(*storetypes.MemoryStoreKey) - if !ok { - return nil - } - - return memStoreKey -} - // GetSubspace returns a param subspace for a given module name. // // NOTE: This is solely to be used for testing purposes. diff --git a/testutil/sims/app_helpers.go b/testutil/sims/app_helpers.go index 2f00346b50dc..26ac443c6482 100644 --- a/testutil/sims/app_helpers.go +++ b/testutil/sims/app_helpers.go @@ -55,11 +55,30 @@ var DefaultConsensusParams = &tmproto.ConsensusParams{ // appConfig usually load from a `app.yaml` with `appconfig.LoadYAML`, defines the application configuration. // extraOutputs defines the extra outputs to be assigned by the dependency injector (depinject). func Setup(appConfig depinject.Config, extraOutputs ...interface{}) (*runtime.App, error) { + return SetupWithBaseAppOption(appConfig, nil, false, extraOutputs...) +} + +// SetupAtGenesis initializes a new runtime.App at genesis. A Nop logger is set in runtime.App. +// appConfig usually load from a `app.yaml` with `appconfig.LoadYAML`, defines the application configuration. +// extraOutputs defines the extra outputs to be assigned by the dependency injector (depinject). +func SetupAtGenesis(appConfig depinject.Config, extraOutputs ...interface{}) (*runtime.App, error) { + return SetupWithBaseAppOption(appConfig, nil, true, extraOutputs...) +} + +// SetupWithBaseAppOption initializes a new runtime.App. A Nop logger is set in runtime.App. +// appConfig usually load from a `app.yaml` with `appconfig.LoadYAML`, defines the application configuration. +// baseAppOption defines the additional operations that must be run on baseapp before app start. +// extraOutputs defines the extra outputs to be assigned by the dependency injector (depinject). +// genesis defines if the app started should already have produced block or not. +func SetupWithBaseAppOption(appConfig depinject.Config, baseAppOption runtime.BaseAppOption, genesis bool, extraOutputs ...interface{}) (*runtime.App, error) { // // create app // - var appBuilder *runtime.AppBuilder - var codec codec.Codec + var ( + app *runtime.App + appBuilder *runtime.AppBuilder + codec codec.Codec + ) if err := depinject.Inject( appConfig, @@ -68,7 +87,11 @@ func Setup(appConfig depinject.Config, extraOutputs ...interface{}) (*runtime.Ap return nil, fmt.Errorf("failed to inject dependencies: %w", err) } - app := appBuilder.Build(log.NewNopLogger(), dbm.NewMemDB(), nil) + if baseAppOption != nil { + app = appBuilder.Build(log.NewNopLogger(), dbm.NewMemDB(), nil, baseAppOption) + } else { + app = appBuilder.Build(log.NewNopLogger(), dbm.NewMemDB(), nil) + } if err := app.Load(true); err != nil { return nil, fmt.Errorf("failed to load app: %w", err) } @@ -114,6 +137,17 @@ func Setup(appConfig depinject.Config, extraOutputs ...interface{}) (*runtime.Ap }, ) + // commit genesis changes + if !genesis { + app.Commit() + app.BeginBlock(abci.RequestBeginBlock{Header: tmproto.Header{ + Height: app.LastBlockHeight() + 1, + AppHash: app.LastCommitID().Hash, + ValidatorsHash: valSet.Hash(), + NextValidatorsHash: valSet.Hash(), + }}) + } + return app, nil } diff --git a/x/capability/capability_test.go b/x/capability/capability_test.go index 24b94cf7d699..b00566b797e9 100644 --- a/x/capability/capability_test.go +++ b/x/capability/capability_test.go @@ -7,39 +7,44 @@ import ( abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" + "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/codec" - "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/runtime" + storetypes "github.com/cosmos/cosmos-sdk/store/types" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/cosmos/cosmos-sdk/types/module" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/capability" "github.com/cosmos/cosmos-sdk/x/capability/keeper" + "github.com/cosmos/cosmos-sdk/x/capability/testutil" "github.com/cosmos/cosmos-sdk/x/capability/types" ) type CapabilityTestSuite struct { suite.Suite + app *runtime.App cdc codec.Codec ctx sdk.Context - app *simapp.SimApp keeper *keeper.Keeper - module module.AppModule + memKey *storetypes.MemoryStoreKey } func (suite *CapabilityTestSuite) SetupTest() { - checkTx := false - app := simapp.Setup(suite.T(), checkTx) - cdc := app.AppCodec() - - // create new keeper so we can define custom scoping before init and seal - keeper := keeper.NewKeeper(cdc, app.GetKey(types.StoreKey), app.GetMemKey(types.MemStoreKey)) + suite.memKey = storetypes.NewMemoryStoreKey("testingkey") + + app, err := simtestutil.SetupWithBaseAppOption(testutil.AppConfig, + func(ba *baseapp.BaseApp) { + ba.MountStores(suite.memKey) + }, + false, + &suite.cdc, + &suite.keeper, + ) + suite.Require().NoError(err) suite.app = app - suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1}) - suite.keeper = keeper - suite.cdc = cdc - suite.module = capability.NewAppModule(cdc, *keeper, true) + suite.ctx = app.BaseApp.NewContext(false, tmproto.Header{Height: 1}) } // The following test case mocks a specific bug discovered in https://github.com/cosmos/cosmos-sdk/issues/9800 @@ -52,7 +57,7 @@ func (suite *CapabilityTestSuite) TestInitializeMemStore() { suite.Require().NotNil(cap1) // mock statesync by creating new keeper that shares persistent state but loses in-memory map - newKeeper := keeper.NewKeeper(suite.cdc, suite.app.GetKey(types.StoreKey), suite.app.GetMemKey("testingkey")) + newKeeper := keeper.NewKeeper(suite.cdc, suite.app.UnsafeFindStoreKey(types.StoreKey).(*storetypes.KVStoreKey), suite.memKey) newSk1 := newKeeper.ScopeToModule(banktypes.ModuleName) // Mock App startup diff --git a/x/capability/genesis_test.go b/x/capability/genesis_test.go index 34a09960e750..00009fd94414 100644 --- a/x/capability/genesis_test.go +++ b/x/capability/genesis_test.go @@ -1,16 +1,14 @@ package capability_test import ( - "github.com/tendermint/tendermint/libs/log" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - dbm "github.com/tendermint/tm-db" - "github.com/cosmos/cosmos-sdk/simapp" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/capability" "github.com/cosmos/cosmos-sdk/x/capability/keeper" - "github.com/cosmos/cosmos-sdk/x/capability/types" + "github.com/cosmos/cosmos-sdk/x/capability/testutil" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -33,11 +31,10 @@ func (suite *CapabilityTestSuite) TestGenesis() { // create new app that does not share persistent or in-memory state // and initialize app from exported genesis state above. - db := dbm.NewMemDB() - encCdc := simapp.MakeTestEncodingConfig() - newApp := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, map[int64]bool{}, simapp.DefaultNodeHome, 5, encCdc, simapp.EmptyAppOptions{}) + var newKeeper *keeper.Keeper + newApp, err := simtestutil.SetupAtGenesis(testutil.AppConfig, &newKeeper) + suite.Require().NoError(err) - newKeeper := keeper.NewKeeper(suite.cdc, newApp.GetKey(types.StoreKey), newApp.GetMemKey(types.MemStoreKey)) newSk1 := newKeeper.ScopeToModule(banktypes.ModuleName) newSk2 := newKeeper.ScopeToModule(stakingtypes.ModuleName) deliverCtx, _ := newApp.BaseApp.NewUncachedContext(false, tmproto.Header{}).WithBlockGasMeter(sdk.NewInfiniteGasMeter()).CacheContext() diff --git a/x/capability/keeper/keeper_test.go b/x/capability/keeper/keeper_test.go index 9757461db71d..0d6a5f06552e 100644 --- a/x/capability/keeper/keeper_test.go +++ b/x/capability/keeper/keeper_test.go @@ -7,10 +7,11 @@ import ( "github.com/stretchr/testify/suite" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" - "github.com/cosmos/cosmos-sdk/simapp" + simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" sdk "github.com/cosmos/cosmos-sdk/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/capability/keeper" + "github.com/cosmos/cosmos-sdk/x/capability/testutil" "github.com/cosmos/cosmos-sdk/x/capability/types" stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types" ) @@ -19,21 +20,16 @@ type KeeperTestSuite struct { suite.Suite ctx sdk.Context - app *simapp.SimApp keeper *keeper.Keeper } func (suite *KeeperTestSuite) SetupTest() { - checkTx := false - app := simapp.Setup(suite.T(), checkTx) - cdc := app.AppCodec() - - // create new keeper so we can define custom scoping before init and seal - keeper := keeper.NewKeeper(cdc, app.GetKey(types.StoreKey), app.GetMemKey(types.MemStoreKey)) + app, err := simtestutil.Setup(testutil.AppConfig, + &suite.keeper, + ) + suite.Require().NoError(err) - suite.app = app - suite.ctx = app.BaseApp.NewContext(checkTx, tmproto.Header{Height: 1}) - suite.keeper = keeper + suite.ctx = app.BaseApp.NewContext(false, tmproto.Header{Height: 1}) } func (suite *KeeperTestSuite) TestSeal() { diff --git a/x/capability/module.go b/x/capability/module.go index c8012522d3c3..3f994cb26b31 100644 --- a/x/capability/module.go +++ b/x/capability/module.go @@ -16,6 +16,7 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" cdctypes "github.com/cosmos/cosmos-sdk/codec/types" + "github.com/cosmos/cosmos-sdk/depinject" "github.com/cosmos/cosmos-sdk/runtime" store "github.com/cosmos/cosmos-sdk/store/types" "github.com/cosmos/cosmos-sdk/telemetry" @@ -165,29 +166,6 @@ func (am AppModule) EndBlock(_ sdk.Context, _ abci.RequestEndBlock) []abci.Valid return []abci.ValidatorUpdate{} } -func init() { - appmodule.Register(&modulev1.Module{}, - appmodule.Provide( - provideModuleBasic, - provideModule, - )) -} - -func provideModuleBasic() runtime.AppModuleBasicWrapper { - return runtime.WrapAppModuleBasic(AppModuleBasic{}) -} - -func provideModule( - kvStoreKey *store.KVStoreKey, - memStoreKey *store.MemoryStoreKey, - cdc codec.Codec, - config *modulev1.Module, -) (*keeper.Keeper, runtime.AppModuleWrapper) { - k := keeper.NewKeeper(cdc, kvStoreKey, memStoreKey) - m := NewAppModule(cdc, *k, config.SealKeeper) - return k, runtime.WrapAppModule(m) -} - // GenerateGenesisState creates a randomized GenState of the capability module. func (AppModule) GenerateGenesisState(simState *module.SimulationState) { simulation.RandomizedGenState(simState) @@ -212,3 +190,46 @@ func (am AppModule) RegisterStoreDecoder(sdr sdk.StoreDecoderRegistry) { func (am AppModule) WeightedOperations(simState module.SimulationState) []simtypes.WeightedOperation { return nil } + +// +// New App Wiring Setup +// + +func init() { + appmodule.Register(&modulev1.Module{}, + appmodule.Provide( + provideModuleBasic, + provideModule, + )) +} + +func provideModuleBasic() runtime.AppModuleBasicWrapper { + return runtime.WrapAppModuleBasic(AppModuleBasic{}) +} + +type capabilityInputs struct { + depinject.In + + Config *modulev1.Module + + KvStoreKey *store.KVStoreKey + MemStoreKey *store.MemoryStoreKey + Cdc codec.Codec +} + +type capabilityOutputs struct { + depinject.Out + + CapabilityKeeper *keeper.Keeper + Module runtime.AppModuleWrapper +} + +func provideModule(in capabilityInputs) capabilityOutputs { + k := keeper.NewKeeper(in.Cdc, in.KvStoreKey, in.MemStoreKey) + m := NewAppModule(in.Cdc, *k, in.Config.SealKeeper) + + return capabilityOutputs{ + CapabilityKeeper: k, + Module: runtime.WrapAppModule(m), + } +} diff --git a/x/capability/simulation/decoder_test.go b/x/capability/simulation/decoder_test.go index 093cf5f2daad..484985bbbc7d 100644 --- a/x/capability/simulation/decoder_test.go +++ b/x/capability/simulation/decoder_test.go @@ -6,15 +6,20 @@ import ( "github.com/stretchr/testify/require" - "github.com/cosmos/cosmos-sdk/simapp" + "github.com/cosmos/cosmos-sdk/codec" + "github.com/cosmos/cosmos-sdk/depinject" sdk "github.com/cosmos/cosmos-sdk/types" "github.com/cosmos/cosmos-sdk/types/kv" "github.com/cosmos/cosmos-sdk/x/capability/simulation" + "github.com/cosmos/cosmos-sdk/x/capability/testutil" "github.com/cosmos/cosmos-sdk/x/capability/types" ) func TestDecodeStore(t *testing.T) { - cdc := simapp.MakeTestEncodingConfig().Codec + var cdc codec.Codec + err := depinject.Inject(testutil.AppConfig, &cdc) + require.NoError(t, err) + dec := simulation.NewDecodeStore(cdc) capOwners := types.CapabilityOwners{ diff --git a/x/capability/spec/03_app_wiring.md b/x/capability/spec/03_app_wiring.md new file mode 100644 index 000000000000..b8d4e29961ca --- /dev/null +++ b/x/capability/spec/03_app_wiring.md @@ -0,0 +1,5 @@ +# App Wiring + +The minimal app-wiring configuration for `x/capability` is as follows: + ++++ https://github.com/cosmos/cosmos-sdk/blob/main/x/capability/testutil/app.yaml diff --git a/x/capability/spec/README.md b/x/capability/spec/README.md index 96a2dcbd9726..d20a2a9f7aa6 100644 --- a/x/capability/spec/README.md +++ b/x/capability/spec/README.md @@ -75,3 +75,4 @@ func NewApp(...) *App { 1. **[Concepts](01_concepts.md)** 1. **[State](02_state.md)** +1. **[App Wiring](03_app_wiring.md)** diff --git a/x/capability/testutil/app.yaml b/x/capability/testutil/app.yaml new file mode 100644 index 000000000000..c0bf0b059a6d --- /dev/null +++ b/x/capability/testutil/app.yaml @@ -0,0 +1,46 @@ +modules: + - name: runtime + config: + "@type": cosmos.app.runtime.v1alpha1.Module + + app_name: CapabilityApp + + begin_blockers: [capability, staking, auth, bank, genutil, params] + end_blockers: [staking, capability, auth, bank, genutil, params] + init_genesis: [capability, auth, bank, staking, genutil, params] + + - name: auth + config: + "@type": cosmos.auth.module.v1.Module + bech32_prefix: cosmos + module_account_permissions: + - account: fee_collector + - account: bonded_tokens_pool + permissions: [burner, staking] + - account: not_bonded_tokens_pool + permissions: [burner, staking] + + - name: bank + config: + "@type": cosmos.bank.module.v1.Module + + - name: params + config: + "@type": cosmos.params.module.v1.Module + + - name: tx + config: + "@type": cosmos.tx.module.v1.Module + + - name: staking + config: + "@type": cosmos.staking.module.v1.Module + + - name: genutil + config: + "@type": cosmos.genutil.module.v1.Module + + - name: capability + config: + "@type": cosmos.capability.module.v1.Module + seal_keeper: true diff --git a/x/capability/testutil/app_config.go b/x/capability/testutil/app_config.go new file mode 100644 index 000000000000..85678ee39ec6 --- /dev/null +++ b/x/capability/testutil/app_config.go @@ -0,0 +1,19 @@ +package testutil + +import ( + _ "embed" + + "cosmossdk.io/core/appconfig" + _ "github.com/cosmos/cosmos-sdk/x/auth" + _ "github.com/cosmos/cosmos-sdk/x/auth/tx/module" + _ "github.com/cosmos/cosmos-sdk/x/bank" + _ "github.com/cosmos/cosmos-sdk/x/capability" + _ "github.com/cosmos/cosmos-sdk/x/genutil" + _ "github.com/cosmos/cosmos-sdk/x/params" + _ "github.com/cosmos/cosmos-sdk/x/staking" +) + +//go:embed app.yaml +var appConfig []byte + +var AppConfig = appconfig.LoadYAML(appConfig) diff --git a/x/nft/simulation/operations_test.go b/x/nft/simulation/operations_test.go index f417fb9efa6e..e5feef0c896d 100644 --- a/x/nft/simulation/operations_test.go +++ b/x/nft/simulation/operations_test.go @@ -54,13 +54,6 @@ func (suite *SimTestSuite) SetupTest() { suite.app = app suite.ctx = app.BaseApp.NewContext(false, tmproto.Header{}) - - suite.app.BeginBlock(abci.RequestBeginBlock{ - Header: tmproto.Header{ - Height: suite.app.LastBlockHeight() + 1, - AppHash: suite.app.LastCommitID().Hash, - }, - }) } func (suite *SimTestSuite) TestWeightedOperations() { @@ -122,6 +115,14 @@ func (suite *SimTestSuite) TestSimulateMsgSend() { blockTime := time.Now().UTC() ctx := suite.ctx.WithBlockTime(blockTime) + // begin new block + suite.app.BeginBlock(abci.RequestBeginBlock{ + Header: tmproto.Header{ + Height: suite.app.LastBlockHeight() + 1, + AppHash: suite.app.LastCommitID().Hash, + }, + }) + // execute operation registry := suite.interfaceRegistry op := simulation.SimulateMsgSend(codec.NewProtoCodec(registry), suite.accountKeeper, suite.bankKeeper, suite.nftKeeper)