github.com/cosmos/cosmos-sdk@v0.50.10/server/cmt_cmds.go (about)

     1  package server
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"strconv"
     8  	"strings"
     9  
    10  	cmtcfg "github.com/cometbft/cometbft/config"
    11  	cmtjson "github.com/cometbft/cometbft/libs/json"
    12  	"github.com/cometbft/cometbft/node"
    13  	"github.com/cometbft/cometbft/p2p"
    14  	pvm "github.com/cometbft/cometbft/privval"
    15  	cmtversion "github.com/cometbft/cometbft/version"
    16  	"github.com/spf13/cobra"
    17  	"sigs.k8s.io/yaml"
    18  
    19  	"cosmossdk.io/log"
    20  
    21  	"github.com/cosmos/cosmos-sdk/client"
    22  	"github.com/cosmos/cosmos-sdk/client/flags"
    23  	"github.com/cosmos/cosmos-sdk/client/grpc/cmtservice"
    24  	rpc "github.com/cosmos/cosmos-sdk/client/rpc"
    25  	cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec"
    26  	"github.com/cosmos/cosmos-sdk/server/types"
    27  	sdk "github.com/cosmos/cosmos-sdk/types"
    28  	"github.com/cosmos/cosmos-sdk/types/query"
    29  	"github.com/cosmos/cosmos-sdk/version"
    30  	auth "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
    31  )
    32  
    33  // StatusCommand returns the command to return the status of the network.
    34  func StatusCommand() *cobra.Command {
    35  	cmd := &cobra.Command{
    36  		Use:   "status",
    37  		Short: "Query remote node for status",
    38  		RunE: func(cmd *cobra.Command, _ []string) error {
    39  			clientCtx, err := client.GetClientQueryContext(cmd)
    40  			if err != nil {
    41  				return err
    42  			}
    43  
    44  			status, err := cmtservice.GetNodeStatus(context.Background(), clientCtx)
    45  			if err != nil {
    46  				return err
    47  			}
    48  
    49  			output, err := cmtjson.Marshal(status)
    50  			if err != nil {
    51  				return err
    52  			}
    53  
    54  			// In order to maintain backwards compatibility, the default json format output
    55  			outputFormat, _ := cmd.Flags().GetString(flags.FlagOutput)
    56  			if outputFormat == flags.OutputFormatJSON {
    57  				clientCtx = clientCtx.WithOutputFormat(flags.OutputFormatJSON)
    58  			}
    59  
    60  			return clientCtx.PrintRaw(output)
    61  		},
    62  	}
    63  
    64  	cmd.Flags().StringP(flags.FlagNode, "n", "tcp://localhost:26657", "Node to connect to")
    65  	cmd.Flags().StringP(flags.FlagOutput, "o", "json", "Output format (text|json)")
    66  
    67  	return cmd
    68  }
    69  
    70  // ShowNodeIDCmd - ported from CometBFT, dump node ID to stdout
    71  func ShowNodeIDCmd() *cobra.Command {
    72  	return &cobra.Command{
    73  		Use:   "show-node-id",
    74  		Short: "Show this node's ID",
    75  		RunE: func(cmd *cobra.Command, args []string) error {
    76  			serverCtx := GetServerContextFromCmd(cmd)
    77  			cfg := serverCtx.Config
    78  
    79  			nodeKey, err := p2p.LoadNodeKey(cfg.NodeKeyFile())
    80  			if err != nil {
    81  				return err
    82  			}
    83  
    84  			cmd.Println(nodeKey.ID())
    85  			return nil
    86  		},
    87  	}
    88  }
    89  
    90  // ShowValidatorCmd - ported from CometBFT, show this node's validator info
    91  func ShowValidatorCmd() *cobra.Command {
    92  	cmd := cobra.Command{
    93  		Use:   "show-validator",
    94  		Short: "Show this node's CometBFT validator info",
    95  		RunE: func(cmd *cobra.Command, args []string) error {
    96  			serverCtx := GetServerContextFromCmd(cmd)
    97  			cfg := serverCtx.Config
    98  
    99  			privValidator := pvm.LoadFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile())
   100  			pk, err := privValidator.GetPubKey()
   101  			if err != nil {
   102  				return err
   103  			}
   104  
   105  			sdkPK, err := cryptocodec.FromCmtPubKeyInterface(pk)
   106  			if err != nil {
   107  				return err
   108  			}
   109  
   110  			clientCtx := client.GetClientContextFromCmd(cmd)
   111  			bz, err := clientCtx.Codec.MarshalInterfaceJSON(sdkPK)
   112  			if err != nil {
   113  				return err
   114  			}
   115  
   116  			cmd.Println(string(bz))
   117  			return nil
   118  		},
   119  	}
   120  
   121  	return &cmd
   122  }
   123  
   124  // ShowAddressCmd - show this node's validator address
   125  func ShowAddressCmd() *cobra.Command {
   126  	cmd := &cobra.Command{
   127  		Use:   "show-address",
   128  		Short: "Shows this node's CometBFT validator consensus address",
   129  		RunE: func(cmd *cobra.Command, args []string) error {
   130  			serverCtx := GetServerContextFromCmd(cmd)
   131  			cfg := serverCtx.Config
   132  
   133  			privValidator := pvm.LoadFilePV(cfg.PrivValidatorKeyFile(), cfg.PrivValidatorStateFile())
   134  
   135  			valConsAddr := (sdk.ConsAddress)(privValidator.GetAddress())
   136  
   137  			cmd.Println(valConsAddr.String())
   138  			return nil
   139  		},
   140  	}
   141  
   142  	return cmd
   143  }
   144  
   145  // VersionCmd prints CometBFT and ABCI version numbers.
   146  func VersionCmd() *cobra.Command {
   147  	return &cobra.Command{
   148  		Use:   "version",
   149  		Short: "Print CometBFT libraries' version",
   150  		Long:  "Print protocols' and libraries' version numbers against which this app has been compiled.",
   151  		RunE: func(cmd *cobra.Command, args []string) error {
   152  			bs, err := yaml.Marshal(&struct {
   153  				CometBFT      string
   154  				ABCI          string
   155  				BlockProtocol uint64
   156  				P2PProtocol   uint64
   157  			}{
   158  				CometBFT:      cmtversion.TMCoreSemVer,
   159  				ABCI:          cmtversion.ABCIVersion,
   160  				BlockProtocol: cmtversion.BlockProtocol,
   161  				P2PProtocol:   cmtversion.P2PProtocol,
   162  			})
   163  			if err != nil {
   164  				return err
   165  			}
   166  
   167  			cmd.Println(string(bs))
   168  			return nil
   169  		},
   170  	}
   171  }
   172  
   173  // QueryBlocksCmd returns a command to search through blocks by events.
   174  func QueryBlocksCmd() *cobra.Command {
   175  	cmd := &cobra.Command{
   176  		Use:   "blocks",
   177  		Short: "Query for paginated blocks that match a set of events",
   178  		Long: `Search for blocks that match the exact given events where results are paginated.
   179  The events query is directly passed to CometBFT's RPC BlockSearch method and must
   180  conform to CometBFT's query syntax.
   181  Please refer to each module's documentation for the full set of events to query
   182  for. Each module documents its respective events under 'xx_events.md'.
   183  `,
   184  		Example: fmt.Sprintf(
   185  			"$ %s query blocks --query \"message.sender='cosmos1...' AND block.height > 7\" --page 1 --limit 30 --order_by asc",
   186  			version.AppName,
   187  		),
   188  		RunE: func(cmd *cobra.Command, args []string) error {
   189  			clientCtx, err := client.GetClientQueryContext(cmd)
   190  			if err != nil {
   191  				return err
   192  			}
   193  			query, _ := cmd.Flags().GetString(auth.FlagQuery)
   194  			page, _ := cmd.Flags().GetInt(flags.FlagPage)
   195  			limit, _ := cmd.Flags().GetInt(flags.FlagLimit)
   196  			orderBy, _ := cmd.Flags().GetString(auth.FlagOrderBy)
   197  
   198  			blocks, err := rpc.QueryBlocks(clientCtx, page, limit, query, orderBy)
   199  			if err != nil {
   200  				return err
   201  			}
   202  
   203  			return clientCtx.PrintProto(blocks)
   204  		},
   205  	}
   206  
   207  	flags.AddQueryFlagsToCmd(cmd)
   208  	cmd.Flags().Int(flags.FlagPage, query.DefaultPage, "Query a specific page of paginated results")
   209  	cmd.Flags().Int(flags.FlagLimit, query.DefaultLimit, "Query number of transactions results per page returned")
   210  	cmd.Flags().String(auth.FlagQuery, "", "The blocks events query per CometBFT's query semantics")
   211  	cmd.Flags().String(auth.FlagOrderBy, "", "The ordering semantics (asc|dsc)")
   212  	_ = cmd.MarkFlagRequired(auth.FlagQuery)
   213  
   214  	return cmd
   215  }
   216  
   217  // QueryBlockCmd implements the default command for a Block query.
   218  func QueryBlockCmd() *cobra.Command {
   219  	cmd := &cobra.Command{
   220  		Use:   "block --type=[height|hash] [height|hash]",
   221  		Short: "Query for a committed block by height, hash, or event(s)",
   222  		Long:  "Query for a specific committed block using the CometBFT RPC `block` and `block_by_hash` method",
   223  		Example: strings.TrimSpace(fmt.Sprintf(`
   224  $ %s query block --%s=%s <height>
   225  $ %s query block --%s=%s <hash>
   226  `,
   227  			version.AppName, auth.FlagType, auth.TypeHeight,
   228  			version.AppName, auth.FlagType, auth.TypeHash)),
   229  		Args: cobra.MaximumNArgs(1),
   230  		RunE: func(cmd *cobra.Command, args []string) error {
   231  			clientCtx, err := client.GetClientQueryContext(cmd)
   232  			if err != nil {
   233  				return err
   234  			}
   235  
   236  			typ, _ := cmd.Flags().GetString(auth.FlagType)
   237  			if len(args) == 0 {
   238  				// do not break default v0.50 behavior of block hash
   239  				// if no args are provided, set the type to height
   240  				typ = auth.TypeHeight
   241  			}
   242  
   243  			switch typ {
   244  			case auth.TypeHeight:
   245  				var (
   246  					err    error
   247  					height int64
   248  				)
   249  				heightStr := ""
   250  				if len(args) > 0 {
   251  					heightStr = args[0]
   252  				}
   253  
   254  				if heightStr == "" {
   255  					cmd.Println("Falling back to latest block height:")
   256  					height, err = rpc.GetChainHeight(clientCtx)
   257  					if err != nil {
   258  						return fmt.Errorf("failed to get chain height: %w", err)
   259  					}
   260  				} else {
   261  					height, err = strconv.ParseInt(heightStr, 10, 64)
   262  					if err != nil {
   263  						return fmt.Errorf("failed to parse block height: %w", err)
   264  					}
   265  				}
   266  
   267  				output, err := rpc.GetBlockByHeight(clientCtx, &height)
   268  				if err != nil {
   269  					return err
   270  				}
   271  
   272  				if output.Header.Height == 0 {
   273  					return fmt.Errorf("no block found with height %s", args[0])
   274  				}
   275  
   276  				return clientCtx.PrintProto(output)
   277  
   278  			case auth.TypeHash:
   279  
   280  				if args[0] == "" {
   281  					return fmt.Errorf("argument should be a tx hash")
   282  				}
   283  
   284  				// If hash is given, then query the tx by hash.
   285  				output, err := rpc.GetBlockByHash(clientCtx, args[0])
   286  				if err != nil {
   287  					return err
   288  				}
   289  
   290  				if output.Header.AppHash == nil {
   291  					return fmt.Errorf("no block found with hash %s", args[0])
   292  				}
   293  
   294  				return clientCtx.PrintProto(output)
   295  
   296  			default:
   297  				return fmt.Errorf("unknown --%s value %s", auth.FlagType, typ)
   298  			}
   299  		},
   300  	}
   301  
   302  	flags.AddQueryFlagsToCmd(cmd)
   303  	cmd.Flags().String(auth.FlagType, auth.TypeHash, fmt.Sprintf("The type to be used when querying tx, can be one of \"%s\", \"%s\"", auth.TypeHeight, auth.TypeHash))
   304  
   305  	return cmd
   306  }
   307  
   308  // QueryBlockResultsCmd implements the default command for a BlockResults query.
   309  func QueryBlockResultsCmd() *cobra.Command {
   310  	cmd := &cobra.Command{
   311  		Use:   "block-results [height]",
   312  		Short: "Query for a committed block's results by height",
   313  		Long:  "Query for a specific committed block's results using the CometBFT RPC `block_results` method",
   314  		Args:  cobra.RangeArgs(0, 1),
   315  		RunE: func(cmd *cobra.Command, args []string) error {
   316  			clientCtx, err := client.GetClientQueryContext(cmd)
   317  			if err != nil {
   318  				return err
   319  			}
   320  
   321  			node, err := clientCtx.GetNode()
   322  			if err != nil {
   323  				return err
   324  			}
   325  
   326  			// optional height
   327  			var height int64
   328  			if len(args) > 0 {
   329  				height, err = strconv.ParseInt(args[0], 10, 64)
   330  				if err != nil {
   331  					return err
   332  				}
   333  			} else {
   334  				cmd.Println("Falling back to latest block height:")
   335  				height, err = rpc.GetChainHeight(clientCtx)
   336  				if err != nil {
   337  					return fmt.Errorf("failed to get chain height: %w", err)
   338  				}
   339  			}
   340  
   341  			blockRes, err := node.BlockResults(context.Background(), &height)
   342  			if err != nil {
   343  				return err
   344  			}
   345  
   346  			// coretypes.ResultBlockResults doesn't implement proto.Message interface
   347  			// so we can't print it using clientCtx.PrintProto
   348  			// we choose to serialize it to json and print the json instead
   349  			blockResStr, err := json.Marshal(blockRes)
   350  			if err != nil {
   351  				return err
   352  			}
   353  
   354  			return clientCtx.PrintRaw(blockResStr)
   355  		},
   356  	}
   357  
   358  	flags.AddQueryFlagsToCmd(cmd)
   359  
   360  	return cmd
   361  }
   362  
   363  func BootstrapStateCmd(appCreator types.AppCreator) *cobra.Command {
   364  	cmd := &cobra.Command{
   365  		Use:   "bootstrap-state",
   366  		Short: "Bootstrap CometBFT state at an arbitrary block height using a light client",
   367  		Args:  cobra.NoArgs,
   368  		RunE: func(cmd *cobra.Command, args []string) error {
   369  			serverCtx := GetServerContextFromCmd(cmd)
   370  			logger := log.NewLogger(cmd.OutOrStdout())
   371  			cfg := serverCtx.Config
   372  
   373  			height, err := cmd.Flags().GetInt64("height")
   374  			if err != nil {
   375  				return err
   376  			}
   377  			if height == 0 {
   378  				home := serverCtx.Viper.GetString(flags.FlagHome)
   379  				db, err := openDB(home, GetAppDBBackend(serverCtx.Viper))
   380  				if err != nil {
   381  					return err
   382  				}
   383  
   384  				app := appCreator(logger, db, nil, serverCtx.Viper)
   385  				height = app.CommitMultiStore().LastCommitID().Version
   386  			}
   387  
   388  			return node.BootstrapStateWithGenProvider(cmd.Context(), cfg, cmtcfg.DefaultDBProvider, getGenDocProvider(cfg), uint64(height), nil)
   389  		},
   390  	}
   391  
   392  	cmd.Flags().Int64("height", 0, "Block height to bootstrap state at, if not provided it uses the latest block height in app state")
   393  
   394  	return cmd
   395  }