github.com/myafeier/go-ethereum@v1.6.8-0.20170719123245-3e0dbe0eaa72/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  	"os"
    23  	"runtime"
    24  	"strings"
    25  	"time"
    26  
    27  	"github.com/ethereum/go-ethereum/accounts"
    28  	"github.com/ethereum/go-ethereum/accounts/keystore"
    29  	"github.com/ethereum/go-ethereum/cmd/utils"
    30  	"github.com/ethereum/go-ethereum/common"
    31  	"github.com/ethereum/go-ethereum/console"
    32  	"github.com/ethereum/go-ethereum/eth"
    33  	"github.com/ethereum/go-ethereum/ethclient"
    34  	"github.com/ethereum/go-ethereum/internal/debug"
    35  	"github.com/ethereum/go-ethereum/log"
    36  	"github.com/ethereum/go-ethereum/metrics"
    37  	"github.com/ethereum/go-ethereum/node"
    38  	"gopkg.in/urfave/cli.v1"
    39  )
    40  
    41  const (
    42  	clientIdentifier = "geth" // Client identifier to advertise over the network
    43  )
    44  
    45  var (
    46  	// Git SHA1 commit hash of the release (set via linker flags)
    47  	gitCommit = ""
    48  	// Ethereum address of the Geth release oracle.
    49  	relOracle = common.HexToAddress("0xfa7b9770ca4cb04296cac84f37736d4041251cdf")
    50  	// The app that holds all commands and flags.
    51  	app = utils.NewApp(gitCommit, "the go-ethereum command line interface")
    52  	// flags that configure the node
    53  	nodeFlags = []cli.Flag{
    54  		utils.IdentityFlag,
    55  		utils.UnlockedAccountFlag,
    56  		utils.PasswordFileFlag,
    57  		utils.BootnodesFlag,
    58  		utils.BootnodesV4Flag,
    59  		utils.BootnodesV5Flag,
    60  		utils.DataDirFlag,
    61  		utils.KeyStoreDirFlag,
    62  		utils.NoUSBFlag,
    63  		utils.EthashCacheDirFlag,
    64  		utils.EthashCachesInMemoryFlag,
    65  		utils.EthashCachesOnDiskFlag,
    66  		utils.EthashDatasetDirFlag,
    67  		utils.EthashDatasetsInMemoryFlag,
    68  		utils.EthashDatasetsOnDiskFlag,
    69  		utils.TxPoolNoLocalsFlag,
    70  		utils.TxPoolPriceLimitFlag,
    71  		utils.TxPoolPriceBumpFlag,
    72  		utils.TxPoolAccountSlotsFlag,
    73  		utils.TxPoolGlobalSlotsFlag,
    74  		utils.TxPoolAccountQueueFlag,
    75  		utils.TxPoolGlobalQueueFlag,
    76  		utils.TxPoolLifetimeFlag,
    77  		utils.FastSyncFlag,
    78  		utils.LightModeFlag,
    79  		utils.SyncModeFlag,
    80  		utils.LightServFlag,
    81  		utils.LightPeersFlag,
    82  		utils.LightKDFFlag,
    83  		utils.CacheFlag,
    84  		utils.TrieCacheGenFlag,
    85  		utils.ListenPortFlag,
    86  		utils.MaxPeersFlag,
    87  		utils.MaxPendingPeersFlag,
    88  		utils.EtherbaseFlag,
    89  		utils.GasPriceFlag,
    90  		utils.MinerThreadsFlag,
    91  		utils.MiningEnabledFlag,
    92  		utils.TargetGasLimitFlag,
    93  		utils.NATFlag,
    94  		utils.NoDiscoverFlag,
    95  		utils.DiscoveryV5Flag,
    96  		utils.NetrestrictFlag,
    97  		utils.NodeKeyFileFlag,
    98  		utils.NodeKeyHexFlag,
    99  		utils.DevModeFlag,
   100  		utils.TestnetFlag,
   101  		utils.RinkebyFlag,
   102  		utils.VMEnableDebugFlag,
   103  		utils.NetworkIdFlag,
   104  		utils.RPCCORSDomainFlag,
   105  		utils.EthStatsURLFlag,
   106  		utils.MetricsEnabledFlag,
   107  		utils.FakePoWFlag,
   108  		utils.NoCompactionFlag,
   109  		utils.GpoBlocksFlag,
   110  		utils.GpoPercentileFlag,
   111  		utils.ExtraDataFlag,
   112  		configFileFlag,
   113  	}
   114  
   115  	rpcFlags = []cli.Flag{
   116  		utils.RPCEnabledFlag,
   117  		utils.RPCListenAddrFlag,
   118  		utils.RPCPortFlag,
   119  		utils.RPCApiFlag,
   120  		utils.WSEnabledFlag,
   121  		utils.WSListenAddrFlag,
   122  		utils.WSPortFlag,
   123  		utils.WSApiFlag,
   124  		utils.WSAllowedOriginsFlag,
   125  		utils.IPCDisabledFlag,
   126  		utils.IPCPathFlag,
   127  	}
   128  
   129  	whisperFlags = []cli.Flag{
   130  		utils.WhisperEnabledFlag,
   131  		utils.WhisperMaxMessageSizeFlag,
   132  		utils.WhisperMinPOWFlag,
   133  	}
   134  )
   135  
   136  func init() {
   137  	// Initialize the CLI app and start Geth
   138  	app.Action = geth
   139  	app.HideVersion = true // we have a command to print the version
   140  	app.Copyright = "Copyright 2013-2017 The go-ethereum Authors"
   141  	app.Commands = []cli.Command{
   142  		// See chaincmd.go:
   143  		initCommand,
   144  		importCommand,
   145  		exportCommand,
   146  		removedbCommand,
   147  		dumpCommand,
   148  		// See monitorcmd.go:
   149  		monitorCommand,
   150  		// See accountcmd.go:
   151  		accountCommand,
   152  		walletCommand,
   153  		// See consolecmd.go:
   154  		consoleCommand,
   155  		attachCommand,
   156  		javascriptCommand,
   157  		// See misccmd.go:
   158  		makedagCommand,
   159  		versionCommand,
   160  		bugCommand,
   161  		licenseCommand,
   162  		// See config.go
   163  		dumpConfigCommand,
   164  	}
   165  
   166  	app.Flags = append(app.Flags, nodeFlags...)
   167  	app.Flags = append(app.Flags, rpcFlags...)
   168  	app.Flags = append(app.Flags, consoleFlags...)
   169  	app.Flags = append(app.Flags, debug.Flags...)
   170  	app.Flags = append(app.Flags, whisperFlags...)
   171  
   172  	app.Before = func(ctx *cli.Context) error {
   173  		runtime.GOMAXPROCS(runtime.NumCPU())
   174  		if err := debug.Setup(ctx); err != nil {
   175  			return err
   176  		}
   177  		// Start system runtime metrics collection
   178  		go metrics.CollectProcessMetrics(3 * time.Second)
   179  
   180  		utils.SetupNetwork(ctx)
   181  		return nil
   182  	}
   183  
   184  	app.After = func(ctx *cli.Context) error {
   185  		debug.Exit()
   186  		console.Stdin.Close() // Resets terminal mode.
   187  		return nil
   188  	}
   189  }
   190  
   191  func main() {
   192  	if err := app.Run(os.Args); err != nil {
   193  		fmt.Fprintln(os.Stderr, err)
   194  		os.Exit(1)
   195  	}
   196  }
   197  
   198  // geth is the main entry point into the system if no special subcommand is ran.
   199  // It creates a default node based on the command line arguments and runs it in
   200  // blocking mode, waiting for it to be shut down.
   201  func geth(ctx *cli.Context) error {
   202  	node := makeFullNode(ctx)
   203  	startNode(ctx, node)
   204  	node.Wait()
   205  	return nil
   206  }
   207  
   208  // startNode boots up the system node and all registered protocols, after which
   209  // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
   210  // miner.
   211  func startNode(ctx *cli.Context, stack *node.Node) {
   212  	// Start up the node itself
   213  	utils.StartNode(stack)
   214  
   215  	// Unlock any account specifically requested
   216  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   217  
   218  	passwords := utils.MakePasswordList(ctx)
   219  	unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
   220  	for i, account := range unlocks {
   221  		if trimmed := strings.TrimSpace(account); trimmed != "" {
   222  			unlockAccount(ctx, ks, trimmed, i, passwords)
   223  		}
   224  	}
   225  	// Register wallet event handlers to open and auto-derive wallets
   226  	events := make(chan accounts.WalletEvent, 16)
   227  	stack.AccountManager().Subscribe(events)
   228  
   229  	go func() {
   230  		// Create an chain state reader for self-derivation
   231  		rpcClient, err := stack.Attach()
   232  		if err != nil {
   233  			utils.Fatalf("Failed to attach to self: %v", err)
   234  		}
   235  		stateReader := ethclient.NewClient(rpcClient)
   236  
   237  		// Open and self derive any wallets already attached
   238  		for _, wallet := range stack.AccountManager().Wallets() {
   239  			if err := wallet.Open(""); err != nil {
   240  				log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
   241  			} else {
   242  				wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
   243  			}
   244  		}
   245  		// Listen for wallet event till termination
   246  		for event := range events {
   247  			if event.Arrive {
   248  				if err := event.Wallet.Open(""); err != nil {
   249  					log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
   250  				} else {
   251  					log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", event.Wallet.Status())
   252  					event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
   253  				}
   254  			} else {
   255  				log.Info("Old wallet dropped", "url", event.Wallet.URL())
   256  				event.Wallet.Close()
   257  			}
   258  		}
   259  	}()
   260  	// Start auxiliary services if enabled
   261  	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
   262  		// Mining only makes sense if a full Ethereum node is running
   263  		var ethereum *eth.Ethereum
   264  		if err := stack.Service(&ethereum); err != nil {
   265  			utils.Fatalf("ethereum service not running: %v", err)
   266  		}
   267  		// Use a reduced number of threads if requested
   268  		if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > 0 {
   269  			type threaded interface {
   270  				SetThreads(threads int)
   271  			}
   272  			if th, ok := ethereum.Engine().(threaded); ok {
   273  				th.SetThreads(threads)
   274  			}
   275  		}
   276  		// Set the gas price to the limits from the CLI and start mining
   277  		ethereum.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name))
   278  		if err := ethereum.StartMining(true); err != nil {
   279  			utils.Fatalf("Failed to start mining: %v", err)
   280  		}
   281  	}
   282  }