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 }