Skip to content

Commit

Permalink
feat(core): add migrations registering (#19370)
Browse files Browse the repository at this point in the history
Co-authored-by: Facundo Medica <14063057+facundomedica@users.noreply.github.com>
  • Loading branch information
julienrbrt and facundomedica committed Feb 9, 2024
1 parent ac48269 commit e15a0de
Show file tree
Hide file tree
Showing 43 changed files with 429 additions and 277 deletions.
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,6 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i
* (crypto | x/auth) [#14372](https://github.com/cosmos/cosmos-sdk/pull/18194) Key checks on signatures antehandle.
* (types) [#18963](https://github.com/cosmos/cosmos-sdk/pull/18963) Swap out amino json encoding of `ABCIMessageLogs` for std lib json encoding

### Deprecated

* (simapp) [#19146](https://github.com/cosmos/cosmos-sdk/pull/19146) Replace `--v` CLI option with `--validator-count`/`-n`.

### Bug Fixes

* (baseapp) [#19338](https://github.com/cosmos/cosmos-sdk/pull/19338) Set HeaderInfo in context when calling `setState`.
Expand Down Expand Up @@ -144,6 +140,11 @@ Every module contains its own CHANGELOG.md. Please refer to the module you are i

* (server) [#18303](https://github.com/cosmos/cosmos-sdk/pull/18303) `appd export` has moved with other genesis commands, use `appd genesis export` instead.

### Deprecated

* (simapp) [#19146](https://github.com/cosmos/cosmos-sdk/pull/19146) Replace `--v` CLI option with `--validator-count`/`-n`.
* (module) [#19370](https://github.com/cosmos/cosmos-sdk/pull/19370) Deprecate `module.Configurator`, use `appmodule.HasMigrations` and `appmodule.HasServicecs` instead from Core API.

## [v0.50.3](https://github.com/cosmos/cosmos-sdk/releases/tag/v0.50.3) - 2023-01-15

### Features
Expand Down
92 changes: 46 additions & 46 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,45 @@ Note, always read the **SimApp** section for more information on application wir

## [Unreleased]

### Unordered Transactions
### SimApp

In this section we describe the changes made in Cosmos SDK' SimApp.
**These changes are directly applicable to your application wiring.**

#### 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.

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

The `client` package has been refactored to make use of the address codecs (address, validator address, consensus address, etc.).
This is part of the work of abstracting the SDK from the global bech32 config.

This means the address codecs must be provided in the `client.Context` in the application client (usually `root.go`).

```diff
clientCtx = clientCtx.
+ WithAddressCodec(addressCodec).
+ WithValidatorAddressCodec(validatorAddressCodec).
+ WithConsensusAddressCodec(consensusAddressCodec)
```

**When using `depinject` / `app v2`, the client codecs can be provided directly from application config.**

Refer to SimApp `root_v2.go` and `root.go` for an example with an app v2 and a legacy app.

### Core

`appmodule.Environment` interface was introduced to fetch different services from the application. This can be used as an alternative to using `sdk.UnwrapContext(ctx)` to fetch the services. It needs to be passed into a module at instantiation.

Circuit Breaker is used as an example.

```go
app.CircuitKeeper = circuitkeeper.NewKeeper(runtime.NewEnvironment((keys[circuittypes.StoreKey]), nil), appCodec, authtypes.NewModuleAddress(govtypes.ModuleName).String(), app.AuthKeeper.AddressCodec())
```

#### 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
Expand Down Expand Up @@ -80,57 +118,19 @@ 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.

### Params

* Params migrations were removed. It is required to migrate to 0.50 prior to upgrading to v0.51.

### SimApp

In this section we describe the changes made in Cosmos SDK' SimApp.
**These changes are directly applicable to your application wiring.**

#### 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.

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

The `client` package has been refactored to make use of the address codecs (address, validator address, consensus address, etc.).
This is part of the work of abstracting the SDK from the global bech32 config.

This means the address codecs must be provided in the `client.Context` in the application client (usually `root.go`).

```diff
clientCtx = clientCtx.
+ WithAddressCodec(addressCodec).
+ WithValidatorAddressCodec(validatorAddressCodec).
+ WithConsensusAddressCodec(consensusAddressCodec)
```

**When using `depinject` / `app v2`, the client codecs can be provided directly from application config.**

Refer to SimApp `root_v2.go` and `root.go` for an example with an app v2 and a legacy app.

#### Dependency Injection

<!-- explain app_config.go changes -->

### Core
### Modules

`appmodule.Environment` interface was introduced to fetch different services from the application. This can be used as an alternative to using `sdk.UnwrapContext(ctx)` to fetch the services. It needs to be passed into a module at instantiation.
#### `**all**`

Circuit Breaker is used as an example.
##### Params

```go
app.CircuitKeeper = circuitkeeper.NewKeeper(runtime.NewEnvironment((keys[circuittypes.StoreKey]), nil), appCodec, authtypes.NewModuleAddress(govtypes.ModuleName).String(), app.AuthKeeper.AddressCodec())
```
Old 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.

### Modules
##### Core API

#### `**all**`
Core API has been introduces for modules in 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.

##### Dependency Injection
##### Dependency Injection

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
3 changes: 2 additions & 1 deletion core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ Ref: https://keepachangelog.com/en/1.0.0/
* [#18379](https://github.com/cosmos/cosmos-sdk/pull/18379) Add branch service.
* [#18457](https://github.com/cosmos/cosmos-sdk/pull/18457) Add branch.ExecuteWithGasLimit.
* [#19041](https://github.com/cosmos/cosmos-sdk/pull/19041) Add `appmodule.Environment` interface to fetch different services
* [#19370](https://github.com/cosmos/cosmos-sdk/pull/19370) Add `appmodule.Migrations` interface to handle migrations

### API Breaking
### API Breaking Changes

* [#18857](https://github.com/cosmos/cosmos-sdk/pull/18857) Moved `FormatCoins` to `x/tx`.
* [#18861](httpes://github.com/cosmos/cosmos-sdk/pull/18861) Moved `coin.ParseCoin` to `client/v2/internal`.
Expand Down
16 changes: 16 additions & 0 deletions core/appmodule/migrations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package appmodule

import "context"

type MigrationRegistrar interface {
// Register registers an in-place store migration for a module. The
// handler is a migration script to perform in-place migrations from version
// `fromVersion` to version `fromVersion+1`.
//
// EACH TIME a module's ConsensusVersion increments, a new migration MUST
// be registered using this function. If a migration handler is missing for
// a particular function, the upgrade logic (see RunMigrations function)
// will panic. If the ConsensusVersion bump does not introduce any store
// changes, then a no-op function must be registered here.
Register(moduleName string, fromVersion uint64, handler func(context.Context) error) error
}
28 changes: 19 additions & 9 deletions core/appmodule/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,12 @@ type HasServices interface {
RegisterServices(grpc.ServiceRegistrar) error
}

// HasPrepareCheckState is an extension interface that contains information about the AppModule
// and PrepareCheckState.
type HasPrepareCheckState interface {
// HasMigrations is the extension interface that modules should implement to register migrations.
type HasMigrations interface {
AppModule
PrepareCheckState(context.Context) error
}

// HasPrecommit is an extension interface that contains information about the AppModule and Precommit.
type HasPrecommit interface {
AppModule
Precommit(context.Context) error
// RegisterMigrations registers the module's migrations with the app's migrator.
RegisterMigrations(MigrationRegistrar) error
}

// ResponsePreBlock represents the response from the PreBlock method.
Expand Down Expand Up @@ -100,3 +95,18 @@ type HasMsgHandler interface {
// RegisterMsgHandlers is implemented by the module that will register msg handlers.
RegisterMsgHandlers(router MsgHandlerRouter)
}

// ---------------------------------------------------------------------------- //

// HasPrepareCheckState is an extension interface that contains information about the AppModule
// and PrepareCheckState.
type HasPrepareCheckState interface {
AppModule
PrepareCheckState(context.Context) error
}

// HasPrecommit is an extension interface that contains information about the AppModule and Precommit.
type HasPrecommit interface {
AppModule
Precommit(context.Context) error
}
2 changes: 2 additions & 0 deletions docs/build/building-modules/13-upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ Since these migrations are functions that need access to a Keeper's store, use a
https://github.com/cosmos/cosmos-sdk/blob/v0.50.0-alpha.0/x/bank/keeper/migrations.go
```

<!-- TODO v0.51: explain the new way with core -->

## Writing Migration Scripts

To define the functionality that takes place during an upgrade, write a migration script and place the functions in a `migrations/` directory. For example, to write migration scripts for the bank module, place the functions in `x/bank/migrations/`. Use the recommended naming convention for these functions. For example, `v2bank` is the script that migrates the package `x/bank/migrations/v2`:
Expand Down
2 changes: 2 additions & 0 deletions runtime/services/autocli.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ func (a *autocliConfigurator) RegisterMigration(string, uint64, module.Migration
return nil
}

func (a *autocliConfigurator) Register(string, uint64, func(context.Context) error) error { return nil }

func (a *autocliConfigurator) RegisterService(sd *grpc.ServiceDesc, ss interface{}) {
if a.registryCache == nil {
a.registryCache, a.err = proto.MergedRegistry()
Expand Down
15 changes: 15 additions & 0 deletions types/module/configurator.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package module

import (
"context"
"fmt"

"github.com/cosmos/gogoproto/grpc"
Expand All @@ -20,6 +21,8 @@ import (
// their services in the RegisterServices method. It is designed to eventually
// support module object capabilities isolation as described in
// https://github.com/cosmos/cosmos-sdk/issues/7093
// Deprecated: The Configurator is deprecated.
// Preferably use core services for registering msg/query server and migrations.
type Configurator interface {
grpc.Server

Expand All @@ -45,6 +48,10 @@ type Configurator interface {
// will panic. If the ConsensusVersion bump does not introduce any store
// changes, then a no-op function must be registered here.
RegisterMigration(moduleName string, fromVersion uint64, handler MigrationHandler) error

// Register registers an in-place store migration for a module.
// It permits to register modules migrations that have migrated to serverv2 but still be compatible with baseapp.
Register(moduleName string, fromVersion uint64, handler func(context.Context) error) error
}

type configurator struct {
Expand Down Expand Up @@ -119,6 +126,14 @@ func (c *configurator) RegisterMigration(moduleName string, fromVersion uint64,
return nil
}

// Register implements the Configurator.Register method
// It allows to register modules migrations that have migrated to server/v2 but still be compatible with baseapp.
func (c *configurator) Register(moduleName string, fromVersion uint64, handler func(context.Context) error) error {
return c.RegisterMigration(moduleName, fromVersion, func(sdkCtx sdk.Context) error {
return handler(sdkCtx)
})
}

// runModuleMigrations runs all in-place store migrations for one given module from a
// version to another version.
func (c *configurator) runModuleMigrations(ctx sdk.Context, moduleName string, fromVersion, toVersion uint64) error {
Expand Down
7 changes: 7 additions & 0 deletions types/module/core_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,13 @@ func (c coreAppModuleBasicAdaptor) RegisterServices(cfg Configurator) {
panic(err)
}
}

if module, ok := c.module.(appmodule.HasMigrations); ok {
err := module.RegisterMigrations(cfg)
if err != nil {
panic(err)
}
}
}

func (c coreAppModuleBasicAdaptor) IsOnePerModuleType() {}
Expand Down
7 changes: 7 additions & 0 deletions types/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,13 @@ func (m *Manager) RegisterServices(cfg Configurator) error {
}
}

if module, ok := module.(appmodule.HasMigrations); ok {
err := module.RegisterMigrations(cfg)
if err != nil {
return err
}
}

if cfg.Error() != nil {
return cfg.Error()
}
Expand Down
19 changes: 9 additions & 10 deletions x/auth/keeper/migrations.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package keeper

import (
"github.com/cosmos/gogoproto/grpc"
"context"

v5 "cosmossdk.io/x/auth/migrations/v5"
"cosmossdk.io/x/auth/types"
Expand All @@ -11,46 +11,45 @@ import (

// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
keeper AccountKeeper
queryServer grpc.Server
keeper AccountKeeper
}

// NewMigrator returns a new Migrator.
func NewMigrator(keeper AccountKeeper, queryServer grpc.Server) Migrator {
return Migrator{keeper: keeper, queryServer: queryServer}
func NewMigrator(keeper AccountKeeper) Migrator {
return Migrator{keeper: keeper}
}

// Migrate1to2 migrates from version 1 to 2.
func (m Migrator) Migrate1to2(ctx sdk.Context) error {
func (m Migrator) Migrate1to2(ctx context.Context) error {
return nil
}

// Migrate2to3 migrates from consensus version 2 to version 3. Specifically, for each account
// we index the account's ID to their address.
func (m Migrator) Migrate2to3(ctx sdk.Context) error {
func (m Migrator) Migrate2to3(ctx context.Context) error {
return nil
}

// Migrate3to4 migrates the x/auth module state from the consensus version 3 to
// version 4. Specifically, it takes the parameters that are currently stored
// and managed by the x/params modules and stores them directly into the x/auth
// module state.
func (m Migrator) Migrate3to4(ctx sdk.Context) error {
func (m Migrator) Migrate3to4(ctx context.Context) error {
return nil
}

// Migrate4To5 migrates the x/auth module state from the consensus version 4 to 5.
// It migrates the GlobalAccountNumber from being a protobuf defined value to a
// big-endian encoded uint64, it also migrates it to use a more canonical prefix.
func (m Migrator) Migrate4To5(ctx sdk.Context) error {
func (m Migrator) Migrate4To5(ctx context.Context) error {
return v5.Migrate(ctx, m.keeper.storeService, m.keeper.AccountNumber)
}

// V45_SetAccount implements V45_SetAccount
// set the account without map to accAddr to accNumber.
//
// NOTE: This is used for testing purposes only.
func (m Migrator) V45SetAccount(ctx sdk.Context, acc sdk.AccountI) error {
func (m Migrator) V45SetAccount(ctx context.Context, acc sdk.AccountI) error {
addr := acc.GetAddress()
store := m.keeper.storeService.OpenKVStore(ctx)

Expand Down
Loading

0 comments on commit e15a0de

Please sign in to comment.