Skip to content

Commit

Permalink
feat(runtime,runtime/v2): skip store for specified modules (cosmos#20409
Browse files Browse the repository at this point in the history
)
  • Loading branch information
julienrbrt authored May 27, 2024
1 parent fe6361b commit 190b20c
Show file tree
Hide file tree
Showing 13 changed files with 537 additions and 102 deletions.
20 changes: 19 additions & 1 deletion UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Note, always read the **SimApp** section for more information on application wir

In this section we describe the changes made in Cosmos SDK' SimApp.
**These changes are directly applicable to your application wiring.**
Please read this section first, but for an exhaustive list of changes, refer to the [CHANGELOG](./simapp/CHANGELOG.md).

#### Client (`root.go`)

Expand Down Expand Up @@ -145,6 +146,23 @@ used as a TTL for the transaction and is used to provide replay protection. See
[ADR-070](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-070-unordered-transactions.md)
for more details.

### Depinject `app_config.go` / `app.yml`

With the introduction of [environment in modules](#core-api), depinject automatically creates the environment for all modules.
Learn more about environment [here](https://example.com) <!-- TODO -->. Given the fields of environment, this means runtime creates a kv store service for all modules by default.
It can happen that some modules do not have a store necessary (such as `x/auth/tx` for instance). In this case, the store creation should be skipped in `app_config.go`:

```diff
InitGenesis: []string{
"..."
},
+ // SkipStoreKeys is an optional list of store keys to skip when constructing the
+ // module's keeper. This is useful when a module does not have a store key.
+ SkipStoreKeys: []string{
+ "tx",
+ },
```

### Protobuf

The `cosmossdk.io/api/tendermint` package has been removed as CometBFT now publishes its protos to `buf.build/tendermint` and `buf.build/cometbft`.
Expand Down Expand Up @@ -203,7 +221,7 @@ been added to avoid the use of the Accounts.String() method.
+type MsgSimulatorFn func(r *rand.Rand, accs []Account, cdc address.Codec) (sdk.Msg, error)
```

##### Dependency Injection
##### Depinject

Previously `cosmossdk.io/core` held functions `Invoke`, `Provide` and `Register` were moved to `cosmossdk.io/depinject/appconfig`.
All modules using dependency injection must update their imports.
Expand Down
213 changes: 175 additions & 38 deletions api/cosmos/app/runtime/v1alpha1/module.pulsar.go

Large diffs are not rendered by default.

207 changes: 172 additions & 35 deletions api/cosmos/app/runtime/v2/module.pulsar.go

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ module cosmossdk.io/api

go 1.21

toolchain go1.22.1

require (
buf.build/gen/go/cometbft/cometbft/protocolbuffers/go v1.34.1-20240312114316-c0d3497e35d6.1
github.com/cosmos/cosmos-proto v1.0.0-beta.5
Expand Down
2 changes: 0 additions & 2 deletions go.work.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
go 1.22.2

toolchain go1.22.2

use (
.
./api
Expand Down
5 changes: 5 additions & 0 deletions proto/cosmos/app/runtime/v1alpha1/module.proto
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ message Module {
// to be used in keeper construction.
repeated StoreKeyConfig override_store_keys = 6;

// skip_store_keys is an optional list of store keys to skip when constructing the
// module's keeper. This is useful when a module does not have a store key.
// NOTE: the provided environment variable will have a fake store service.
repeated string skip_store_keys = 11;

// order_migrations defines the order in which module migrations are performed.
// If this is left empty, it uses the default migration order.
// https://pkg.go.dev/github.com/cosmos/[email protected]/types/module#DefaultMigrationsOrder
Expand Down
5 changes: 5 additions & 0 deletions proto/cosmos/app/runtime/v2/module.proto
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ message Module {
// override_store_keys is an optional list of overrides for the module store keys
// to be used in keeper construction.
repeated StoreKeyConfig override_store_keys = 10;

// skip_store_keys is an optional list of store keys to skip when constructing the
// module's keeper. This is useful when a module does not have a store key.
// NOTE: the provided environment variable will have a fake store service.
repeated string skip_store_keys = 11;
}

// GasConfig is the config object for gas limits.
Expand Down
57 changes: 47 additions & 10 deletions runtime/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package runtime
import (
"fmt"
"os"
"slices"

"github.com/cosmos/gogoproto/proto"
"google.golang.org/protobuf/reflect/protodesc"
Expand Down Expand Up @@ -192,6 +193,10 @@ func ProvideKVStoreKey(
key depinject.ModuleKey,
app *AppBuilder,
) *storetypes.KVStoreKey {
if slices.Contains(config.SkipStoreKeys, key.Name()) {
return nil
}

override := storeKeyOverride(config, key.Name())

var storeKeyName string
Expand All @@ -206,13 +211,29 @@ func ProvideKVStoreKey(
return storeKey
}

func ProvideTransientStoreKey(key depinject.ModuleKey, app *AppBuilder) *storetypes.TransientStoreKey {
func ProvideTransientStoreKey(
config *runtimev1alpha1.Module,
key depinject.ModuleKey,
app *AppBuilder,
) *storetypes.TransientStoreKey {
if slices.Contains(config.SkipStoreKeys, key.Name()) {
return nil
}

storeKey := storetypes.NewTransientStoreKey(fmt.Sprintf("transient:%s", key.Name()))
registerStoreKey(app, storeKey)
return storeKey
}

func ProvideMemoryStoreKey(key depinject.ModuleKey, app *AppBuilder) *storetypes.MemoryStoreKey {
func ProvideMemoryStoreKey(
config *runtimev1alpha1.Module,
key depinject.ModuleKey,
app *AppBuilder,
) *storetypes.MemoryStoreKey {
if slices.Contains(config.SkipStoreKeys, key.Name()) {
return nil
}

storeKey := storetypes.NewMemoryStoreKey(fmt.Sprintf("memory:%s", key.Name()))
registerStoreKey(app, storeKey)
return storeKey
Expand All @@ -234,23 +255,39 @@ func ProvideEnvironment(
msgServiceRouter *baseapp.MsgServiceRouter,
queryServiceRouter *baseapp.GRPCQueryRouter,
) (store.KVStoreService, store.MemoryStoreService, appmodule.Environment) {
storeKey := ProvideKVStoreKey(config, key, app)
kvService := kvStoreService{key: storeKey}
var (
kvService store.KVStoreService = failingStoreService{}
memKvService store.MemoryStoreService = failingStoreService{}
)

memStoreKey := ProvideMemoryStoreKey(key, app)
memStoreService := memStoreService{key: memStoreKey}
// skips modules that have no store
if !slices.Contains(config.SkipStoreKeys, key.Name()) {
storeKey := ProvideKVStoreKey(config, key, app)
kvService = kvStoreService{key: storeKey}

memStoreKey := ProvideMemoryStoreKey(config, key, app)
memKvService = memStoreService{key: memStoreKey}
}

return kvService, memStoreService, NewEnvironment(
return kvService, memKvService, NewEnvironment(
kvService,
logger.With(log.ModuleKey, fmt.Sprintf("x/%s", key.Name())),
EnvWithMsgRouterService(msgServiceRouter),
EnvWithQueryRouterService(queryServiceRouter),
EnvWithMemStoreService(memStoreService),
EnvWithMemStoreService(memKvService),
)
}

func ProvideTransientStoreService(key depinject.ModuleKey, app *AppBuilder) store.TransientStoreService {
storeKey := ProvideTransientStoreKey(key, app)
func ProvideTransientStoreService(
config *runtimev1alpha1.Module,
key depinject.ModuleKey,
app *AppBuilder,
) store.TransientStoreService {
storeKey := ProvideTransientStoreKey(config, key, app)
if storeKey == nil {
return failingStoreService{}
}

return transientStoreService{key: storeKey}
}

Expand Down
14 changes: 14 additions & 0 deletions runtime/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,20 @@ func (t transientStoreService) OpenTransientStore(ctx context.Context) store.KVS
return newKVStore(sdk.UnwrapSDKContext(ctx).KVStore(t.key))
}

type failingStoreService struct{}

func (failingStoreService) OpenKVStore(ctx context.Context) store.KVStore {
panic("kv store service not available for this module: verify runtime `skip_store_keys` app config if not expected")
}

func (failingStoreService) OpenMemoryStore(ctx context.Context) store.KVStore {
panic("memory kv store service not available for this module: verify runtime `skip_store_keys` app config if not expected")
}

func (failingStoreService) OpenTransientStore(ctx context.Context) store.KVStore {
panic("transient kv store service not available for this module: verify runtime `skip_store_keys` app config if not expected")
}

// CoreKVStore is a wrapper of Core/Store kvstore interface
// Remove after https://github.com/cosmos/cosmos-sdk/issues/14714 is closed
type coreKVStore struct {
Expand Down
38 changes: 24 additions & 14 deletions runtime/v2/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package runtime
import (
"fmt"
"os"
"slices"

"github.com/cosmos/gogoproto/proto"
"google.golang.org/grpc"
Expand Down Expand Up @@ -185,19 +186,28 @@ func ProvideEnvironment(logger log.Logger, config *runtimev2.Module, key depinje
store.KVStoreService,
store.MemoryStoreService,
) {
var kvStoreKey string
storeKeyOverride := storeKeyOverride(config, key.Name())
if storeKeyOverride != nil {
kvStoreKey = storeKeyOverride.KvStoreKey
} else {
kvStoreKey = key.Name()
}
registerStoreKey(appBuilder, kvStoreKey)
kvService := stf.NewKVStoreService([]byte(kvStoreKey))
var (
kvService store.KVStoreService = failingStoreService{}
memKvService store.MemoryStoreService = failingStoreService{}
)

// skips modules that have no store
if !slices.Contains(config.SkipStoreKeys, key.Name()) {
var kvStoreKey string
storeKeyOverride := storeKeyOverride(config, key.Name())
if storeKeyOverride != nil {
kvStoreKey = storeKeyOverride.KvStoreKey
} else {
kvStoreKey = key.Name()
}

registerStoreKey(appBuilder, kvStoreKey)
kvService = stf.NewKVStoreService([]byte(kvStoreKey))

memStoreKey := fmt.Sprintf("memory:%s", key.Name())
registerStoreKey(appBuilder, memStoreKey)
memService := stf.NewMemoryStoreService([]byte(memStoreKey))
memStoreKey := fmt.Sprintf("memory:%s", key.Name())
registerStoreKey(appBuilder, memStoreKey)
memKvService = stf.NewMemoryStoreService([]byte(memStoreKey))
}

env := appmodulev2.Environment{
Logger: logger,
Expand All @@ -209,10 +219,10 @@ func ProvideEnvironment(logger log.Logger, config *runtimev2.Module, key depinje
MsgRouterService: stf.NewMsgRouterService(appBuilder.app.msgRouterBuilder),
TransactionService: services.NewContextAwareTransactionService(),
KVStoreService: kvService,
MemStoreService: memService,
MemStoreService: memKvService,
}

return env, kvService, memService
return env, kvService, memKvService
}

func registerStoreKey(wrapper *AppBuilder, key string) {
Expand Down
21 changes: 21 additions & 0 deletions runtime/v2/stub.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package runtime

import (
"context"

"cosmossdk.io/core/store"
)

type failingStoreService struct{}

func (failingStoreService) OpenKVStore(ctx context.Context) store.KVStore {
panic("kv store service not available for this module: verify runtime `skip_store_keys` app config if not expected")
}

func (failingStoreService) OpenMemoryStore(ctx context.Context) store.KVStore {
panic("memory kv store service not available for this module: verify runtime `skip_store_keys` app config if not expected")
}

func (failingStoreService) OpenTransientStore(ctx context.Context) store.KVStore {
panic("transient kv store service not available for this module: verify runtime `skip_store_keys` app config if not expected")
}
50 changes: 50 additions & 0 deletions simapp/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<!--
Guiding Principles:
Changelogs are for humans, not machines.
There should be an entry for every single version.
The same types of changes should be grouped.
Versions and sections should be linkable.
The latest version comes first.
The release date of each version is displayed.
Mention whether you follow Semantic Versioning.
Usage:
Change log entries are to be added to the Unreleased section under the
appropriate stanza (see below). Each entry should ideally include a tag and
the Github issue reference in the following format:
* (<tag>) [#<issue-number>] Changelog message.
Types of changes (Stanzas):
"Features" for new features.
"Improvements" for changes in existing functionality.
"Deprecated" for soon-to-be removed features.
"Bug Fixes" for any bug fixes.
"API Breaking" for breaking exported APIs used by developers building on SDK.
Ref: https://keepachangelog.com/en/1.0.0/
-->

# Changelog

`SimApp` is an application built using the Cosmos SDK for testing and educational purposes.
It won't be tagged or intented to be imported in an application.
This changelog is aimed to help developers understand the wiring changes between SDK versions.
It is an exautive list of changes that completes the SimApp section in the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#simapp)

## v0.50 to v0.51

Always refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md) to understand the changes.

* [#20409](https://github.com/cosmos/cosmos-sdk/pull/20409) Add `tx` as `SkipStoreKeys` in `app_config.go`.

<!-- TODO: move changelog.md elements to here -->

## v0.47 to v0.50

No changelog is provided for this migration. Please refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#v050x)

## v0.46 to v0.47

No changelog is provided for this migration. Please refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#v047x)

## v0.45 to v0.46

No changelog is provided for this migration. Please refer to the [UPGRADING.md](https://github.com/cosmos/cosmos-sdk/blob/main/UPGRADING.md#v046x)

5 changes: 5 additions & 0 deletions simapp/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ var (
// ExportGenesis: []string{},
// Uncomment if you want to set a custom migration order here.
// OrderMigrations: []string{},
// SkipStoreKeys is an optional list of store keys to skip when constructing the
// module's keeper. This is useful when a module does not have a store key.
SkipStoreKeys: []string{
"tx",
},
}),
},
{
Expand Down

0 comments on commit 190b20c

Please sign in to comment.