Skip to main content

Upgrading a Blockchain to use Ignite CLI v0.18

Ignite CLI v0.18 comes with Cosmos SDK v0.44. This version of Cosmos SDK introduced changes that are not compatible with chains that were scaffolded with Ignite CLI versions lower than v0.18.

Important: After upgrading from Ignite CLI v0.17.3 to Ignite CLI v0.18, you must update the default blockchain template to use blockchains that were scaffolded with earlier versions.

These instructions are written for a blockchain that was scaffolded with the following command:

ignite scaffold chain github.com/username/mars

If you used a different module path, replace username and mars with the correct values for your blockchain.

Blockchain

For each file listed, make the required changes to the source code of the blockchain template.

go.mod

module github.com/username/mars

go 1.16

require (
github.com/cosmos/cosmos-sdk v0.44.0
github.com/cosmos/ibc-go v1.2.0
github.com/gogo/protobuf v1.3.3
github.com/google/go-cmp v0.5.6 // indirect
github.com/gorilla/mux v1.8.0
github.com/grpc-ecosystem/grpc-gateway v1.16.0
github.com/spf13/cast v1.3.1
github.com/spf13/cobra v1.1.3
github.com/stretchr/testify v1.7.0
github.com/tendermint/spm v0.1.6
github.com/tendermint/tendermint v0.34.13
github.com/tendermint/tm-db v0.6.4
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83
google.golang.org/grpc v1.40.0
)

replace (
github.com/99designs/keyring => github.com/cosmos/keyring v1.1.7-0.20210622111912-ef00f8ac3d76
github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.3-alpha.regen.1
google.golang.org/grpc => google.golang.org/grpc v1.33.2
)

app/app.go

import (
//...
// Add the following packages:
"github.com/cosmos/cosmos-sdk/x/feegrant"
feegrantkeeper "github.com/cosmos/cosmos-sdk/x/feegrant/keeper"
feegrantmodule "github.com/cosmos/cosmos-sdk/x/feegrant/module"

"github.com/cosmos/ibc-go/modules/apps/transfer"
ibctransferkeeper "github.com/cosmos/ibc-go/modules/apps/transfer/keeper"
ibctransfertypes "github.com/cosmos/ibc-go/modules/apps/transfer/types"
ibc "github.com/cosmos/ibc-go/modules/core"
ibcclient "github.com/cosmos/ibc-go/modules/core/02-client"
ibcporttypes "github.com/cosmos/ibc-go/modules/core/05-port/types"
ibchost "github.com/cosmos/ibc-go/modules/core/24-host"
ibckeeper "github.com/cosmos/ibc-go/modules/core/keeper"

// Remove the following packages:
// transfer "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer"
// ibctransferkeeper "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/keeper"
// ibctransfertypes "github.com/cosmos/cosmos-sdk/x/ibc/applications/transfer/types"
// ibc "github.com/cosmos/cosmos-sdk/x/ibc/core"
// ibcclient "github.com/cosmos/cosmos-sdk/x/ibc/core/02-client"
// porttypes "github.com/cosmos/cosmos-sdk/x/ibc/core/05-port/types"
// ibchost "github.com/cosmos/cosmos-sdk/x/ibc/core/24-host"
// ibckeeper "github.com/cosmos/cosmos-sdk/x/ibc/core/keeper"
)

var (
//...
ModuleBasics = module.NewBasicManager(
//...
slashing.AppModuleBasic{},
// Add feegrantmodule.AppModuleBasic{},
feegrantmodule.AppModuleBasic{}, // <--
ibc.AppModuleBasic{},
//...
)
//...
)

type App struct {
//...
// Replace codec.Marshaler with codec.Codec
appCodec codec.Codec // <--
// Add FeeGrantKeeper
FeeGrantKeeper feegrantkeeper.Keeper // <--
}

