Path: blob/main/docs/versioned_docs/version-v0.26/06-migration/v0.25.0.md
1007 views
---
sidebar_position: 994 title: v0.25.0 description: For chains that were scaffolded with Ignite CLI versions lower than v0.25.0. changes are required to use Ignite CLI v0.25.0.
---
Protobuf directory migration
v0.25.0
changes the location of scaffolded .proto
files. Previously, .proto
files were located in ./proto/{moduleName}/
, where moduleName
is the same name of the Cosmos SDK module found in ./x/{moduleName}/
. This new version of ignite
modifies the scaffolded protobuf files so that they are now generated in ./proto/{appName}/{moduleName}
.
The only change that is needed to be made is to create an {appName}
folder in the proto
directory, and then place the sub-directories within it. An example below demonstrates this change:
Previous Directory Structure
This example shows a chain that was generated using ignite
with v0.24.0
using the following command:
ignite s chain github.com/cosmos/planet --no-module ignite s module mars
├── app ├── cmd ├── docs ├── proto │ ├── mars ├── x │ ├── mars ├── README.md ├── config.yml ├── go.mod ├── go.sum └── .gitignore
v0.25.0
Directory Structure
This example shows a chain that was generated using ignite
with v0.25.0
using the following command:
ignite s chain github.com/cosmos/planet --no-module ignite s module mars
├── app ├── cmd ├── docs ├── proto │ ├── planet │ │ ├── mars ├── x │ ├── mars ├── README.md ├── config.yml ├── go.mod ├── go.sum └── .gitignore
The only difference is the additional directory planet
which is the name of the application. The name of the app can be verified by checking the package in the go.mod
file. In this example, the package is github.com/cosmos/planet
where planet
is the app name.
Removing cosmoscmd
v0.25.0
removes the cosmoscmd
package from scaffolded chains. This package provided utility for creating commands and starting up their application. The cosmoscmd
package is now deprecated, and it is suggested that chains implement this functionality in their codebase so they can be more easily upgraded and customized.
The main functionality of cosmoscmd
will be moved to the app
package of your chain. Some imports in these examples contain the sample string, {ModulePath}
. Replace this string with the Go module path of your blockchain. For example, if your blockchain module path is github.com/planet/mars
, {ModulePath}/app/params
would be become github.com/planet/mars/app/params
.
Migration in app
package
To begin, create a new file, ./app/params/encoding.go
, containing the following code:
package params import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" ) // EncodingConfig specifies the concrete encoding types to use for a given app. // This is provided for compatibility between protobuf and amino implementations. type EncodingConfig struct { InterfaceRegistry types.InterfaceRegistry Marshaler codec.Codec TxConfig client.TxConfig Amino *codec.LegacyAmino }
Next, create a new file, ./app/encoding.go
, containing the following code:
package app import ( "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" "github.com/cosmos/cosmos-sdk/std" "github.com/cosmos/cosmos-sdk/x/auth/tx" "{ModulePath}/app/params" ) // makeEncodingConfig creates an EncodingConfig for an amino based test configuration. func makeEncodingConfig() params.EncodingConfig { amino := codec.NewLegacyAmino() interfaceRegistry := types.NewInterfaceRegistry() marshaler := codec.NewProtoCodec(interfaceRegistry) txCfg := tx.NewTxConfig(marshaler, tx.DefaultSignModes) return params.EncodingConfig{ InterfaceRegistry: interfaceRegistry, Marshaler: marshaler, TxConfig: txCfg, Amino: amino, } } // MakeEncodingConfig creates an EncodingConfig for testing func MakeEncodingConfig() params.EncodingConfig { encodingConfig := makeEncodingConfig() std.RegisterLegacyAminoCodec(encodingConfig.Amino) std.RegisterInterfaces(encodingConfig.InterfaceRegistry) ModuleBasics.RegisterLegacyAminoCodec(encodingConfig.Amino) ModuleBasics.RegisterInterfaces(encodingConfig.InterfaceRegistry) return encodingConfig }
Next, modify ./app/simulation_test.go
so that it looks like the following:
package app_test import ( "os" "testing" "time" "github.com/cosmos/cosmos-sdk/simapp" simulationtypes "github.com/cosmos/cosmos-sdk/types/simulation" "github.com/cosmos/cosmos-sdk/x/simulation" "github.com/stretchr/testify/require" abci "github.com/tendermint/tendermint/abci/types" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmtypes "github.com/tendermint/tendermint/types" // remove-next-line "github.com/ignite/cli/ignite/pkg/cosmoscmd" // highlight-next-line "{ModulePath}/app" ) // remove-start type SimApp interface { cosmoscmd.App GetBaseApp() *baseapp.BaseApp AppCodec() codec.Codec SimulationManager() *module.SimulationManager ModuleAccountAddrs() map[string]bool Name() string LegacyAmino() *codec.LegacyAmino BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock EndBlocker(ctx sdk.Context, req abci.RequestEndBlock) abci.ResponseEndBlock InitChainer(ctx sdk.Context, req abci.RequestInitChain) abci.ResponseInitChain } // remove-end // ... // BenchmarkSimulation run the chain simulation // Running using starport command: // `starport chain simulate -v --numBlocks 200 --blockSize 50` // Running as go benchmark test: // `go test -benchmem -run=^$ -bench ^BenchmarkSimulation ./app -NumBlocks=200 -BlockSize 50 -Commit=true -Verbose=true -Enabled=true` func BenchmarkSimulation(b *testing.B) { // ... // remove-next-line encoding := cosmoscmd.MakeEncodingConfig(app.ModuleBasics) // highlight-next-line encoding := app.MakeEncodingConfig() app := app.New( logger, db, nil, true, map[int64]bool{}, app.DefaultNodeHome, 0, encoding, simapp.EmptyAppOptions{}, ) // remove-start simApp, ok := app.(SimApp) require.True(b, ok, "can't use simapp") // remove-end // Run randomized simulations _, simParams, simErr := simulation.SimulateFromSeed( b, os.Stdout, // highlight-next-line app.BaseApp, // highlight-next-line simapp.AppStateFn(app.AppCodec(), app.SimulationManager()), simulationtypes.RandomAccounts, // highlight-next-line simapp.SimulationOperations(app, app.AppCodec(), config), // highlight-next-line app.ModuleAccountAddrs(), config, // highlight-next-line app.AppCodec(), ) // export state and simParams before the simulation error is checked // highlight-next-line err = simapp.CheckExportSimulation(app, config, simParams) require.NoError(b, err) require.NoError(b, simErr) // ... }
The main changes here are that the SimApp
interface has been removed and is being replaced with app
.
The final modification in the app
package is in app/app.go
:
package app import ( // ... // this line is used by starport scaffolding # stargate/app/moduleImport // remove-next-line "github.com/ignite/cli/ignite/pkg/cosmoscmd" // highlight-start appparams "{ModulePath}/app/params" "{ModulePath}/docs" // highlight-end ) // ... var ( // remove-next-line _ cosmoscmd.App = (*App)(nil) _ servertypes.Application = (*App)(nil) _ simapp.App = (*App)(nil) ) // ... // New returns a reference to an initialized blockchain app func New( logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, skipUpgradeHeights map[int64]bool, homePath string, invCheckPeriod uint, // highlight-next-line encodingConfig appparams.EncodingConfig, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), // highlight-next-line ) *App { appCodec := encodingConfig.Marshaler cdc := encodingConfig.Amino interfaceRegistry := encodingConfig.InterfaceRegistry bApp := baseapp.NewBaseApp( Name, logger, db, encodingConfig.TxConfig.TxDecoder(), baseAppOptions..., ) // ... } // ... // Name returns the name of the App func (app *App) Name() string { return app.BaseApp.Name() } // remove-start // GetBaseApp returns the base app of the application func (app App) GetBaseApp() *baseapp.BaseApp { return app.BaseApp } // remove-end // BeginBlocker application updates every begin block func (app *App) BeginBlocker(ctx sdk.Context, req abci.RequestBeginBlock) abci.ResponseBeginBlock { return app.mm.BeginBlock(ctx, req) } // ...
Again, here we are removing the use of cosmoscmd
and replacing it with app
.
Migration in cmd
package
Some imports in these examples contain the sample string, {binaryNamePrefix}d
. Replace this string with the binary name of your blockchain. For example, if your blockchain module path is github.com/planet/mars
, ./cmd/{binaryNamePrefix}d/cmd/
would be become ./cmd/marsd/cmd/
.
First, create the new file ./cmd/{binaryNamePrefix}d/cmd/config.go
with the following code:
package cmd import ( sdk "github.com/cosmos/cosmos-sdk/types" "{ModulePath}/app" ) func initSDKConfig() { // Set prefixes accountPubKeyPrefix := app.AccountAddressPrefix + "pub" validatorAddressPrefix := app.AccountAddressPrefix + "valoper" validatorPubKeyPrefix := app.AccountAddressPrefix + "valoperpub" consNodeAddressPrefix := app.AccountAddressPrefix + "valcons" consNodePubKeyPrefix := app.AccountAddressPrefix + "valconspub" // Set and seal config config := sdk.GetConfig() config.SetBech32PrefixForAccount(app.AccountAddressPrefix, accountPubKeyPrefix) config.SetBech32PrefixForValidator(validatorAddressPrefix, validatorPubKeyPrefix) config.SetBech32PrefixForConsensusNode(consNodeAddressPrefix, consNodePubKeyPrefix) config.Seal() }
Next, create the new file ./cmd/{binaryNamePrefix}d/cmd/genaccounts.go
with the following code:
package cmd import ( "bufio" "encoding/json" "errors" "fmt" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/crypto/keyring" "github.com/cosmos/cosmos-sdk/server" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/genutil" genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/spf13/cobra" ) const ( flagVestingStart = "vesting-start-time" flagVestingEnd = "vesting-end-time" flagVestingAmt = "vesting-amount" ) // AddGenesisAccountCmd returns add-genesis-account cobra Command. func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command { cmd := &cobra.Command{ Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]", Short: "Add a genesis account to genesis.json", Long: `Add a genesis account to genesis.json. The provided account must specify the account address or key name and a list of initial coins. If a key name is given, the address will be looked up in the local Keybase. The list of initial tokens must contain valid denominations. Accounts may optionally be supplied with vesting parameters. `, Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { clientCtx := client.GetClientContextFromCmd(cmd) cdc := clientCtx.Codec serverCtx := server.GetServerContextFromCmd(cmd) config := serverCtx.Config config.SetRoot(clientCtx.HomeDir) coins, err := sdk.ParseCoinsNormalized(args[1]) if err != nil { return fmt.Errorf("failed to parse coins: %w", err) } addr, err := sdk.AccAddressFromBech32(args[0]) if err != nil { inBuf := bufio.NewReader(cmd.InOrStdin()) keyringBackend, err := cmd.Flags().GetString(flags.FlagKeyringBackend) if err != nil { return err } // attempt to lookup address from Keybase if no address was provided kb, err := keyring.New(sdk.KeyringServiceName(), keyringBackend, clientCtx.HomeDir, inBuf, cdc) if err != nil { return err } info, err := kb.Key(args[0]) if err != nil { return fmt.Errorf("failed to get address from Keybase: %w", err) } addr, err = info.GetAddress() if err != nil { return fmt.Errorf("failed to get address from Keybase: %w", err) } } vestingStart, err := cmd.Flags().GetInt64(flagVestingStart) if err != nil { return err } vestingEnd, err := cmd.Flags().GetInt64(flagVestingEnd) if err != nil { return err } vestingAmtStr, err := cmd.Flags().GetString(flagVestingAmt) if err != nil { return err } vestingAmt, err := sdk.ParseCoinsNormalized(vestingAmtStr) if err != nil { return fmt.Errorf("failed to parse vesting amount: %w", err) } // create concrete account type based on input parameters var genAccount authtypes.GenesisAccount balances := banktypes.Balance{Address: addr.String(), Coins: coins.Sort()} baseAccount := authtypes.NewBaseAccount(addr, nil, 0, 0) if !vestingAmt.IsZero() { baseVestingAccount := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd) if (balances.Coins.IsZero() && !baseVestingAccount.OriginalVesting.IsZero()) || baseVestingAccount.OriginalVesting.IsAnyGT(balances.Coins) { return errors.New("vesting amount cannot be greater than total amount") } switch { case vestingStart != 0 && vestingEnd != 0: genAccount = authvesting.NewContinuousVestingAccountRaw(baseVestingAccount, vestingStart) case vestingEnd != 0: genAccount = authvesting.NewDelayedVestingAccountRaw(baseVestingAccount) default: return errors.New("invalid vesting parameters; must supply start and end time or end time") } } else { genAccount = baseAccount } if err := genAccount.Validate(); err != nil { return fmt.Errorf("failed to validate new genesis account: %w", err) } genFile := config.GenesisFile() appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) if err != nil { return fmt.Errorf("failed to unmarshal genesis state: %w", err) } authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState) accs, err := authtypes.UnpackAccounts(authGenState.Accounts) if err != nil { return fmt.Errorf("failed to get accounts from any: %w", err) } if accs.Contains(addr) { return fmt.Errorf("cannot add account at existing address %s", addr) } // Add the new account to the set of genesis accounts and sanitize the // accounts afterwards. accs = append(accs, genAccount) accs = authtypes.SanitizeGenesisAccounts(accs) genAccs, err := authtypes.PackAccounts(accs) if err != nil { return fmt.Errorf("failed to convert accounts into any's: %w", err) } authGenState.Accounts = genAccs authGenStateBz, err := cdc.MarshalJSON(&authGenState) if err != nil { return fmt.Errorf("failed to marshal auth genesis state: %w", err) } appState[authtypes.ModuleName] = authGenStateBz bankGenState := banktypes.GetGenesisStateFromAppState(cdc, appState) bankGenState.Balances = append(bankGenState.Balances, balances) bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) bankGenStateBz, err := cdc.MarshalJSON(bankGenState) if err != nil { return fmt.Errorf("failed to marshal bank genesis state: %w", err) } appState[banktypes.ModuleName] = bankGenStateBz appStateJSON, err := json.Marshal(appState) if err != nil { return fmt.Errorf("failed to marshal application genesis state: %w", err) } genDoc.AppState = appStateJSON return genutil.ExportGenesisFile(genDoc, genFile) }, } cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)") cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory") cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts") cmd.Flags().Int64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts") cmd.Flags().Int64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts") flags.AddQueryFlagsToCmd(cmd) return cmd }
This command allows one to generate new accounts: appd add-genesis-account
.
Next, create the new file ./cmd/{binaryNamePrefix}d/cmd/root.go
with the following code:
package cmd import ( "errors" "io" "os" "path/filepath" "strings" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/config" "github.com/cosmos/cosmos-sdk/client/debug" "github.com/cosmos/cosmos-sdk/client/flags" "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/server" serverconfig "github.com/cosmos/cosmos-sdk/server/config" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/snapshots" snapshottypes "github.com/cosmos/cosmos-sdk/snapshots/types" "github.com/cosmos/cosmos-sdk/store" sdk "github.com/cosmos/cosmos-sdk/types" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" "github.com/cosmos/cosmos-sdk/x/auth/types" banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/crisis" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" "github.com/ignite/cli/ignite/services/network" "github.com/spf13/cast" "github.com/spf13/cobra" "github.com/spf13/pflag" tmcfg "github.com/tendermint/tendermint/config" tmcli "github.com/tendermint/tendermint/libs/cli" "github.com/tendermint/tendermint/libs/log" dbm "github.com/tendermint/tm-db" // this line is used by starport scaffolding # root/moduleImport "{ModulePath}/app" appparams "{ModulePath}/app/params" ) // NewRootCmd creates a new root command for a Cosmos SDK application func NewRootCmd() (*cobra.Command, appparams.EncodingConfig) { encodingConfig := app.MakeEncodingConfig() initClientCtx := client.Context{}. WithCodec(encodingConfig.Marshaler). WithInterfaceRegistry(encodingConfig.InterfaceRegistry). WithTxConfig(encodingConfig.TxConfig). WithLegacyAmino(encodingConfig.Amino). WithInput(os.Stdin). WithAccountRetriever(types.AccountRetriever{}). WithHomeDir(app.DefaultNodeHome). WithViper("") rootCmd := &cobra.Command{ Use: app.Name + "d", Short: "Stargate CosmosHub App", PersistentPreRunE: func(cmd *cobra.Command, _ []string) error { // set the default command outputs cmd.SetOut(cmd.OutOrStdout()) cmd.SetErr(cmd.ErrOrStderr()) initClientCtx, err := client.ReadPersistentCommandFlags(initClientCtx, cmd.Flags()) if err != nil { return err } initClientCtx, err = config.ReadFromClientConfig(initClientCtx) if err != nil { return err } if err := client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil { return err } customAppTemplate, customAppConfig := initAppConfig() customTMConfig := initTendermintConfig() return server.InterceptConfigsPreRunHandler( cmd, customAppTemplate, customAppConfig, customTMConfig, ) }, } initRootCmd(rootCmd, encodingConfig) overwriteFlagDefaults(rootCmd, map[string]string{ flags.FlagChainID: strings.ReplaceAll(app.Name, "-", ""), flags.FlagKeyringBackend: "test", }) return rootCmd, encodingConfig } // initTendermintConfig helps to override default Tendermint Config values. // return tmcfg.DefaultConfig if no custom configuration is required for the application. func initTendermintConfig() *tmcfg.Config { cfg := tmcfg.DefaultConfig() return cfg } func initRootCmd( rootCmd *cobra.Command, encodingConfig appparams.EncodingConfig, ) { // Set config initSDKConfig() rootCmd.AddCommand( genutilcli.InitCmd(app.ModuleBasics, app.DefaultNodeHome), genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome), genutilcli.MigrateGenesisCmd(), genutilcli.GenTxCmd( app.ModuleBasics, encodingConfig.TxConfig, banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome, ), genutilcli.ValidateGenesisCmd(app.ModuleBasics), AddGenesisAccountCmd(app.DefaultNodeHome), tmcli.NewCompletionCmd(rootCmd, true), debug.Cmd(), config.Cmd(), // this line is used by starport scaffolding # root/commands ) a := appCreator{ encodingConfig, } // add server commands server.AddCommands( rootCmd, app.DefaultNodeHome, a.newApp, a.appExport, addModuleInitFlags, ) // add keybase, auxiliary RPC, query, and tx child commands rootCmd.AddCommand( rpc.StatusCommand(), queryCommand(), txCommand(), keys.Commands(app.DefaultNodeHome), ) } // queryCommand returns the sub-command to send queries to the app func queryCommand() *cobra.Command { cmd := &cobra.Command{ Use: "query", Aliases: []string{"q"}, Short: "Querying subcommands", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } cmd.AddCommand( authcmd.GetAccountCmd(), rpc.ValidatorCommand(), rpc.BlockCommand(), authcmd.QueryTxsByEventsCmd(), authcmd.QueryTxCmd(), ) app.ModuleBasics.AddQueryCommands(cmd) cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") return cmd } // txCommand returns the sub-command to send transactions to the app func txCommand() *cobra.Command { cmd := &cobra.Command{ Use: "tx", Short: "Transactions subcommands", DisableFlagParsing: true, SuggestionsMinimumDistance: 2, RunE: client.ValidateCmd, } cmd.AddCommand( authcmd.GetSignCommand(), authcmd.GetSignBatchCommand(), authcmd.GetMultiSignCommand(), authcmd.GetValidateSignaturesCommand(), flags.LineBreak, authcmd.GetBroadcastCommand(), authcmd.GetEncodeCommand(), authcmd.GetDecodeCommand(), ) app.ModuleBasics.AddTxCommands(cmd) cmd.PersistentFlags().String(flags.FlagChainID, "", "The network chain ID") return cmd } func addModuleInitFlags(startCmd *cobra.Command) { crisis.AddModuleInitFlags(startCmd) // this line is used by starport scaffolding # root/arguments } func overwriteFlagDefaults(c *cobra.Command, defaults map[string]string) { set := func(s *pflag.FlagSet, key, val string) { if f := s.Lookup(key); f != nil { f.DefValue = val f.Value.Set(val) } } for key, val := range defaults { set(c.Flags(), key, val) set(c.PersistentFlags(), key, val) } for _, c := range c.Commands() { overwriteFlagDefaults(c, defaults) } } type appCreator struct { encodingConfig appparams.EncodingConfig } // newApp creates a new Cosmos SDK app func (a appCreator) newApp( logger log.Logger, db dbm.DB, traceStore io.Writer, appOpts servertypes.AppOptions, ) servertypes.Application { var cache sdk.MultiStorePersistentCache if cast.ToBool(appOpts.Get(server.FlagInterBlockCache)) { cache = store.NewCommitKVStoreCacheManager() } skipUpgradeHeights := make(map[int64]bool) for _, h := range cast.ToIntSlice(appOpts.Get(server.FlagUnsafeSkipUpgrades)) { skipUpgradeHeights[int64(h)] = true } pruningOpts, err := server.GetPruningOptionsFromFlags(appOpts) if err != nil { panic(err) } snapshotDir := filepath.Join(cast.ToString(appOpts.Get(flags.FlagHome)), "data", "snapshots") snapshotDB, err := dbm.NewDB("metadata", dbm.GoLevelDBBackend, snapshotDir) if err != nil { panic(err) } snapshotStore, err := snapshots.NewStore(snapshotDB, snapshotDir) if err != nil { panic(err) } snapshotOptions := snapshottypes.NewSnapshotOptions( cast.ToUint64(appOpts.Get(server.FlagStateSyncSnapshotInterval)), cast.ToUint32(appOpts.Get(server.FlagStateSyncSnapshotKeepRecent)), ) return app.New( logger, db, traceStore, true, skipUpgradeHeights, cast.ToString(appOpts.Get(flags.FlagHome)), cast.ToUint(appOpts.Get(server.FlagInvCheckPeriod)), a.encodingConfig, appOpts, baseapp.SetPruning(pruningOpts), baseapp.SetMinGasPrices(cast.ToString(appOpts.Get(server.FlagMinGasPrices))), baseapp.SetMinRetainBlocks(cast.ToUint64(appOpts.Get(server.FlagMinRetainBlocks))), baseapp.SetHaltHeight(cast.ToUint64(appOpts.Get(server.FlagHaltHeight))), baseapp.SetHaltTime(cast.ToUint64(appOpts.Get(server.FlagHaltTime))), baseapp.SetInterBlockCache(cache), baseapp.SetTrace(cast.ToBool(appOpts.Get(server.FlagTrace))), baseapp.SetIndexEvents(cast.ToStringSlice(appOpts.Get(server.FlagIndexEvents))), baseapp.SetSnapshot(snapshotStore, snapshotOptions), ) } // appExport creates a new simapp (optionally at a given height) func (a appCreator) appExport( logger log.Logger, db dbm.DB, traceStore io.Writer, height int64, forZeroHeight bool, jailAllowedAddrs []string, appOpts servertypes.AppOptions, ) (servertypes.ExportedApp, error) { homePath, ok := appOpts.Get(flags.FlagHome).(string) if !ok || homePath == "" { return servertypes.ExportedApp{}, errors.New("application home not set") } app := app.New( logger, db, traceStore, height == -1, // -1: no height provided map[int64]bool{}, homePath, uint(1), a.encodingConfig, appOpts, ) if height != -1 { if err := app.LoadHeight(height); err != nil { return servertypes.ExportedApp{}, err } } return app.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs) } // initAppConfig helps to override default appConfig template and configs. // return "", nil if no custom configuration is required for the application. func initAppConfig() (string, interface{}) { // The following code snippet is just for reference. // WASMConfig defines configuration for the wasm module. type WASMConfig struct { // This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries QueryGasLimit uint64 `mapstructure:"query_gas_limit"` // Address defines the gRPC-web server to listen on LruSize uint64 `mapstructure:"lru_size"` } type CustomAppConfig struct { serverconfig.Config WASM WASMConfig `mapstructure:"wasm"` } // Optionally allow the chain developer to overwrite the SDK's default // server config. srvCfg := serverconfig.DefaultConfig() // The SDK's default minimum gas price is set to "" (empty value) inside // app.toml. If left empty by validators, the node will halt on startup. // However, the chain developer can set a default app.toml value for their // validators here. // // In summary: // - if you leave srvCfg.MinGasPrices = "", all validators MUST tweak their // own app.toml config, // - if you set srvCfg.MinGasPrices non-empty, validators CAN tweak their // own app.toml to override, or use this default value. // // In simapp, we set the min gas prices to 0. srvCfg.MinGasPrices = "0stake" customAppConfig := CustomAppConfig{ Config: *srvCfg, WASM: WASMConfig{ LruSize: 1, QueryGasLimit: 300000, }, } customAppTemplate := serverconfig.DefaultConfigTemplate + ` [wasm] # This is the maximum sdk gas (wasm and storage) that we allow for any x/wasm "smart" queries query_gas_limit = 300000 # This is the number of wasm vm instances we keep cached in memory for speed-up # Warning: this is currently unstable and may lead to crashes, best to keep for 0 unless testing locally lru_size = 0` return customAppTemplate, customAppConfig }
Finally, modify ./cmd/{binaryNamePrefix}d/main.go
to include the new changes:
package main import ( "os" "github.com/cosmos/cosmos-sdk/server" svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" // remove-next-line "github.com/ignite/cli/ignite/pkg/cosmoscmd" "{ModulePath}/app" "{ModulePath}/cmd/{BinaryNamePrefix}d/cmd" ) func main() { // highlight-start rootCmd, _ := cmd.NewRootCmd() if err := svrcmd.Execute(rootCmd, "", app.DefaultNodeHome); err != nil { switch e := err.(type) { case server.ErrorCode: os.Exit(e.Code) default: os.Exit(1) } } // highlight-end }
Migration in testutil
package
Modify ./testutil/network/network.go
to include the new changes:
package network import ( "fmt" "testing" "time" "github.com/cosmos/cosmos-sdk/baseapp" "github.com/cosmos/cosmos-sdk/crypto/hd" "github.com/cosmos/cosmos-sdk/crypto/keyring" pruningtypes "github.com/cosmos/cosmos-sdk/pruning/types" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/simapp" "github.com/cosmos/cosmos-sdk/testutil/network" sdk "github.com/cosmos/cosmos-sdk/types" authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" "github.com/stretchr/testify/require" tmrand "github.com/tendermint/tendermint/libs/rand" tmdb "github.com/tendermint/tm-db" // highlight-next-line "{ModulePath}/app" // remove-next-line "github.com/ignite/cli/ignite/pkg/cosmoscmd" ) // ... // DefaultConfig will initialize config for the network with custom application, // genesis and single validator. All other parameters are inherited from cosmos-sdk/testutil/network.DefaultConfig func DefaultConfig() network.Config { // highlight-next-line encoding := app.MakeEncodingConfig() // remove-next-line encoding := cosmoscmd.MakeEncodingConfig(app.ModuleBasics) return network.Config{ Codec: encoding.Marshaler, TxConfig: encoding.TxConfig, LegacyAmino: encoding.Amino, InterfaceRegistry: encoding.InterfaceRegistry, AccountRetriever: authtypes.AccountRetriever{}, AppConstructor: func(val network.Validator) servertypes.Application { return app.New( val.Ctx.Logger, tmdb.NewMemDB(), nil, true, map[int64]bool{}, val.Ctx.Config.RootDir, 0, encoding, simapp.EmptyAppOptions{}, baseapp.SetPruning(pruningtypes.NewPruningOptionsFromString(val.AppConfig.Pruning)), baseapp.SetMinGasPrices(val.AppConfig.MinGasPrices), ) }, GenesisState: app.ModuleBasics.DefaultGenesis(encoding.Marshaler), TimeoutCommit: 2 * time.Second, ChainID: "chain-" + tmrand.NewRand().Str(6), NumValidators: 1, BondDenom: sdk.DefaultBondDenom, MinGasPrices: fmt.Sprintf("0.000006%s", sdk.DefaultBondDenom), AccountTokens: sdk.TokensFromConsensusPower(1000, sdk.DefaultPowerReduction), StakingTokens: sdk.TokensFromConsensusPower(500, sdk.DefaultPowerReduction), BondedTokens: sdk.TokensFromConsensusPower(100, sdk.DefaultPowerReduction), PruningStrategy: pruningtypes.PruningOptionNothing, CleanupDir: true, SigningAlgo: string(hd.Secp256k1Type), KeyringOptions: []keyring.Option{}, } }
Fix ICA controller keeper wiring
Related issue: https://github.com/ignite/cli/issues/2867
Apply the following changes to app/app.go
file :
package app import ( // highlight-start icacontrollerkeeper "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/keeper" icacontrollertypes "github.com/cosmos/ibc-go/v5/modules/apps/27-interchain-accounts/controller/types" // highlight-end // ... ) // New returns a reference to an initialized blockchain app func New( logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, skipUpgradeHeights map[int64]bool, homePath string, invCheckPeriod uint, encodingConfig appparams.EncodingConfig, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), ) *App { // ... keys := sdk.NewKVStoreKeys( authtypes.StoreKey, authz.ModuleName, banktypes.StoreKey, stakingtypes.StoreKey, minttypes.StoreKey, distrtypes.StoreKey, slashingtypes.StoreKey, govtypes.StoreKey, paramstypes.StoreKey, ibchost.StoreKey, upgradetypes.StoreKey, feegrant.StoreKey, evidencetypes.StoreKey, ibctransfertypes.StoreKey, icahosttypes.StoreKey, capabilitytypes.StoreKey, group.StoreKey, // highlight-next-line icacontrollertypes.StoreKey, yourchainmoduletypes.StoreKey, // this line is used by starport scaffolding # stargate/app/storeKey ) // ... // remove-next-line icaModule := ica.NewAppModule(nil, &app.ICAHostKeeper) // highlight-start icaControllerKeeper := icacontrollerkeeper.NewKeeper( appCodec, keys[icacontrollertypes.StoreKey], app.GetSubspace(icacontrollertypes.SubModuleName), app.IBCKeeper.ChannelKeeper, // may be replaced with middleware such as ics29 fee app.IBCKeeper.ChannelKeeper, &app.IBCKeeper.PortKeeper, scopedICAControllerKeeper, app.MsgServiceRouter(), ) icaModule := ica.NewAppModule(&icaControllerKeeper, &app.ICAHostKeeper) // highlight-end icaHostIBCModule := icahost.NewIBCModule(app.ICAHostKeeper) // ... } // ... // initParamsKeeper init params keeper and its subspaces func initParamsKeeper(appCodec codec.BinaryCodec, legacyAmino *codec.LegacyAmino, key, tkey storetypes.StoreKey) paramskeeper.Keeper { paramsKeeper := paramskeeper.NewKeeper(appCodec, legacyAmino, key, tkey) paramsKeeper.Subspace(authtypes.ModuleName) paramsKeeper.Subspace(banktypes.ModuleName) paramsKeeper.Subspace(stakingtypes.ModuleName) paramsKeeper.Subspace(minttypes.ModuleName) paramsKeeper.Subspace(distrtypes.ModuleName) paramsKeeper.Subspace(slashingtypes.ModuleName) paramsKeeper.Subspace(govtypes.ModuleName).WithKeyTable(govv1.ParamKeyTable()) paramsKeeper.Subspace(crisistypes.ModuleName) paramsKeeper.Subspace(ibctransfertypes.ModuleName) paramsKeeper.Subspace(ibchost.ModuleName) // highlight-next-line paramsKeeper.Subspace(icacontrollertypes.SubModuleName) paramsKeeper.Subspace(icahosttypes.SubModuleName) paramsKeeper.Subspace(mychainmoduletypes.ModuleName) // this line is used by starport scaffolding # stargate/app/paramSubspace return paramsKeeper }
Fix capability keeper not sealed
Related issue: https://github.com/ignite/cli/issues/1921
Apply the following change to app/app.go
file :
package app // New returns a reference to an initialized blockchain app func New( logger log.Logger, db dbm.DB, traceStore io.Writer, loadLatest bool, skipUpgradeHeights map[int64]bool, homePath string, invCheckPeriod uint, encodingConfig appparams.EncodingConfig, appOpts servertypes.AppOptions, baseAppOptions ...func(*baseapp.BaseApp), ) *App { // ... // this line is used by starport scaffolding # stargate/app/keeperDefinition // highlight-start // Sealing prevents other modules from creating scoped sub-keepers app.CapabilityKeeper.Seal() // highlight-end // Create static IBC router, add transfer route, then set and seal it // ... }