Synopsis
In-place store migrations allow modules to upgrade to new versions that include breaking changes. This document covers both the module-side (writing migrations) and the app-side (running migrations during an upgrade).
Consensus Version
Successful upgrades of existing modules require eachAppModule to implement the function ConsensusVersion() uint64.
- The versions must be hard-coded by the module developer.
- The initial version must be set to 1.
Registering Migrations
To register the functionality that takes place during a module upgrade, you must register which migrations you want to take place. Migration registration takes place in theConfigurator using the RegisterMigration method. The AppModule reference to the configurator is in the RegisterServices method.
You can register one or more migrations. If you register more than one migration script, list the migrations in increasing order and ensure there are enough migrations that lead to the desired consensus version. For example, to migrate to version 3 of a module, register separate migrations for version 1 and version 2 as shown in the following example:
Migrator as shown in this example:
Writing Migration Scripts
To define the functionality that takes place during an upgrade, write a migration script and place the functions in amigrations/ directory. For example, to write migration scripts for the bank module, place the functions in x/bank/migrations/. Import each version package and call its MigrateStore function from the corresponding Migrator method:
Running Migrations in the App
Once modules have registered their migrations, the app runs them inside anUpgradeHandler. The upgrade handler type is:
VersionMap stored by x/upgrade (reflecting the consensus versions from the previous binary), performs any additional upgrade logic, and must return the updated VersionMap from RunMigrations. Register the handler in app.go:
RunMigrations iterates over all registered modules in order, checks each module’s version in the VersionMap, and runs all registered migration scripts for modules whose consensus version has increased. The updated VersionMap is returned to the upgrade keeper, which persists it in the x/upgrade store.
Order of migrations
By default, migrations run in alphabetical order by module name, with one exception:x/auth runs last due to state dependencies with other modules (see cosmos/cosmos-sdk#10591). To change the order, call app.ModuleManager.SetOrderMigrations(module1, module2, ...) in app.go. The function panics if any registered module is omitted.
Adding new modules during an upgrade
New modules are recognized because they have no entry in thex/upgrade VersionMap store. RunMigrations calls InitGenesis for them automatically.
If you need to add stores for a new module, configure the store loader before the upgrade runs:
InitGenesis for a new module (for example, if you are manually initializing state in the handler), set its version in fromVM before calling RunMigrations:
Genesis state
When starting a new chain, the consensus version of each module must be saved to state during genesis. Add this toInitChainer in app.go:
Overwriting genesis functions
The SDK provides modules that app developers can import, and those modules often already have anInitGenesis function. If you want to run a custom genesis function for one of those modules during an upgrade instead of the default one, you must both call your custom function in the handler AND manually set that module’s consensus version in fromVM. Without the second step, RunMigrations will run the module’s existing InitGenesis even though you already initialized it.