Co-authored-by: Alex | Interchain Labs <alex@interchainlabs.io> Co-authored-by: Tyler <48813565+technicallyty@users.noreply.github.com>
This commit is contained in:
parent
65acc32084
commit
6a1ec1bfc0
2
docs/docs/build/abci/01-prepare-proposal.md
vendored
2
docs/docs/build/abci/01-prepare-proposal.md
vendored
@ -33,7 +33,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/baseapp/abci_utils.go
|
||||
```
|
||||
|
||||
This default implementation can be overridden by the application developer in
|
||||
favor of a custom implementation in [`app_di.go`](../building-apps/01-app-go-v2.md):
|
||||
favor of a custom implementation in [`app_di.go`](../building-apps/01-app-go-di.md):
|
||||
|
||||
```go
|
||||
prepareOpt := func(app *baseapp.BaseApp) {
|
||||
|
||||
2
docs/docs/build/abci/02-process-proposal.md
vendored
2
docs/docs/build/abci/02-process-proposal.md
vendored
@ -18,7 +18,7 @@ https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/baseapp/abci_utils.go#L21
|
||||
```
|
||||
|
||||
Like `PrepareProposal`, this implementation is the default and can be modified by
|
||||
the application developer in [`app_di.go`](../building-apps/01-app-go-v2.md). If you decide to implement
|
||||
the application developer in [`app_di.go`](../building-apps/01-app-go-di.md). If you decide to implement
|
||||
your own `ProcessProposal` handler, you must ensure that the transactions
|
||||
provided in the proposal DO NOT exceed the maximum block gas and `maxtxbytes` (if set).
|
||||
|
||||
|
||||
152
docs/docs/build/building-apps/00-runtime.md
vendored
Normal file
152
docs/docs/build/building-apps/00-runtime.md
vendored
Normal file
@ -0,0 +1,152 @@
|
||||
---
|
||||
sidebar_position: 1
|
||||
---
|
||||
|
||||
# What is `runtime`?
|
||||
|
||||
The `runtime` package in the Cosmos SDK provides a flexible framework for configuring and managing blockchain applications. It serves as the foundation for creating modular blockchain applications using a declarative configuration approach.
|
||||
|
||||
## Overview
|
||||
|
||||
The runtime package acts as a wrapper around the `BaseApp` and `ModuleManager`, offering a hybrid approach where applications can be configured both declaratively through configuration files and programmatically through traditional methods.
|
||||
It is a layer of abstraction between `baseapp` and the application modules that simplifies the process of building a Cosmos SDK application.
|
||||
|
||||
## Core Components
|
||||
|
||||
### App Structure
|
||||
|
||||
The runtime App struct contains several key components:
|
||||
|
||||
```go
|
||||
type App struct {
|
||||
*baseapp.BaseApp
|
||||
ModuleManager *module.Manager
|
||||
configurator module.Configurator
|
||||
config *runtimev1alpha1.Module
|
||||
storeKeys []storetypes.StoreKey
|
||||
// ... other fields
|
||||
}
|
||||
```
|
||||
|
||||
Cosmos SDK applications should embed the `*runtime.App` struct to leverage the runtime module.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_di.go#L60-L61
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
The runtime module is configured using App Wiring. The main configuration object is the [`Module` message](https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/proto/cosmos/app/runtime/v1alpha1/module.proto), which supports the following key settings:
|
||||
|
||||
* `app_name`: The name of the application
|
||||
* `begin_blockers`: List of module names to call during BeginBlock
|
||||
* `end_blockers`: List of module names to call during EndBlock
|
||||
* `init_genesis`: Order of module initialization during genesis
|
||||
* `export_genesis`: Order for exporting module genesis data
|
||||
* `pre_blockers`: Modules to execute before block processing
|
||||
|
||||
Learn more about wiring `runtime` in the [next section](./01-app-go-di.md).
|
||||
|
||||
#### Store Configuration
|
||||
|
||||
By default, the runtime module uses the module name as the store key.
|
||||
However it provides a flexible store key configuration through:
|
||||
|
||||
* `override_store_keys`: Allows customizing module store keys
|
||||
* `skip_store_keys`: Specifies store keys to skip during keeper construction
|
||||
|
||||
Example configuration:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L133-L138
|
||||
```
|
||||
|
||||
## Key Features
|
||||
|
||||
### 1. BaseApp and other Core SDK components integration
|
||||
|
||||
The runtime module integrates with the `BaseApp` and other core SDK components to provide a seamless experience for developers.
|
||||
|
||||
The developer only needs to embed the `runtime.App` struct in their application to leverage the runtime module.
|
||||
The configuration of the module manager and other core components is handled internally via the [`AppBuilder`](#4-application-building).
|
||||
|
||||
### 2. Module Registration
|
||||
|
||||
Runtime has built-in support for [`depinject`-enabled modules](../building-modules/15-depinject.md).
|
||||
Such modules can be registered through the configuration file (often named `app_config.go`), with no additional code required.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L210-L216
|
||||
```
|
||||
|
||||
Additionally, the runtime package facilitates manual module registration through the `RegisterModules` method. This is the primary integration point for modules not registered via configuration.
|
||||
|
||||
:::warning
|
||||
Even when using manual registration, the module should still be configured in the `Module` message in AppConfig.
|
||||
:::
|
||||
|
||||
```go
|
||||
func (a *App) RegisterModules(modules ...module.AppModule) error
|
||||
```
|
||||
|
||||
The SDK recommends using the declarative approach with `depinject` for module registration whenever possible.
|
||||
|
||||
### 3. Service Registration
|
||||
|
||||
Runtime registers all [core services](https://pkg.go.dev/cosmossdk.io/core) required by modules.
|
||||
These services include `store`, `event manager`, `context`, and `logger`.
|
||||
Runtime ensures that services are scoped to their respective modules during the wiring process.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/runtime/module.go#L201-L235
|
||||
```
|
||||
|
||||
Additionally, runtime provides automatic registration of other essential (i.e., gRPC routes) services available to the App:
|
||||
|
||||
* AutoCLI Query Service
|
||||
* Reflection Service
|
||||
* Custom module services
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/runtime/builder.go#L52-L54
|
||||
```
|
||||
|
||||
### 4. Application Building
|
||||
|
||||
The `AppBuilder` type provides a structured way to build applications:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/runtime/builder.go#L14-L19
|
||||
```
|
||||
|
||||
Key building steps:
|
||||
|
||||
1. Configuration loading
|
||||
2. Module registration
|
||||
3. Service setup
|
||||
4. Store mounting
|
||||
5. Router configuration
|
||||
|
||||
An application only needs to call `AppBuilder.Build` to create a fully configured application (`runtime.App`).
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/runtime/builder.go#L26-L57
|
||||
```
|
||||
|
||||
More information on building applications can be found in the [next section](./02-app-building.md).
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Module Order**: Carefully consider the order of modules in begin_blockers, end_blockers, and pre_blockers.
|
||||
2. **Store Keys**: Use override_store_keys only when necessary to maintain clarity
|
||||
3. **Genesis Order**: Maintain correct initialization order in init_genesis
|
||||
4. **Migration Management**: Use order_migrations to control upgrade paths
|
||||
|
||||
### Migration Considerations
|
||||
|
||||
When upgrading between versions:
|
||||
|
||||
1. Review the migration order specified in `order_migrations`
|
||||
2. Ensure all required modules are included in the configuration
|
||||
3. Validate store key configurations
|
||||
4. Test the upgrade path thoroughly
|
||||
@ -6,16 +6,17 @@ sidebar_position: 1
|
||||
|
||||
:::note Synopsis
|
||||
|
||||
The Cosmos SDK allows much easier wiring of an `app.go` thanks to App Wiring and [`depinject`](../packages/01-depinject.md).
|
||||
The Cosmos SDK allows much easier wiring of an `app.go` thanks to [runtime](./00-runtime.md) and app wiring.
|
||||
Learn more about the rationale of App Wiring in [ADR-057](../architecture/adr-057-app-wiring.md).
|
||||
|
||||
:::
|
||||
|
||||
:::note Pre-requisite Readings
|
||||
|
||||
* [ADR 057: App Wiring](../architecture/adr-057-app-wiring.md)
|
||||
* [Depinject Documentation](../packages/01-depinject.md)
|
||||
* [What is `runtime`?](./00-runtime.md)
|
||||
* [Depinject documentation](../packages/01-depinject.md)
|
||||
* [Modules depinject-ready](../building-modules/15-depinject.md)
|
||||
* [ADR 057: App Wiring](../architecture/adr-057-app-wiring.md)
|
||||
|
||||
:::
|
||||
|
||||
@ -28,30 +29,39 @@ The `app_config.go` file is the single place to configure all modules parameters
|
||||
1. Create the `AppConfig` variable:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L290
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L289-L303
|
||||
```
|
||||
|
||||
Where the `appConfig` combines the [runtime](./00-runtime.md) configuration and the (extra) modules configuration.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_di.go#L113-L161
|
||||
```
|
||||
|
||||
2. Configure the `runtime` module:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L289-L302
|
||||
```
|
||||
|
||||
3. Configure the modules defined in the `PreBlocker`, `BeginBlocker` and `EndBlocker` and the `tx` module:
|
||||
In this configuration, the order at which the modules are defined in PreBlockers, BeginBlocks, and EndBlockers is important.
|
||||
They are named in the order they should be executed by the module manager.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L108-L132
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L103-L188
|
||||
```
|
||||
|
||||
3. Wire the other modules:
|
||||
|
||||
Next to runtime, the other (depinject-enabled) modules are wired in the `AppConfig`:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L103-L286
|
||||
```
|
||||
|
||||
Note: the `tx` isn't a module, but a configuration. It should be wired in the `AppConfig` as well.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go#L222-L227
|
||||
```
|
||||
|
||||
### Complete `app_config.go`
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go
|
||||
```
|
||||
See the complete `app_config.go` file for `SimApp` [here](https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_config.go).
|
||||
|
||||
### Alternative formats
|
||||
|
||||
@ -93,12 +103,12 @@ modules:
|
||||
"@type": cosmos.tx.module.v1.Module
|
||||
```
|
||||
|
||||
A more complete example of `app.yaml` can be found [here](https://github.com/cosmos/cosmos-sdk/blob/91b1d83f1339e235a1dfa929ecc00084101a19e3/simapp/app.yaml).
|
||||
A more complete example of `app.yaml` can be found [here](https://github.com/cosmonity/chain-minimal/blob/mini-v050.3/app/app.yaml).
|
||||
|
||||
## `app_di.go`
|
||||
|
||||
`app_di.go` is the place where `SimApp` is constructed. `depinject.Inject` facilitates this by automatically wiring the app modules and keepers, with the provided application configuration `AppConfig`. `SimApp` is constructed upon calling the `Build` method on the injected `*runtime.AppBuilder`.
|
||||
In short, `depinject` and the [`runtime` package](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/runtime) abstract the wiring of the app, and the `AppBuilder` takes care of constructing the application. [`runtime`](https://pkg.go.dev/github.com/cosmos/cosmos-sdk/runtime) handles registering the codecs, KV store, subspaces, and instantiating `baseapp`.
|
||||
`app_di.go` is the place where `SimApp` is constructed. `depinject.Inject` automatically wires the app modules and keepers when provided with an application configuration (`AppConfig`). `SimApp` is constructed upon calling the injected `*runtime.AppBuilder` with `appBuilder.Build(...)`.
|
||||
In short `depinject` and the [`runtime` package](./00-runtime.md) abstract the wiring of the app, and the `AppBuilder` is the place where the app is constructed. [`runtime`](./00-runtime.md) takes care of registering the codecs, KV store, subspaces and instantiating `baseapp`.
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_di.go#L100-L270
|
||||
@ -29,7 +29,7 @@ Namely, the SDK provides the following mempools:
|
||||
* [Sender Nonce Mempool](#sender-nonce-mempool)
|
||||
* [Priority Nonce Mempool](#priority-nonce-mempool)
|
||||
|
||||
The default SDK is a [No-op Mempool](#no-op-mempool), but it can be replaced by the application developer in [`app.go`](./01-app-go-v2.md):
|
||||
By default, the SDK uses the [No-op Mempool](#no-op-mempool), but it can be replaced by the application developer in [`app.go`](./01-app-go-di.md):
|
||||
|
||||
```go
|
||||
nonceMempool := mempool.NewSenderNonceMempool()
|
||||
|
||||
@ -121,4 +121,4 @@ The module is now ready to be used with `depinject` by a chain developer.
|
||||
|
||||
## Integrate in an application
|
||||
|
||||
The App Wiring is done in `app_config.go` / `app.yaml` and `app_v2.go` and is explained in detail in the [overview of `app_v2.go`](../building-apps/01-app-go-v2.md).
|
||||
The App Wiring is done in `app_config.go` / `app.yaml` and `app_v2.go` and is explained in detail in the [overview of `app_v2.go`](../building-apps/01-app-go-di.md).
|
||||
|
||||
@ -50,17 +50,17 @@ In general, the core of the state-machine is defined in a file called `app.go`.
|
||||
|
||||
The first thing defined in `app.go` is the `type` of the application. It is generally comprised of the following parts:
|
||||
|
||||
* **A reference to [`baseapp`](../advanced/00-baseapp.md).** The custom application defined in `app.go` is an extension of `baseapp`. When a transaction is relayed by CometBFT to the application, `app` uses `baseapp`'s methods to route them to the appropriate module. `baseapp` implements most of the core logic for the application, including all the [ABCI methods](https://docs.cometbft.com/v0.37/spec/abci/) and the [routing logic](../advanced/00-baseapp.md#routing).
|
||||
* **A list of store keys**. The [store](../advanced/04-store.md), which contains the entire state, is implemented as a [`multistore`](../advanced/04-store.md#multistore) (i.e. a store of stores) in the Cosmos SDK. Each module uses one or multiple stores in the multistore to persist their part of the state. These stores can be accessed with specific keys that are declared in the `app` type. These keys, along with the `keepers`, are at the heart of the [object-capabilities model](../advanced/10-ocap.md) of the Cosmos SDK.
|
||||
* **A list of module's `keeper`s.** Each module defines an abstraction called [`keeper`](../../build/building-modules/06-keeper.md), which handles reads and writes for this module's store(s). The `keeper`'s methods of one module can be called from other modules (if authorized), which is why they are declared in the application's type and exported as interfaces to other modules so that the latter can only access the authorized functions.
|
||||
* **Embeding [runtime.App](../../build/building-apps/00-runtime.md)** The runtime package manages the application's core components and modules through dependency injection. It provides declarative configuration for module management, state storage, and ABCI handling.
|
||||
* `Runtime` wraps `BaseApp`, meaning when a transaction is relayed by CometBFT to the application, `app` uses `runtime`'s methods to route them to the appropriate module. `BaseApp` implements all the [ABCI methods](https://docs.cometbft.com/v0.38/spec/abci/) and the [routing logic](../advanced/00-baseapp.md#service-routers).
|
||||
* It automatically configures the **[module manager](../../build/building-modules/01-module-manager.md#manager)** based on the app wiring configuration. The module manager facilitates operations related to these modules, like registering their [`Msg` service](../../build/building-modules/03-msg-services.md) and [gRPC `Query` service](#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`PreBlocker`](#preblocker) and [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker).
|
||||
* [**An App Wiring configuration file**](../../build/building-apps/00-runtime.md) The app wiring configuration file contains the list of application's modules that `runtime` must instantiate. The instantiation of the modules are done using `depinject`. It also contains the order in which all module's `InitGenesis` and `Pre/Begin/EndBlocker` methods should be executed.
|
||||
* **A reference to an [`appCodec`](../advanced/05-encoding.md).** The application's `appCodec` is used to serialize and deserialize data structures in order to store them, as stores can only persist `[]bytes`. The default codec is [Protocol Buffers](../advanced/05-encoding.md).
|
||||
* **A reference to a [`legacyAmino`](../advanced/05-encoding.md) codec.** Some parts of the Cosmos SDK have not been migrated to use the `appCodec` above, and are still hardcoded to use Amino. Other parts explicitly use Amino for backwards compatibility. For these reasons, the application still holds a reference to the legacy Amino codec. Please note that the Amino codec will be removed from the SDK in the upcoming releases.
|
||||
* **A reference to a [module manager](../../build/building-modules/01-module-manager.md#manager)** and a [basic module manager](../../build/building-modules/01-module-manager.md#basicmanager). The module manager is an object that contains a list of the application's modules. It facilitates operations related to these modules, like registering their [`Msg` service](../advanced/00-baseapp.md#msg-services) and [gRPC `Query` service](../advanced/00-baseapp.md#grpc-query-services), or setting the order of execution between modules for various functions like [`InitChainer`](#initchainer), [`PreBlocker`](#preblocker) and [`BeginBlocker` and `EndBlocker`](#beginblocker-and-endblocker).
|
||||
|
||||
See an example of application type definition from `simapp`, the Cosmos SDK's own app used for demo and testing purposes:
|
||||
|
||||
```go reference
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/simapp/app.go#L173-L212
|
||||
https://github.com/cosmos/cosmos-sdk/blob/v0.53.0-rc.2/simapp/app_di.go#L57-L90
|
||||
```
|
||||
|
||||
### Constructor Function
|
||||
|
||||
@ -3,6 +3,7 @@ package runtime
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"slices"
|
||||
|
||||
"github.com/cosmos/gogoproto/proto"
|
||||
"google.golang.org/protobuf/reflect/protodesc"
|
||||
@ -199,6 +200,10 @@ func storeKeyOverride(config *runtimev1alpha1.Module, moduleName string) *runtim
|
||||
}
|
||||
|
||||
func ProvideKVStoreKey(config *runtimev1alpha1.Module, key depinject.ModuleKey, app *AppBuilder) *storetypes.KVStoreKey {
|
||||
if slices.Contains(config.SkipStoreKeys, key.Name()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
override := storeKeyOverride(config, key.Name())
|
||||
|
||||
var storeKeyName string
|
||||
@ -213,13 +218,21 @@ func ProvideKVStoreKey(config *runtimev1alpha1.Module, key depinject.ModuleKey,
|
||||
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
|
||||
@ -234,13 +247,13 @@ func ProvideKVStoreService(config *runtimev1alpha1.Module, key depinject.ModuleK
|
||||
return kvStoreService{key: storeKey}
|
||||
}
|
||||
|
||||
func ProvideMemoryStoreService(key depinject.ModuleKey, app *AppBuilder) store.MemoryStoreService {
|
||||
storeKey := ProvideMemoryStoreKey(key, app)
|
||||
func ProvideMemoryStoreService(config *runtimev1alpha1.Module, key depinject.ModuleKey, app *AppBuilder) store.MemoryStoreService {
|
||||
storeKey := ProvideMemoryStoreKey(config, key, app)
|
||||
return memStoreService{key: storeKey}
|
||||
}
|
||||
|
||||
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)
|
||||
return transientStoreService{key: storeKey}
|
||||
}
|
||||
|
||||
|
||||
@ -136,6 +136,9 @@ var (
|
||||
KvStoreKey: "acc",
|
||||
},
|
||||
},
|
||||
SkipStoreKeys: []string{
|
||||
"tx",
|
||||
},
|
||||
// NOTE: The genutils module must occur after staking so that pools are
|
||||
// properly initialized with tokens from genesis accounts.
|
||||
// NOTE: The genutils module must also occur after auth so that it can access the params from auth.
|
||||
|
||||
Loading…
Reference in New Issue
Block a user