From 12edad662664603b973259d83b5f06843493c9f2 Mon Sep 17 00:00:00 2001 From: Julien Robert Date: Sat, 17 Aug 2024 09:33:15 +0200 Subject: [PATCH] docs: rename app v2 to app di when talking about runtime v0 (#21329) (cherry picked from commit 651868a177d00c423e3086e6c255bf729ccd25f3) # Conflicts: # UPGRADING.md --- UPGRADING.md | 407 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 403 insertions(+), 4 deletions(-) diff --git a/UPGRADING.md b/UPGRADING.md index 354844624ae6..4dd072bbaeb2 100644 --- a/UPGRADING.md +++ b/UPGRADING.md @@ -3,7 +3,406 @@ This guide provides instructions for upgrading to specific versions of Cosmos SDK. Note, always read the **SimApp** section for more information on application wiring updates. +<<<<<<< HEAD ## [v0.50.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.0) +======= +## [Unreleased] + +### BaseApp + +#### Nested Messages Simulation + +Now it is possible to simulate the nested messages of a message, providing developers with a powerful tool for +testing and predicting the behavior of complex transactions. This feature allows for a more comprehensive +evaluation of gas consumption, state changes, and potential errors that may occur when executing nested +messages. However, it's important to note that while the simulation can provide valuable insights, it does not +guarantee the correct execution of the nested messages in the future. Factors such as changes in the +blockchain state or updates to the protocol could potentially affect the actual execution of these nested +messages when the transaction is finally processed on the network. + +For example, consider a governance proposal that includes nested messages to update multiple protocol +parameters. At the time of simulation, the blockchain state may be suitable for executing all these nested +messages successfully. However, by the time the actual governance proposal is executed (which could be days or +weeks later), the blockchain state might have changed significantly. As a result, while the simulation showed +a successful execution, the actual governance proposal might fail when it's finally processed. + +By default, when simulating transactions, the gas cost of nested messages is not calculated. This means that +only the gas cost of the top-level message is considered. However, this behavior can be customized using the +`SetIncludeNestedMsgsGas` option when building the BaseApp. By providing a list of message types to this option, +you can specify which messages should have their nested message gas costs included in the simulation. This +allows for more accurate gas estimation for transactions involving specific message types that contain nested +messages, while maintaining the default behavior for other message types. + +Here is an example on how `SetIncludeNestedMsgsGas` option could be set to calculate the gas of a gov proposal +nested messages: + +```go +baseAppOptions = append(baseAppOptions, baseapp.SetIncludeNestedMsgsGas([]sdk.Message{&gov.MsgSubmitProposal{}})) +// ... +app.App = appBuilder.Build(db, traceStore, baseAppOptions...) +``` + +## [v0.52.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.52.0-alpha.0) + +Documentation to migrate an application from v0.50.x to server/v2 is available elsewhere. +It is additional to the changes described here. + +### SimApp + +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`) + +The `client` package has been refactored to make use of the address codecs (address, validator address, consensus address, etc.) +and address bech32 prefixes (address and validator address). +This is part of the work of abstracting the SDK from the global bech32 config. + +This means the address codecs and prefixes must be provided in the `client.Context` in the application client (usually `root.go`). + +```diff +clientCtx = clientCtx. ++ WithAddressCodec(addressCodec). ++ WithValidatorAddressCodec(validatorAddressCodec). ++ WithConsensusAddressCodec(consensusAddressCodec). ++ WithAddressPrefix("cosmos"). ++ WithValidatorPrefix("cosmosvaloper") +``` + +**When using `depinject` / `app_di`, the client codecs can be provided directly from application config.** + +Refer to SimApp `root_di.go` and `root.go` for an example with an app di and a legacy app. + +Additionally, a simplification of the start command leads to the following change: + +```diff +- server.AddCommands(rootCmd, newApp, func(startCmd *cobra.Command) {}) ++ server.AddCommands(rootCmd, newApp, server.StartCmdOptions[servertypes.Application]{}) +``` + +#### Server (`app.go`) + +##### Module Manager + +The basic module manager has been deleted. It was not necessary anymore and was simplified to use the `module.Manager` directly. +It can be removed from your `app.go`. + +For depinject users, it isn't necessary anymore to supply a `map[string]module.AppModuleBasic` for customizing the app module basic instantiation. +The custom parameters (such as genutil message validator or gov proposal handler, or evidence handler) can directly be supplied. +When requiring a module manager in `root.go`, inject `*module.Manager` using `depinject.Inject`. + +For non depinject users, simply call `RegisterLegacyAminoCodec` and `RegisterInterfaces` on the module manager: + +```diff +-app.BasicModuleManager = module.NewBasicManagerFromManager(...) +-app.BasicModuleManager.RegisterLegacyAminoCodec(legacyAmino) +-app.BasicModuleManager.RegisterInterfaces(interfaceRegistry) ++app.ModuleManager.RegisterLegacyAminoCodec(legacyAmino) ++app.ModuleManager.RegisterInterfaces(interfaceRegistry) +``` + +Additionally, thanks to the genesis simplification, as explained in [the genesis interface update](#genesis-interface), the module manager `InitGenesis` and `ExportGenesis` methods do not require the codec anymore. + +##### GRPC-WEB + +Grpc-web embedded client has been removed from the server. If you would like to use grpc-web, you can use the [envoy proxy](https://www.envoyproxy.io/docs/envoy/latest/start/start). + +##### AnteHandlers + +The `GasConsumptionDecorator` and `IncreaseSequenceDecorator` have been merged with the SigVerificationDecorator, so you'll +need to remove them both from your app.go code, they will yield to unresolvable symbols when compiling. + +#### Unordered Transactions + +The Cosmos SDK now supports unordered transactions. This means that transactions +can be executed in any order and doesn't require the client to deal with or manage +nonces. This also means the order of execution is not guaranteed. To enable unordered +transactions in your application: + +* Update the `App` constructor to create, load, and save the unordered transaction + manager. + + ```go + func NewApp(...) *App { + // ... + + // create, start, and load the unordered tx manager + utxDataDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data") + app.UnorderedTxManager = unorderedtx.NewManager(utxDataDir) + app.UnorderedTxManager.Start() + + if err := app.UnorderedTxManager.OnInit(); err != nil { + panic(fmt.Errorf("failed to initialize unordered tx manager: %w", err)) + } + } + ``` + +* Add the decorator to the existing AnteHandler chain, which should be as early + as possible. + + ```go + anteDecorators := []sdk.AnteDecorator{ + ante.NewSetUpContextDecorator(), + // ... + ante.NewUnorderedTxDecorator(unorderedtx.DefaultMaxTimeoutDuration, options.TxManager, options.Environment), + // ... + } + + return sdk.ChainAnteDecorators(anteDecorators...), nil + ``` + +* If the App has a SnapshotManager defined, you must also register the extension + for the TxManager. + + ```go + if manager := app.SnapshotManager(); manager != nil { + err := manager.RegisterExtensions(unorderedtx.NewSnapshotter(app.UnorderedTxManager)) + if err != nil { + panic(fmt.Errorf("failed to register snapshot extension: %s", err)) + } + } + ``` + +* Create or update the App's `Close()` method to close the unordered tx manager. + Note, this is critical as it ensures the manager's state is written to file + such that when the node restarts, it can recover the state to provide replay + protection. + + ```go + func (app *App) Close() error { + // ... + + // close the unordered tx manager + if e := app.UnorderedTxManager.Close(); e != nil { + err = errors.Join(err, e) + } + + return err + } + ``` + +To submit an unordered transaction, the client must set the `unordered` flag to +`true` and ensure a reasonable `timeout_height` is set. The `timeout_height` is +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) . 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`. +There is no longer a need for the Cosmos SDK to host these protos for itself and its dependencies. +That package containing proto v2 generated code, but the SDK now uses [buf generated go SDK instead](https://buf.build/docs/bsr/generated-sdks/go). +If you were depending on `cosmossdk.io/api/tendermint`, please use the buf generated go SDK instead, or ask CometBFT host the generated proto v2 code. + +The `codectypes.Any` has moved to `github.com/cosmos/gogoproto/types/any`. Module developers need to update the `buf.gen.gogo.yaml` configuration files by adjusting the corresponding `opt` option to `Mgoogle/protobuf/any.proto=github.com/cosmos/gogoproto/types/any` for directly mapping the`Any` type to its new location: + +```diff +version: v1 +plugins: + - name: gocosmos + out: .. +- opt: plugins=grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/cosmos-sdk/codec/types,Mcosmos/orm/v1/orm.proto=cosmossdk.io/orm ++ opt: plugins=grpc,Mgoogle/protobuf/any.proto=github.com/cosmos/gogoproto/types/any,Mcosmos/orm/v1/orm.proto=cosmossdk.io/orm + - name: grpc-gateway + out: .. + opt: logtostderr=true,allow_colon_final_segments=true + +``` + +Also, any usages of the interfaces `AnyUnpacker` and `UnpackInterfacesMessage` must be replaced with the interfaces of the same name in the `github.com/cosmos/gogoproto/types/any` package. + +### Modules + +#### `**all**` + +##### Core API + +Core API has been introduced for modules since v0.47. With the deprecation of `sdk.Context`, we strongly recommend to use the `cosmossdk.io/core/appmodule` interfaces for the modules. This will allow the modules to work out of the box with server/v2 and baseapp, as well as limit their dependencies on the SDK. + +Additionally, the `appmodule.Environment` struct is introduced to fetch different services from the application. +This should be used as an alternative to using `sdk.UnwrapContext(ctx)` to fetch the services. +It needs to be passed into a module at instantiation (or depinject will inject the correct environment). + +`x/circuit` is used as an example: + +```go +app.CircuitKeeper = circuitkeeper.NewKeeper(runtime.NewEnvironment(runtime.NewKVStoreService(keys[circuittypes.StoreKey]), logger.With(log.ModuleKey, "x/circuit")), appCodec, authtypes.NewModuleAddress(govtypes.ModuleName).String(), app.AuthKeeper.AddressCodec()) +``` + +If your module requires a message server or query server, it should be passed in the environment as well. + +```diff +-govKeeper := govkeeper.NewKeeper(appCodec, runtime.NewKVStoreService(keys[govtypes.StoreKey]), app.AuthKeeper, app.BankKeeper,app.StakingKeeper, app.PoolKeeper, app.MsgServiceRouter(), govConfig, authtypes.NewModuleAddress(govtypes.ModuleName).String()) ++govKeeper := govkeeper.NewKeeper(appCodec, runtime.NewEnvironment(runtime.NewKVStoreService(keys[govtypes.StoreKey]), logger.With(log.ModuleKey, "x/circuit"), runtime.EnvWithMsgRouterService(app.MsgServiceRouter()), runtime.EnvWithQueryRouterService(app.GRPCQueryRouter())), app.AuthKeeper, app.BankKeeper, app.StakingKeeper, app.PoolKeeper, govConfig, authtypes.NewModuleAddress(govtypes.ModuleName).String()) +``` + +The signature of the extension interface `HasRegisterInterfaces` has been changed to accept a `cosmossdk.io/core/registry.InterfaceRegistrar` instead of a `codec.InterfaceRegistry`. `HasRegisterInterfaces` is now a part of `cosmossdk.io/core/appmodule`. Modules should update their `HasRegisterInterfaces` implementation to accept a `cosmossdk.io/core/registry.InterfaceRegistrar` interface. + +```diff +-func (AppModule) RegisterInterfaces(registry codectypes.InterfaceRegistry) { ++func (AppModule) RegisterInterfaces(registry registry.InterfaceRegistrar) { +``` + +The signature of the extension interface `HasAminoCodec` has been changed to accept a `cosmossdk.io/core/legacy.Amino` instead of a `codec.LegacyAmino`. Modules should update their `HasAminoCodec` implementation to accept a `cosmossdk.io/core/legacy.Amino` interface. + +```diff +-func (AppModule) RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) { ++func (AppModule) RegisterLegacyAminoCodec(cdc legacy.Amino) { +``` + +##### Simulation + +`MsgSimulatorFn` has been updated to return an error. Its context argument has been removed, and an address.Codec has +been added to avoid the use of the Accounts.String() method. + +```diff +-type MsgSimulatorFn func(r *rand.Rand, ctx sdk.Context, accs []Account) sdk.Msg ++type MsgSimulatorFn func(r *rand.Rand, accs []Account, cdc address.Codec) (sdk.Msg, error) +``` + +##### 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. + +##### Params + +Previous module migrations have been removed. It is required to migrate to v0.50 prior to upgrading to v0.51 for not missing any module migrations. + +##### Genesis Interface + +All genesis interfaces have been migrated to take `context.Context` instead of `sdk.Context`. +Secondly, the codec is no longer passed in by the framework. The codec is now passed in by the module. +Lastly, all InitGenesis and ExportGenesis functions now return an error. + +```go +// InitGenesis performs genesis initialization for the module. +func (am AppModule) InitGenesis(ctx context.Context, data json.RawMessage) error { +} + +// ExportGenesis returns the exported genesis state as raw bytes for the module. +func (am AppModule) ExportGenesis(ctx context.Context) (json.RawMessage, error) { +} +``` + +##### Migration to Collections + +Most of Cosmos SDK modules have migrated to [collections](https://docs.cosmos.network/main/build/packages/collections). +Many functions have been removed due to this changes as the API can be smaller thanks to collections. +For modules that have migrated, verify you are checking against `collections.ErrNotFound` when applicable. + +#### `x/accounts` + +Accounts's AccountNumber will be used as a global account number tracking replacing Auth legacy AccountNumber. Must set accounts's AccountNumber with auth's AccountNumber value in upgrade handler. This is done through auth keeper MigrateAccountNumber function. + +```go +import authkeeper "cosmossdk.io/x/auth/keeper" +... +err := authkeeper.MigrateAccountNumberUnsafe(ctx, &app.AuthKeeper) +if err != nil { + return nil, err +} +``` + +#### `x/auth` + +Auth was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/auth` + +#### `x/authz` + +Authz was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/authz` + +#### `x/bank` + +Bank was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/bank` + +### `x/crsis` + +The Crisis module was removed due to it not being supported or functional any longer. + +#### `x/distribution` + +Distribution was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/distribution` + +The existing chains using x/distribution module needs to add the new x/protocolpool module. + +#### `x/group` + +Group was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/group` + +#### `x/gov` + +Gov was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/gov` + +Gov v1beta1 proposal handler has been changed to take in a `context.Context` instead of `sdk.Context`. +This change was made to allow legacy proposals to be compatible with server/v2. +If you wish to migrate to server/v2, you should update your proposal handler to take in a `context.Context` and use services. +On the other hand, if you wish to keep using baseapp, simply unwrap the sdk context in your proposal handler. + +#### `x/mint` + +Mint was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/mint` + +#### `x/slashing` + +Slashing was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/slashing` + +#### `x/staking` + +Staking was spun out into its own `go.mod`. To import it use `cosmossdk.io/x/staking` + +#### `x/params` + +A standalone Go module was created and it is accessible at "cosmossdk.io/x/params". + +#### `x/protocolpool` + +Introducing a new `x/protocolpool` module to handle community pool funds. Its store must be added while upgrading to v0.51.x. + +Example: + +```go +func (app SimApp) RegisterUpgradeHandlers() { + app.UpgradeKeeper.SetUpgradeHandler( + UpgradeName, + func(ctx sdk.Context, _ upgradetypes.Plan, fromVM module.VersionMap) (module.VersionMap, error) { + return app.ModuleManager.RunMigrations(ctx, app.Configurator(), fromVM) + }, + ) + + // ... +} +``` + +Add `x/protocolpool` store while upgrading to v0.51.x: + +```go +storetypes.StoreUpgrades{ + Added: []string{ + protocolpooltypes.ModuleName, + }, +} +``` + +## [v0.50.x](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.0-alpha.0) +>>>>>>> 651868a17 (docs: rename app v2 to app di when talking about runtime v0 (#21329)) ### Migration to CometBFT (Part 2) @@ -72,7 +471,7 @@ for more info. A `SetPreBlocker` method has been added to BaseApp. This is essential for BaseApp to run `PreBlock` which runs before begin blocker other modules, and allows to modify consensus parameters, and the changes are visible to the following state machine logics. Read more about other use cases [here](https://github.com/cosmos/cosmos-sdk/blob/main/docs/architecture/adr-068-preblock.md). -`depinject` / app v2 users need to add `x/upgrade` in their `app_config.go` / `app.yml`: +`depinject` / app di users need to add `x/upgrade` in their `app_config.go` / `app.yml`: ```diff + PreBlockers: []string{ @@ -180,7 +579,7 @@ The following modules `NewKeeper` function now take a `KVStoreService` instead o * `x/slashing` * `x/upgrade` -**Users using `depinject` / app v2 do not need any changes, this is abstracted for them.** +**Users using `depinject` / app di do not need any changes, this is abstracted for them.** Users manually wiring their chain need to use the `runtime.NewKVStoreService` method to create a `KVStoreService` from a `StoreKey`: @@ -197,7 +596,7 @@ app.ConsensusParamsKeeper = consensusparamkeeper.NewKeeper( Replace all your CometBFT logger imports by `cosmossdk.io/log`. -Additionally, `depinject` / app v2 users must now supply a logger through the main `depinject.Supply` function instead of passing it to `appBuilder.Build`. +Additionally, `depinject` / app di users must now supply a logger through the main `depinject.Supply` function instead of passing it to `appBuilder.Build`. ```diff appConfig = depinject.Configs( @@ -221,7 +620,7 @@ User manually wiring their chain need to add the logger argument when creating t Previously, the `ModuleBasics` was a global variable that was used to register all modules' `AppModuleBasic` implementation. The global variable has been removed and the basic module manager can be now created from the module manager. -This is automatically done for `depinject` / app v2 users, however for supplying different app module implementation, pass them via `depinject.Supply` in the main `AppConfig` (`app_config.go`): +This is automatically done for `depinject` / app di users, however for supplying different app module implementation, pass them via `depinject.Supply` in the main `AppConfig` (`app_config.go`): ```go depinject.Supply(