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