github.com/gochain-io/gochain@v2.2.26+incompatible/cmd/gochain/main.go (about) 1 // Copyright 2014 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 // geth is the official command-line client for GoChain. 18 package main 19 20 import ( 21 "context" 22 "fmt" 23 "os" 24 "runtime" 25 "sort" 26 "strings" 27 "time" 28 29 "go.opencensus.io/exporter/stackdriver" 30 "go.opencensus.io/trace" 31 "gopkg.in/urfave/cli.v1" 32 33 "github.com/gochain-io/gochain/accounts" 34 "github.com/gochain-io/gochain/accounts/keystore" 35 "github.com/gochain-io/gochain/cmd/utils" 36 "github.com/gochain-io/gochain/common" 37 "github.com/gochain-io/gochain/console" 38 "github.com/gochain-io/gochain/eth" 39 "github.com/gochain-io/gochain/goclient" 40 "github.com/gochain-io/gochain/internal/debug" 41 "github.com/gochain-io/gochain/log" 42 "github.com/gochain-io/gochain/metrics" 43 "github.com/gochain-io/gochain/node" 44 ) 45 46 const ( 47 clientIdentifier = "GoChain" // Client identifier to advertise over the network 48 ) 49 50 var ( 51 // Git SHA1 commit hash of the release (set via linker flags) 52 gitCommit = "" 53 // GoChain address of the GoChain release oracle. 54 relOracle = common.HexToAddress("0xfa7b9770ca4cb04296cac84f37736d4041251cdf") 55 // The app that holds all commands and flags. 56 app = utils.NewApp(gitCommit, "the GoChain command line interface") 57 // flags that configure the node 58 nodeFlags = []cli.Flag{ 59 utils.IdentityFlag, 60 utils.UnlockedAccountFlag, 61 utils.PasswordFileFlag, 62 utils.BootnodesFlag, 63 utils.BootnodesV4Flag, 64 utils.BootnodesV5Flag, 65 utils.DataDirFlag, 66 utils.KeyStoreDirFlag, 67 utils.NoUSBFlag, 68 utils.DashboardEnabledFlag, 69 utils.DashboardAddrFlag, 70 utils.DashboardPortFlag, 71 utils.DashboardRefreshFlag, 72 utils.DashboardAssetsFlag, 73 utils.TxPoolNoLocalsFlag, 74 utils.TxPoolJournalFlag, 75 utils.TxPoolRejournalFlag, 76 utils.TxPoolPriceLimitFlag, 77 utils.TxPoolPriceBumpFlag, 78 utils.TxPoolAccountSlotsFlag, 79 utils.TxPoolGlobalSlotsFlag, 80 utils.TxPoolAccountQueueFlag, 81 utils.TxPoolGlobalQueueFlag, 82 utils.TxPoolLifetimeFlag, 83 utils.FastSyncFlag, 84 utils.LightModeFlag, 85 utils.SyncModeFlag, 86 utils.GCModeFlag, 87 utils.LightServFlag, 88 utils.LightPeersFlag, 89 utils.LightKDFFlag, 90 utils.CacheFlag, 91 utils.CacheDatabaseFlag, 92 utils.CacheGCFlag, 93 utils.TrieCacheGenFlag, 94 utils.ListenPortFlag, 95 utils.MaxPeersFlag, 96 utils.MaxPendingPeersFlag, 97 utils.MiningEnabledFlag, 98 utils.MinerThreadsFlag, 99 utils.MinerLegacyThreadsFlag, 100 utils.MinerNotifyFlag, 101 utils.MinerGasTargetFlag, 102 utils.MinerLegacyGasTargetFlag, 103 utils.MinerGasLimitFlag, 104 utils.MinerGasPriceFlag, 105 utils.MinerLegacyGasPriceFlag, 106 utils.MinerEtherbaseFlag, 107 utils.MinerLegacyEtherbaseFlag, 108 utils.MinerExtraDataFlag, 109 utils.MinerLegacyExtraDataFlag, 110 utils.MinerRecommitIntervalFlag, 111 utils.MinerNoVerfiyFlag, 112 utils.NATFlag, 113 utils.NoDiscoverFlag, 114 utils.DiscoveryV5Flag, 115 utils.NetrestrictFlag, 116 utils.NodeKeyFileFlag, 117 utils.NodeKeyHexFlag, 118 utils.DeveloperFlag, 119 utils.DeveloperPeriodFlag, 120 utils.TestnetFlag, 121 utils.VMEnableDebugFlag, 122 utils.NetworkIdFlag, 123 utils.RPCCORSDomainFlag, 124 utils.RPCVirtualHostsFlag, 125 utils.NetStatsURLFlag, 126 utils.MetricsEnabledFlag, 127 utils.TracingStackdriverFlag, 128 utils.TracingSampleRateFlag, 129 utils.FakePoWFlag, 130 utils.NoCompactionFlag, 131 utils.GpoBlocksFlag, 132 utils.GpoPercentileFlag, 133 utils.EthdbEndpointFlag, 134 utils.EthdbBucketFlag, 135 utils.EthdbAccessKeyIDFlag, 136 utils.EthdbSecretAccessKeyFlag, 137 utils.EthdbMaxOpenSegmentCountFlag, 138 configFileFlag, 139 } 140 141 rpcFlags = []cli.Flag{ 142 utils.RPCEnabledFlag, 143 utils.RPCListenAddrFlag, 144 utils.RPCPortFlag, 145 utils.RPCApiFlag, 146 utils.WSEnabledFlag, 147 utils.WSListenAddrFlag, 148 utils.WSPortFlag, 149 utils.WSApiFlag, 150 utils.WSAllowedOriginsFlag, 151 utils.IPCDisabledFlag, 152 utils.IPCPathFlag, 153 } 154 155 whisperFlags = []cli.Flag{ 156 utils.WhisperEnabledFlag, 157 utils.WhisperMaxMessageSizeFlag, 158 utils.WhisperMinPOWFlag, 159 } 160 ) 161 162 func init() { 163 // Initialize the CLI app and start GoChain 164 app.Action = gochain 165 app.HideVersion = true // we have a command to print the version 166 app.Copyright = "Copyright 2018 The GoChain Authors" 167 app.Commands = []cli.Command{ 168 // See chaincmd.go: 169 initCommand, 170 importCommand, 171 exportCommand, 172 copydbCommand, 173 removedbCommand, 174 dumpCommand, 175 // See monitorcmd.go: 176 monitorCommand, 177 // See accountcmd.go: 178 accountCommand, 179 walletCommand, 180 // See consolecmd.go: 181 consoleCommand, 182 attachCommand, 183 javascriptCommand, 184 // See misccmd.go: 185 versionCommand, 186 bugCommand, 187 licenseCommand, 188 // See config.go 189 dumpConfigCommand, 190 } 191 sort.Sort(cli.CommandsByName(app.Commands)) 192 193 app.Flags = append(app.Flags, nodeFlags...) 194 app.Flags = append(app.Flags, rpcFlags...) 195 app.Flags = append(app.Flags, consoleFlags...) 196 app.Flags = append(app.Flags, debug.Flags...) 197 app.Flags = append(app.Flags, whisperFlags...) 198 199 app.Before = func(ctx *cli.Context) error { 200 runtime.GOMAXPROCS(runtime.NumCPU()) 201 if err := debug.Setup(ctx); err != nil { 202 return err 203 } 204 // Start system runtime metrics collection 205 go metrics.CollectProcessMetrics(3 * time.Second) 206 207 return nil 208 } 209 210 app.After = func(ctx *cli.Context) error { 211 debug.Exit() 212 console.Stdin.Close() // Resets terminal mode. 213 return nil 214 } 215 } 216 217 func main() { 218 if err := app.Run(os.Args); err != nil { 219 fmt.Fprintln(os.Stderr, err) 220 os.Exit(1) 221 } 222 } 223 224 // geth is the main entry point into the system if no special subcommand is ran. 225 // It creates a default node based on the command line arguments and runs it in 226 // blocking mode, waiting for it to be shut down. 227 func gochain(ctx *cli.Context) error { 228 if ctx.GlobalIsSet(utils.TracingStackdriverFlag.Name) { 229 gcpProjectID := ctx.GlobalString(utils.TracingStackdriverFlag.Name) 230 // Enable the Stackdriver Tracing exporter. 231 sd, err := stackdriver.NewExporter(stackdriver.Options{ 232 ProjectID: gcpProjectID, 233 }) 234 if err != nil { 235 return fmt.Errorf("failed to create the Stackdriver exporter: %v", err) 236 } 237 defer sd.Flush() 238 239 // Register/enable the trace exporter. 240 trace.RegisterExporter(sd) 241 242 if ctx.GlobalIsSet(utils.TracingSampleRateFlag.Name) { 243 rate := ctx.GlobalFloat64(utils.TracingSampleRateFlag.Name) 244 trace.ApplyConfig(trace.Config{DefaultSampler: trace.ProbabilitySampler(rate)}) 245 } 246 } 247 248 node := makeFullNode(ctx) 249 startNode(ctx, node) 250 node.Wait() 251 return nil 252 } 253 254 // startNode boots up the system node and all registered protocols, after which 255 // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the 256 // miner. 257 func startNode(ctx *cli.Context, stack *node.Node) { 258 // Start up the node itself 259 utils.StartNode(stack) 260 261 // Unlock any account specifically requested 262 ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore) 263 264 passwords := utils.MakePasswordList(ctx) 265 unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",") 266 for i, account := range unlocks { 267 if trimmed := strings.TrimSpace(account); trimmed != "" { 268 unlockAccount(ctx, ks, trimmed, i, passwords) 269 } 270 } 271 // Register wallet event handlers to open and auto-derive wallets 272 events := make(chan accounts.WalletEvent, 16) 273 stack.AccountManager().Subscribe(events) 274 275 go func() { 276 // Create an chain state reader for self-derivation 277 rpcClient, err := stack.Attach() 278 if err != nil { 279 utils.Fatalf("Failed to attach to self: %v", err) 280 } 281 stateReader := goclient.NewClient(rpcClient) 282 283 // Open any wallets already attached 284 for _, wallet := range stack.AccountManager().Wallets() { 285 if err := wallet.Open(""); err != nil { 286 log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err) 287 } 288 } 289 // Listen for wallet event till termination 290 for event := range events { 291 switch event.Kind { 292 case accounts.WalletArrived: 293 if err := event.Wallet.Open(""); err != nil { 294 log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err) 295 } 296 case accounts.WalletOpened: 297 status, _ := event.Wallet.Status() 298 log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status) 299 300 if event.Wallet.URL().Scheme == "ledger" { 301 event.Wallet.SelfDerive(accounts.DefaultLedgerBaseDerivationPath, stateReader) 302 } else { 303 event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader) 304 } 305 306 case accounts.WalletDropped: 307 log.Info("Old wallet dropped", "url", event.Wallet.URL()) 308 event.Wallet.Close() 309 } 310 } 311 }() 312 // Start auxiliary services if enabled 313 if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) { 314 // Mining only makes sense if a full GoChain node is running 315 if ctx.GlobalBool(utils.LightModeFlag.Name) || ctx.GlobalString(utils.SyncModeFlag.Name) == "light" { 316 utils.Fatalf("Light clients do not support mining") 317 } 318 var gochain *eth.GoChain 319 if err := stack.Service(&gochain); err != nil { 320 utils.Fatalf("GoChain service not running: %v", err) 321 } 322 // Set the gas price to the limits from the CLI and start mining 323 gasprice := utils.GlobalBig(ctx, utils.MinerLegacyGasPriceFlag.Name) 324 if ctx.IsSet(utils.MinerGasPriceFlag.Name) { 325 gasprice = utils.GlobalBig(ctx, utils.MinerGasPriceFlag.Name) 326 } 327 gochain.TxPool().SetGasPrice(context.Background(), gasprice) 328 329 threads := ctx.GlobalInt(utils.MinerLegacyThreadsFlag.Name) 330 if ctx.GlobalIsSet(utils.MinerThreadsFlag.Name) { 331 threads = ctx.GlobalInt(utils.MinerThreadsFlag.Name) 332 } 333 if err := gochain.StartMining(threads); err != nil { 334 utils.Fatalf("Failed to start mining: %v", err) 335 } 336 } 337 }