func New(...) {
//bApp.SetAppVersion(version.Version)
bApp.SetVersion(version.Version) // <--

keys := sdk.NewKVStoreKeys(
//...
upgradetypes.StoreKey,
// Add feegrant.StoreKey
feegrant.StoreKey, // <--
evidencetypes.StoreKey,
//...
)

app.FeeGrantKeeper = feegrantkeeper.NewKeeper(appCodec, keys[feegrant.StoreKey], app.AccountKeeper) // <--
// Add app.BaseApp as the last argument to upgradekeeper.NewKeeper
app.UpgradeKeeper = upgradekeeper.NewKeeper(skipUpgradeHeights, keys[upgradetypes.StoreKey], appCodec, homePath, app.BaseApp)

app.IBCKeeper = ibckeeper.NewKeeper(
// Add app.UpgradeKeeper
appCodec, keys[ibchost.StoreKey], app.GetSubspace(ibchost.ModuleName), app.StakingKeeper, app.UpgradeKeeper, scopedIBCKeeper,
)

govRouter.AddRoute(govtypes.RouterKey, govtypes.ProposalHandler).
//...
// Replace NewClientUpdateProposalHandler with NewClientProposalHandler
AddRoute(ibchost.RouterKey, ibcclient.NewClientProposalHandler(app.IBCKeeper.ClientKeeper))

// Replace porttypes with ibcporttypes
ibcRouter := ibcporttypes.NewRouter()

app.mm.SetOrderBeginBlockers(
upgradetypes.ModuleName,
// Add capabilitytypes.ModuleName,
capabilitytypes.ModuleName,
minttypes.ModuleName,
//...
// Add feegrant.ModuleName,
feegrant.ModuleName,
)

// Add app.appCodec as an argument to module.NewConfigurator:
app.mm.RegisterServices(module.NewConfigurator(app.appCodec, app.MsgServiceRouter(), app.GRPCQueryRouter()))

// Replace:
// app.SetAnteHandler(
// ante.NewAnteHandler(
// app.AccountKeeper, app.BankKeeper, ante.DefaultSigVerificationGasConsumer,
// encodingConfig.TxConfig.SignModeHandler(),
// ),
// )

// With the following:
anteHandler, err := ante.NewAnteHandler(
ante.HandlerOptions{
AccountKeeper: app.AccountKeeper,
BankKeeper: app.BankKeeper,
SignModeHandler: encodingConfig.TxConfig.SignModeHandler(),
FeegrantKeeper: app.FeeGrantKeeper,
SigGasConsumer: ante.DefaultSigVerificationGasConsumer,
},
)
if err != nil {
panic(err)
}
app.SetAnteHandler(anteHandler)

// Remove the following:
// ctx := app.BaseApp.NewUncachedContext(true, tmproto.Header{})
// app.CapabilityKeeper.InitializeAndSeal(ctx)
}

func (app *App) InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain {
var genesisState GenesisState
if err := tmjson.Unmarshal(req.AppStateBytes, &genesisState); err != nil {
panic(err)
}
// Add the following:
app.UpgradeKeeper.SetModuleVersionMap(ctx, app.mm.GetVersionMap())
return app.mm.InitGenesis(ctx, app.appCodec, genesisState)
}

// Replace Marshaler with Codec
func (app *App) AppCodec() codec.Codec {
return app.appCodec
}

// Replace BinaryMarshaler with BinaryCodec
func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey sdk.StoreKey) paramskeeper.Keeper {
//...
}

app/genesis.go

// Replace codec.JSONMarshaler with codec.JSONCodec
func NewDefaultGenesisState(cdc codec.JSONCodec) GenesisState {
//...
}

testutil/keeper/mars.go

Add the following code:

package keeper

import (
"testing"

"github.com/username/mars/x/mars/keeper"
"github.com/username/mars/x/mars/types"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmdb "github.com/tendermint/tm-db"
)

func MarsKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
storeKey := sdk.NewKVStoreKey(types.StoreKey)
memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey)

db := tmdb.NewMemDB()
stateStore := store.NewCommitMultiStore(db)
stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil)
require.NoError(t, stateStore.LoadLatestVersion())

registry := codectypes.NewInterfaceRegistry()
k := keeper.NewKeeper(
codec.NewProtoCodec(registry),
storeKey,
memStoreKey,
)

ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, log.NewNopLogger())
return k, ctx
}

If mars is an IBC-enabled module, add the following code, instead:

package keeper

import (
"testing"

"github.com/username/test/x/mars/keeper"
"github.com/username/test/x/mars/types"
"github.com/cosmos/cosmos-sdk/codec"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
"github.com/cosmos/cosmos-sdk/store"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
capabilitykeeper "github.com/cosmos/cosmos-sdk/x/capability/keeper"
typesparams "github.com/cosmos/cosmos-sdk/x/params/types"
ibckeeper "github.com/cosmos/ibc-go/modules/core/keeper"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/libs/log"
tmproto "github.com/tendermint/tendermint/proto/tendermint/types"
tmdb "github.com/tendermint/tm-db"
)

