## Description removes the dependency of tendermint/utils/log from countless locations. This is in effort of reducing Tendermint's lib usage in the sdk this is nonbreaking as the interface is the same. To eliminate tm/utils/log in the sdk we need a few more things. Once we have fully removed the tendermint logger, I would propose we break the interface and define our own for our use case, when we pass the logger to tendermint in the node.New() function we can wrap our logger for its use case --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [ ] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [ ] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#pr-targeting)) - [ ] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/main/docs/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/main/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [ ] reviewed "Files changed" and left comments if necessary - [ ] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
341 lines
10 KiB
Go
341 lines
10 KiB
Go
package cmd
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
|
|
cmtcfg "github.com/cometbft/cometbft/config"
|
|
dbm "github.com/cosmos/cosmos-db"
|
|
"github.com/cosmos/cosmos-sdk/log"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
|
|
"cosmossdk.io/simapp"
|
|
"cosmossdk.io/simapp/params"
|
|
confixcmd "cosmossdk.io/tools/confix/cmd"
|
|
rosettaCmd "cosmossdk.io/tools/rosetta/cmd"
|
|
|
|
"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/pruning"
|
|
"github.com/cosmos/cosmos-sdk/client/rpc"
|
|
"github.com/cosmos/cosmos-sdk/codec"
|
|
"github.com/cosmos/cosmos-sdk/server"
|
|
serverconfig "github.com/cosmos/cosmos-sdk/server/config"
|
|
servertypes "github.com/cosmos/cosmos-sdk/server/types"
|
|
simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims"
|
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
|
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
|
"github.com/cosmos/cosmos-sdk/x/auth/tx"
|
|
txmodule "github.com/cosmos/cosmos-sdk/x/auth/tx/config"
|
|
"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"
|
|
)
|
|
|
|
// NewRootCmd creates a new root command for simd. It is called once in the
|
|
// main function.
|
|
func NewRootCmd() *cobra.Command {
|
|
// we "pre"-instantiate the application for getting the injected/configured encoding configuration
|
|
// note, this is not necessary when using app wiring, as depinject can be directly used.
|
|
// for consistency between app-v1 and app-v2, we do it the same way via methods on simapp
|
|
tempApp := simapp.NewSimApp(log.NewNopLogger(), dbm.NewMemDB(), nil, true, simtestutil.NewAppOptionsWithFlagHome(tempDir()))
|
|
encodingConfig := params.EncodingConfig{
|
|
InterfaceRegistry: tempApp.InterfaceRegistry(),
|
|
Codec: tempApp.AppCodec(),
|
|
TxConfig: tempApp.TxConfig(),
|
|
Amino: tempApp.LegacyAmino(),
|
|
}
|
|
|
|
initClientCtx := client.Context{}.
|
|
WithCodec(encodingConfig.Codec).
|
|
WithInterfaceRegistry(encodingConfig.InterfaceRegistry).
|
|
WithLegacyAmino(encodingConfig.Amino).
|
|
WithInput(os.Stdin).
|
|
WithAccountRetriever(types.AccountRetriever{}).
|
|
WithHomeDir(simapp.DefaultNodeHome).
|
|
WithViper("") // In simapp, we don't use any prefix for env variables.
|
|
|
|
rootCmd := &cobra.Command{
|
|
Use: "simd",
|
|
Short: "simulation 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
|
|
}
|
|
|
|
// This needs to go after ReadFromClientConfig, as that function
|
|
// sets the RPC client needed for SIGN_MODE_TEXTUAL.
|
|
//
|
|
// TODO Currently, the TxConfig below doesn't include Textual, so
|
|
// an error will arise when using the --textual flag.
|
|
// ref: https://github.com/cosmos/cosmos-sdk/issues/11970
|
|
txConfigWithTextual := tx.NewTxConfigWithTextual(
|
|
codec.NewProtoCodec(encodingConfig.InterfaceRegistry),
|
|
encodingConfig.TxConfig.SignModeHandler().Modes(),
|
|
txmodule.NewTextualWithGRPCConn(initClientCtx),
|
|
)
|
|
initClientCtx = initClientCtx.WithTxConfig(txConfigWithTextual)
|
|
|
|
if err := client.SetCmdClientContextHandler(initClientCtx, cmd); err != nil {
|
|
return err
|
|
}
|
|
|
|
customAppTemplate, customAppConfig := initAppConfig()
|
|
customCMTConfig := initTendermintConfig()
|
|
|
|
return server.InterceptConfigsPreRunHandler(cmd, customAppTemplate, customAppConfig, customCMTConfig)
|
|
},
|
|
}
|
|
|
|
initRootCmd(rootCmd, encodingConfig)
|
|
|
|
if err := tempApp.AutoCliOpts().EnhanceRootCommand(rootCmd); err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
return rootCmd
|
|
}
|
|
|
|
// initTendermintConfig helps to override default Tendermint Config values.
|
|
// return cmtcfg.DefaultConfig if no custom configuration is required for the application.
|
|
func initTendermintConfig() *cmtcfg.Config {
|
|
cfg := cmtcfg.DefaultConfig()
|
|
|
|
// these values put a higher strain on node memory
|
|
// cfg.P2P.MaxNumInboundPeers = 100
|
|
// cfg.P2P.MaxNumOutboundPeers = 40
|
|
|
|
return cfg
|
|
}
|
|
|
|
// 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"
|
|
// srvCfg.BaseConfig.IAVLDisableFastNode = true // disable fastnode by default
|
|
|
|
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
|
|
}
|
|
|
|
func initRootCmd(rootCmd *cobra.Command, encodingConfig params.EncodingConfig) {
|
|
cfg := sdk.GetConfig()
|
|
cfg.Seal()
|
|
|
|
rootCmd.AddCommand(
|
|
genutilcli.InitCmd(simapp.ModuleBasics, simapp.DefaultNodeHome),
|
|
NewTestnetCmd(simapp.ModuleBasics, banktypes.GenesisBalancesIterator{}),
|
|
debug.Cmd(),
|
|
confixcmd.ConfigCommand(),
|
|
pruning.Cmd(newApp),
|
|
)
|
|
|
|
server.AddCommands(rootCmd, simapp.DefaultNodeHome, newApp, appExport, addModuleInitFlags)
|
|
|
|
// add keybase, auxiliary RPC, query, genesis, and tx child commands
|
|
rootCmd.AddCommand(
|
|
rpc.StatusCommand(),
|
|
genesisCommand(encodingConfig),
|
|
queryCommand(),
|
|
txCommand(),
|
|
keys.Commands(simapp.DefaultNodeHome),
|
|
)
|
|
|
|
// add rosetta
|
|
rootCmd.AddCommand(rosettaCmd.RosettaCommand(encodingConfig.InterfaceRegistry, encodingConfig.Codec))
|
|
}
|
|
|
|
func addModuleInitFlags(startCmd *cobra.Command) {
|
|
crisis.AddModuleInitFlags(startCmd)
|
|
}
|
|
|
|
// genesisCommand builds genesis-related `simd genesis` command. Users may provide application specific commands as a parameter
|
|
func genesisCommand(encodingConfig params.EncodingConfig, cmds ...*cobra.Command) *cobra.Command {
|
|
cmd := genutilcli.GenesisCoreCommand(encodingConfig.TxConfig, simapp.ModuleBasics, simapp.DefaultNodeHome)
|
|
|
|
for _, sub_cmd := range cmds {
|
|
cmd.AddCommand(sub_cmd)
|
|
}
|
|
return cmd
|
|
}
|
|
|
|
func queryCommand() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "query",
|
|
Aliases: []string{"q"},
|
|
Short: "Querying subcommands",
|
|
DisableFlagParsing: false,
|
|
SuggestionsMinimumDistance: 2,
|
|
RunE: client.ValidateCmd,
|
|
}
|
|
|
|
cmd.AddCommand(
|
|
authcmd.GetAccountCmd(),
|
|
rpc.ValidatorCommand(),
|
|
rpc.BlockCommand(),
|
|
authcmd.QueryTxsByEventsCmd(),
|
|
authcmd.QueryTxCmd(),
|
|
)
|
|
|
|
simapp.ModuleBasics.AddQueryCommands(cmd)
|
|
|
|
return cmd
|
|
}
|
|
|
|
func txCommand() *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "tx",
|
|
Short: "Transactions subcommands",
|
|
DisableFlagParsing: false,
|
|
SuggestionsMinimumDistance: 2,
|
|
RunE: client.ValidateCmd,
|
|
}
|
|
|
|
cmd.AddCommand(
|
|
authcmd.GetSignCommand(),
|
|
authcmd.GetSignBatchCommand(),
|
|
authcmd.GetMultiSignCommand(),
|
|
authcmd.GetMultiSignBatchCmd(),
|
|
authcmd.GetValidateSignaturesCommand(),
|
|
authcmd.GetBroadcastCommand(),
|
|
authcmd.GetEncodeCommand(),
|
|
authcmd.GetDecodeCommand(),
|
|
authcmd.GetAuxToFeeCommand(),
|
|
)
|
|
|
|
simapp.ModuleBasics.AddTxCommands(cmd)
|
|
|
|
return cmd
|
|
}
|
|
|
|
// newApp creates the application
|
|
func newApp(
|
|
logger log.Logger,
|
|
db dbm.DB,
|
|
traceStore io.Writer,
|
|
appOpts servertypes.AppOptions,
|
|
) servertypes.Application {
|
|
baseappOptions := server.DefaultBaseappOptions(appOpts)
|
|
|
|
return simapp.NewSimApp(
|
|
logger, db, traceStore, true,
|
|
appOpts,
|
|
baseappOptions...,
|
|
)
|
|
}
|
|
|
|
// appExport creates a new simapp (optionally at a given height) and exports state.
|
|
func appExport(
|
|
logger log.Logger,
|
|
db dbm.DB,
|
|
traceStore io.Writer,
|
|
height int64,
|
|
forZeroHeight bool,
|
|
jailAllowedAddrs []string,
|
|
appOpts servertypes.AppOptions,
|
|
modulesToExport []string,
|
|
) (servertypes.ExportedApp, error) {
|
|
var simApp *simapp.SimApp
|
|
|
|
// this check is necessary as we use the flag in x/upgrade.
|
|
// we can exit more gracefully by checking the flag here.
|
|
homePath, ok := appOpts.Get(flags.FlagHome).(string)
|
|
if !ok || homePath == "" {
|
|
return servertypes.ExportedApp{}, errors.New("application home not set")
|
|
}
|
|
|
|
viperAppOpts, ok := appOpts.(*viper.Viper)
|
|
if !ok {
|
|
return servertypes.ExportedApp{}, errors.New("appOpts is not viper.Viper")
|
|
}
|
|
|
|
// overwrite the FlagInvCheckPeriod
|
|
viperAppOpts.Set(server.FlagInvCheckPeriod, 1)
|
|
appOpts = viperAppOpts
|
|
|
|
if height != -1 {
|
|
simApp = simapp.NewSimApp(logger, db, traceStore, false, appOpts)
|
|
|
|
if err := simApp.LoadHeight(height); err != nil {
|
|
return servertypes.ExportedApp{}, err
|
|
}
|
|
} else {
|
|
simApp = simapp.NewSimApp(logger, db, traceStore, true, appOpts)
|
|
}
|
|
|
|
return simApp.ExportAppStateAndValidators(forZeroHeight, jailAllowedAddrs, modulesToExport)
|
|
}
|
|
|
|
var tempDir = func() string {
|
|
dir, err := os.MkdirTemp("", "simapp")
|
|
if err != nil {
|
|
dir = simapp.DefaultNodeHome
|
|
}
|
|
defer os.RemoveAll(dir)
|
|
|
|
return dir
|
|
}
|