github.com/lazyledger/lazyledger-core@v0.35.0-dev.0.20210613111200-4c651f053571/cmd/tendermint/commands/run_node.go (about)

     1  package commands
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/sha256"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  
    10  	"github.com/spf13/cobra"
    11  
    12  	cfg "github.com/lazyledger/lazyledger-core/config"
    13  	"github.com/lazyledger/lazyledger-core/ipfs"
    14  	tmos "github.com/lazyledger/lazyledger-core/libs/os"
    15  	nm "github.com/lazyledger/lazyledger-core/node"
    16  )
    17  
    18  var (
    19  	genesisHash []byte
    20  	initIPFS    bool
    21  )
    22  
    23  // AddNodeFlags exposes some common configuration options on the command-line
    24  // These are exposed for convenience of commands embedding a tendermint node
    25  func AddNodeFlags(cmd *cobra.Command) {
    26  	// bind flags
    27  	cmd.Flags().String("moniker", config.Moniker, "node name")
    28  
    29  	// priv val flags
    30  	cmd.Flags().String(
    31  		"priv-validator-laddr",
    32  		config.PrivValidatorListenAddr,
    33  		"socket address to listen on for connections from external priv-validator process")
    34  
    35  	// node flags
    36  	cmd.Flags().Bool("fast-sync", config.FastSyncMode, "fast blockchain syncing")
    37  	cmd.Flags().BytesHexVar(
    38  		&genesisHash,
    39  		"genesis-hash",
    40  		[]byte{},
    41  		"optional SHA-256 hash of the genesis file")
    42  	cmd.Flags().Int64("consensus.double-sign-check-height", config.Consensus.DoubleSignCheckHeight,
    43  		"how many blocks to look back to check existence of the node's "+
    44  			"consensus votes before joining consensus")
    45  
    46  	// abci flags
    47  	cmd.Flags().String(
    48  		"proxy-app",
    49  		config.ProxyApp,
    50  		"proxy app address, or one of: 'kvstore',"+
    51  			" 'persistent_kvstore',"+
    52  			" 'counter',"+
    53  			" 'counter_serial' or 'noop' for local testing.")
    54  
    55  	// rpc flags
    56  	cmd.Flags().String("rpc.laddr", config.RPC.ListenAddress, "RPC listen address. Port required")
    57  	cmd.Flags().String(
    58  		"rpc.grpc-laddr",
    59  		config.RPC.GRPCListenAddress,
    60  		"GRPC listen address (BroadcastTx only). Port required")
    61  	cmd.Flags().Bool("rpc.unsafe", config.RPC.Unsafe, "enabled unsafe rpc methods")
    62  	cmd.Flags().String("rpc.pprof-laddr", config.RPC.PprofListenAddress, "pprof listen address (https://golang.org/pkg/net/http/pprof)")
    63  
    64  	// p2p flags
    65  	cmd.Flags().String(
    66  		"p2p.laddr",
    67  		config.P2P.ListenAddress,
    68  		"node listen address. (0.0.0.0:0 means any interface, any port)")
    69  	cmd.Flags().String("p2p.seeds", config.P2P.Seeds, "comma-delimited ID@host:port seed nodes")
    70  	cmd.Flags().String("p2p.persistent-peers", config.P2P.PersistentPeers, "comma-delimited ID@host:port persistent peers")
    71  	cmd.Flags().String("p2p.unconditional-peer-ids",
    72  		config.P2P.UnconditionalPeerIDs, "comma-delimited IDs of unconditional peers")
    73  	cmd.Flags().Bool("p2p.upnp", config.P2P.UPNP, "enable/disable UPNP port forwarding")
    74  	cmd.Flags().Bool("p2p.pex", config.P2P.PexReactor, "enable/disable Peer-Exchange")
    75  	cmd.Flags().Bool("p2p.seed-mode", config.P2P.SeedMode, "enable/disable seed mode")
    76  	cmd.Flags().String("p2p.private-peer-ids", config.P2P.PrivatePeerIDs, "comma-delimited private peer IDs")
    77  
    78  	// consensus flags
    79  	cmd.Flags().Bool(
    80  		"consensus.create-empty-blocks",
    81  		config.Consensus.CreateEmptyBlocks,
    82  		"set this to false to only produce blocks when there are txs or when the AppHash changes")
    83  	cmd.Flags().String(
    84  		"consensus.create-empty-blocks-interval",
    85  		config.Consensus.CreateEmptyBlocksInterval.String(),
    86  		"the possible interval between empty blocks")
    87  
    88  	// db flags
    89  	cmd.Flags().String(
    90  		"db-dir",
    91  		config.DBPath,
    92  		"database directory")
    93  
    94  	cmd.Flags().String(
    95  		"ipfs.repo-path",
    96  		config.IPFS.RepoPath,
    97  		"custom IPFS repository path. Defaults to `.{RootDir}/ipfs`",
    98  	)
    99  	cmd.Flags().Bool(
   100  		"ipfs.serve-api",
   101  		config.IPFS.ServeAPI,
   102  		"set this to expose IPFS API(useful for debugging)",
   103  	)
   104  	cmd.Flags().BoolVar(
   105  		&initIPFS,
   106  		"ipfs.init",
   107  		false,
   108  		"set this to initialize repository for embedded IPFS node. Flag is ignored if repo is already initialized",
   109  	)
   110  }
   111  
   112  // NewRunNodeCmd returns the command that allows the CLI to start a node.
   113  // It can be used with a custom PrivValidator and in-process ABCI application.
   114  func NewRunNodeCmd(nodeProvider nm.Provider) *cobra.Command {
   115  	cmd := &cobra.Command{
   116  		Use:     "start",
   117  		Aliases: []string{"node", "run"},
   118  		Short:   "Run the tendermint node",
   119  		RunE: func(cmd *cobra.Command, args []string) error {
   120  			if err := checkGenesisHash(config); err != nil {
   121  				return err
   122  			}
   123  
   124  			n, err := nodeProvider(
   125  				config,
   126  				ipfs.Embedded(initIPFS, config.IPFS, logger),
   127  				logger,
   128  			)
   129  			if err != nil {
   130  				return fmt.Errorf("failed to create node: %w", err)
   131  			}
   132  
   133  			if err := n.Start(); err != nil {
   134  				return fmt.Errorf("failed to start node: %w", err)
   135  			}
   136  
   137  			logger.Info("Started node", "nodeInfo", n.Switch().NodeInfo())
   138  
   139  			// Stop upon receiving SIGTERM or CTRL-C.
   140  			tmos.TrapSignal(logger, func() {
   141  				if n.IsRunning() {
   142  					if err := n.Stop(); err != nil {
   143  						logger.Error("unable to stop the node", "error", err)
   144  					}
   145  				}
   146  			})
   147  
   148  			// Run forever.
   149  			select {}
   150  		},
   151  	}
   152  
   153  	AddNodeFlags(cmd)
   154  	return cmd
   155  }
   156  
   157  func checkGenesisHash(config *cfg.Config) error {
   158  	if len(genesisHash) == 0 || config.Genesis == "" {
   159  		return nil
   160  	}
   161  
   162  	// Calculate SHA-256 hash of the genesis file.
   163  	f, err := os.Open(config.GenesisFile())
   164  	if err != nil {
   165  		return fmt.Errorf("can't open genesis file: %w", err)
   166  	}
   167  	defer f.Close()
   168  	h := sha256.New()
   169  	if _, err := io.Copy(h, f); err != nil {
   170  		return fmt.Errorf("error when hashing genesis file: %w", err)
   171  	}
   172  	actualHash := h.Sum(nil)
   173  
   174  	// Compare with the flag.
   175  	if !bytes.Equal(genesisHash, actualHash) {
   176  		return fmt.Errorf(
   177  			"--genesis_hash=%X does not match %s hash: %X",
   178  			genesisHash, config.GenesisFile(), actualHash)
   179  	}
   180  
   181  	return nil
   182  }