github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/cmd/geth/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 Ethereum. 18 package main 19 20 import ( 21 "fmt" 22 "log" 23 "math/rand" 24 "os" 25 "path/filepath" 26 "time" 27 28 "gopkg.in/urfave/cli.v1" 29 30 "github.com/ethereumproject/benchmark/rtprof" 31 "github.com/ethereumproject/go-ethereum/common" 32 "github.com/ethereumproject/go-ethereum/console" 33 "github.com/ethereumproject/go-ethereum/core" 34 "github.com/ethereumproject/go-ethereum/logger" 35 "github.com/ethereumproject/go-ethereum/metrics" 36 ) 37 38 // Version is the application revision identifier. It can be set with the linker 39 // as in: go build -ldflags "-X main.Version="`git describe --tags` 40 var Version = "source" 41 42 func init() { 43 rand.Seed(time.Now().UTC().UnixNano()) 44 common.SetClientVersion(Version) 45 } 46 47 var makeDagCommand = cli.Command{ 48 Action: makedag, 49 Name: "make-dag", 50 Aliases: []string{"makedag"}, 51 Usage: "Generate ethash dag (for testing)", 52 Description: ` 53 The makedag command generates an ethash DAG in /tmp/dag. 54 55 This command exists to support the system testing project. 56 Regular users do not need to execute it. 57 `, 58 } 59 60 var gpuInfoCommand = cli.Command{ 61 Action: gpuinfo, 62 Name: "gpu-info", 63 Aliases: []string{"gpuinfo"}, 64 Usage: "GPU info", 65 Description: ` 66 Prints OpenCL device info for all found GPUs. 67 `, 68 } 69 70 var gpuBenchCommand = cli.Command{ 71 Action: gpubench, 72 Name: "gpu-bench", 73 Aliases: []string{"gpubench"}, 74 Usage: "Benchmark GPU", 75 Description: ` 76 Runs quick benchmark on first GPU found. 77 `, 78 } 79 80 var versionCommand = cli.Command{ 81 Action: version, 82 Name: "version", 83 Usage: "Print ethereum version numbers", 84 Description: ` 85 The output of this command is supposed to be machine-readable. 86 `, 87 } 88 89 var makeMlogDocCommand = cli.Command{ 90 Action: makeMLogDocumentation, 91 Name: "mdoc", 92 Usage: "Generate mlog documentation", 93 Description: ` 94 Auto-generates documentation for all available mlog lines. 95 Use -md switch to toggle markdown output (eg. for wiki). 96 Arguments may be used to specify exclusive candidate components; 97 so 'geth mdoc -md discover' will generate markdown documentation only 98 for the 'discover' component. 99 `, 100 Flags: []cli.Flag{ 101 cli.BoolFlag{ 102 Name: "md", 103 Usage: "Toggle markdown formatting", 104 }, 105 }, 106 } 107 108 func makeCLIApp() (app *cli.App) { 109 app = cli.NewApp() 110 app.Name = filepath.Base(os.Args[0]) 111 app.Version = Version 112 app.Usage = "the go-ethereum command line interface" 113 app.Action = geth 114 app.HideVersion = true // we have a command to print the version 115 116 app.Commands = []cli.Command{ 117 importCommand, 118 exportCommand, 119 dumpChainConfigCommand, 120 upgradedbCommand, 121 dumpCommand, 122 rollbackCommand, 123 recoverCommand, 124 resetCommand, 125 monitorCommand, 126 accountCommand, 127 walletCommand, 128 consoleCommand, 129 attachCommand, 130 javascriptCommand, 131 statusCommand, 132 apiCommand, 133 makeDagCommand, 134 gpuInfoCommand, 135 gpuBenchCommand, 136 versionCommand, 137 makeMlogDocCommand, 138 buildAddrTxIndexCommand, 139 } 140 141 app.Flags = []cli.Flag{ 142 PprofFlag, 143 PprofIntervalFlag, 144 SputnikVMFlag, 145 NodeNameFlag, 146 UnlockedAccountFlag, 147 PasswordFileFlag, 148 AccountsIndexFlag, 149 BootnodesFlag, 150 DataDirFlag, 151 DocRootFlag, 152 KeyStoreDirFlag, 153 ChainIdentityFlag, 154 BlockchainVersionFlag, 155 FastSyncFlag, 156 AddrTxIndexFlag, 157 AddrTxIndexAutoBuildFlag, 158 CacheFlag, 159 LightKDFFlag, 160 JSpathFlag, 161 ListenPortFlag, 162 MaxPeersFlag, 163 MaxPendingPeersFlag, 164 EtherbaseFlag, 165 GasPriceFlag, 166 MinerThreadsFlag, 167 MiningEnabledFlag, 168 MiningGPUFlag, 169 AutoDAGFlag, 170 TargetGasLimitFlag, 171 NATFlag, 172 NatspecEnabledFlag, 173 NoDiscoverFlag, 174 NodeKeyFileFlag, 175 NodeKeyHexFlag, 176 RPCEnabledFlag, 177 RPCListenAddrFlag, 178 RPCPortFlag, 179 RPCApiFlag, 180 WSEnabledFlag, 181 WSListenAddrFlag, 182 WSPortFlag, 183 WSApiFlag, 184 WSAllowedOriginsFlag, 185 IPCDisabledFlag, 186 IPCApiFlag, 187 IPCPathFlag, 188 ExecFlag, 189 PreloadJSFlag, 190 WhisperEnabledFlag, 191 DevModeFlag, 192 TestNetFlag, 193 NetworkIdFlag, 194 RPCCORSDomainFlag, 195 NeckbeardFlag, 196 VerbosityFlag, 197 DisplayFlag, 198 DisplayFormatFlag, 199 VModuleFlag, 200 LogDirFlag, 201 LogMaxSizeFlag, 202 LogMinSizeFlag, 203 LogMaxTotalSizeFlag, 204 LogIntervalFlag, 205 LogMaxAgeFlag, 206 LogCompressFlag, 207 LogStatusFlag, 208 MLogFlag, 209 MLogDirFlag, 210 MLogComponentsFlag, 211 BacktraceAtFlag, 212 MetricsFlag, 213 FakePoWFlag, 214 SolcPathFlag, 215 GpoMinGasPriceFlag, 216 GpoMaxGasPriceFlag, 217 GpoFullBlockRatioFlag, 218 GpobaseStepDownFlag, 219 GpobaseStepUpFlag, 220 GpobaseCorrectionFactorFlag, 221 ExtraDataFlag, 222 Unused1, 223 } 224 225 app.Before = func(ctx *cli.Context) error { 226 227 // It's a patch. 228 // Don't know why urfave/cli isn't catching the unknown command on its own. 229 if ctx.Args().Present() { 230 commandExists := false 231 for _, cmd := range app.Commands { 232 if cmd.HasName(ctx.Args().First()) { 233 commandExists = true 234 } 235 } 236 if !commandExists { 237 if e := cli.ShowCommandHelp(ctx, ctx.Args().First()); e != nil { 238 return e 239 } 240 } 241 } 242 243 // Check for --exec set without console OR attach 244 if ctx.IsSet(ExecFlag.Name) { 245 // If no command is used, OR command is not one of the valid commands attach/console 246 if cmdName := ctx.Args().First(); cmdName == "" || (cmdName != "console" && cmdName != "attach") { 247 log.Printf("Error: --%v flag requires use of 'attach' OR 'console' command, command was: '%v'", ExecFlag.Name, cmdName) 248 cli.ShowCommandHelp(ctx, consoleCommand.Name) 249 cli.ShowCommandHelp(ctx, attachCommand.Name) 250 os.Exit(1) 251 } 252 } 253 254 if ctx.IsSet(SputnikVMFlag.Name) { 255 if core.SputnikVMExists { 256 core.UseSputnikVM = "true" 257 } else { 258 log.Fatal("This version of geth wasn't built to include SputnikVM. To build with SputnikVM, use -tags=sputnikvm following the go build command.") 259 } 260 } 261 262 // Check for migrations and handle if conditionals are met. 263 if err := handleIfDataDirSchemaMigrations(ctx); err != nil { 264 return err 265 } 266 267 if err := setupLogRotation(ctx); err != nil { 268 return err 269 } 270 271 // Handle parsing and applying log verbosity, severities, and default configurations from context. 272 if err := setupLogging(ctx); err != nil { 273 return err 274 } 275 276 // Handle parsing and applying log rotation configs from context. 277 if err := setupLogRotation(ctx); err != nil { 278 return err 279 } 280 281 if s := ctx.String("metrics"); s != "" { 282 go metrics.CollectToFile(s) 283 } 284 285 // (whilei): I use `log` instead of `glog` because git diff tells me: 286 // > The output of this command is supposed to be machine-readable. 287 gasLimit := ctx.GlobalString(aliasableName(TargetGasLimitFlag.Name, ctx)) 288 if _, ok := core.TargetGasLimit.SetString(gasLimit, 0); !ok { 289 return fmt.Errorf("malformed %s flag value %q", aliasableName(TargetGasLimitFlag.Name, ctx), gasLimit) 290 } 291 292 // Set morden chain by default for dev mode. 293 if ctx.GlobalBool(aliasableName(DevModeFlag.Name, ctx)) { 294 if !ctx.GlobalIsSet(aliasableName(ChainIdentityFlag.Name, ctx)) { 295 if e := ctx.Set(aliasableName(ChainIdentityFlag.Name, ctx), "morden"); e != nil { 296 return fmt.Errorf("failed to set chain value: %v", e) 297 } 298 } 299 } 300 301 if port := ctx.GlobalInt(PprofFlag.Name); port != 0 { 302 interval := 5 * time.Second 303 if i := ctx.GlobalInt(PprofIntervalFlag.Name); i > 0 { 304 interval = time.Duration(i) * time.Second 305 } 306 rtppf.Start(interval, port) 307 } 308 309 return nil 310 } 311 312 app.After = func(ctx *cli.Context) error { 313 rtppf.Stop() 314 logger.Flush() 315 console.Stdin.Close() // Resets terminal mode. 316 return nil 317 } 318 319 app.CommandNotFound = func(c *cli.Context, command string) { 320 fmt.Fprintf(c.App.Writer, "Invalid command: %q. Please find `geth` usage below. \n", command) 321 cli.ShowAppHelp(c) 322 os.Exit(3) 323 } 324 return app 325 } 326 327 func main() { 328 app := makeCLIApp() 329 if err := app.Run(os.Args); err != nil { 330 fmt.Fprintln(os.Stderr, err) 331 os.Exit(1) 332 } 333 } 334 335 // geth is the main entry point into the system if no special subcommand is ran. 336 // It creates a default node based on the command line arguments and runs it in 337 // blocking mode, waiting for it to be shut down. 338 func geth(ctx *cli.Context) error { 339 340 n := MakeSystemNode(Version, ctx) 341 ethe := startNode(ctx, n) 342 343 if ctx.GlobalString(LogStatusFlag.Name) != "off" { 344 dispatchStatusLogs(ctx, ethe) 345 } 346 logLoggingConfiguration(ctx) 347 348 n.Wait() 349 350 return nil 351 }