func MarsKeeper(t testing.TB) (*keeper.Keeper, sdk.Context) {
logger := log.NewNopLogger()

storeKey := sdk.NewKVStoreKey(types.StoreKey)
memStoreKey := storetypes.NewMemoryStoreKey(types.MemStoreKey)

db := tmdb.NewMemDB()
stateStore := store.NewCommitMultiStore(db)
stateStore.MountStoreWithDB(storeKey, sdk.StoreTypeIAVL, db)
stateStore.MountStoreWithDB(memStoreKey, sdk.StoreTypeMemory, nil)
require.NoError(t, stateStore.LoadLatestVersion())

registry := codectypes.NewInterfaceRegistry()
appCodec := codec.NewProtoCodec(registry)
capabilityKeeper := capabilitykeeper.NewKeeper(appCodec, storeKey, memStoreKey)

amino := codec.NewLegacyAmino()
ss := typesparams.NewSubspace(appCodec,
amino,
storeKey,
memStoreKey,
"MarsSubSpace",
)
IBCKeeper := ibckeeper.NewKeeper(
appCodec,
storeKey,
ss,
nil,
nil,
capabilityKeeper.ScopeToModule("MarsIBCKeeper"),
)

k := keeper.NewKeeper(
codec.NewProtoCodec(registry),
storeKey,
memStoreKey,
IBCKeeper.ChannelKeeper,
&IBCKeeper.PortKeeper,
capabilityKeeper.ScopeToModule("MarsScopedKeeper"),
)

ctx := sdk.NewContext(stateStore, tmproto.Header{}, false, logger)
return k, ctx
}

testutil/network/network.go

func DefaultConfig() network.Config {
//...
return network.Config{
//...
// Add sdk.DefaultPowerReduction
AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction),
StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction),
BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction),
//...
}
}

testutil/sample/sample.go

Add the following code:

package sample

import (
"github.com/cosmos/cosmos-sdk/crypto/keys/ed25519"
sdk "github.com/cosmos/cosmos-sdk/types"
)

// AccAddress returns a sample account address
func AccAddress() string {
pk := ed25519.GenPrivKey().PubKey()
addr := pk.Address()
return sdk.AccAddress(addr).String()
}

BandChain Support

If your module includes integration with BandChain, added manually or scaffolded with ignite scaffold band, upgrade the github.com/bandprotocol/bandchain-packet package to v0.0.2 in go.mod.

Module

x/mars/keeper/keeper.go

type (
Keeper struct {
// Replace Marshaler with BinaryCodec
cdc codec.BinaryCodec
//...
}
)

func NewKeeper(
// Replace Marshaler with BinaryCodec
cdc codec.BinaryCodec,
//...
) *Keeper {
// ...
}

x/mars/keeper/msg_server_test.go

package keeper_test

import (
//...
// Add the following:
keepertest "github.com/username/mars/testutil/keeper"
"github.com/username/mars/x/mars/keeper"
)

func setupMsgServer(t testing.TB) (types.MsgServer, context.Context) {
// Replace
// keeper, ctx := setupKeeper(t)
// return NewMsgServerImpl(*keeper), sdk.WrapSDKContext(ctx)

// With the following:
k, ctx := keepertest.MarsKeeper(t)
return keeper.NewMsgServerImpl(*k), sdk.WrapSDKContext(ctx)
}

x/mars/module.go

type AppModuleBasic struct {
// Replace Marshaler with BinaryCodec
cdc codec.BinaryCodec
}

// Replace Marshaler with BinaryCodec
func NewAppModuleBasic(cdc codec.BinaryCodec) AppModuleBasic {
return AppModuleBasic{cdc: cdc}
}

// Replace JSONMarshaler with JSONCodec
func (AppModuleBasic) DefaultGenesis(cdc codec.JSONCodec) json.RawMessage {
return cdc.MustMarshalJSON(types.DefaultGenesis())
}

// Replace JSONMarshaler with JSONCodec
func (AppModuleBasic) ValidateGenesis(cdc codec.JSONCodec, config client.TxEncodingConfig, bz json.RawMessage) error {
//...
}

// Replace codec.Marshaller with codec.Codec
func NewAppModule(cdc codec.Codec, keeper keeper.Keeper) AppModule {
//...
}

// Replace JSONMarshaler with JSONCodec
func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.RawMessage) []abci.ValidatorUpdate {
//...
}

// Replace JSONMarshaler with JSONCodec
func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage {
//...
}

// Add the following
func (AppModule) ConsensusVersion() uint64 { return 2 }