github.com/alanchchen/go-ethereum@v1.6.6-0.20170601190819-6171d01b1195/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.TxPoolPriceLimitFlag,
    70  		utils.TxPoolPriceBumpFlag,
    71  		utils.TxPoolAccountSlotsFlag,
    72  		utils.TxPoolGlobalSlotsFlag,
    73  		utils.TxPoolAccountQueueFlag,
    74  		utils.TxPoolGlobalQueueFlag,
    75  		utils.TxPoolLifetimeFlag,
    76  		utils.FastSyncFlag,
    77  		utils.LightModeFlag,
    78  		utils.SyncModeFlag,
    79  		utils.LightServFlag,
    80  		utils.LightPeersFlag,
    81  		utils.LightKDFFlag,
    82  		utils.CacheFlag,
    83  		utils.TrieCacheGenFlag,
    84  		utils.ListenPortFlag,
    85  		utils.MaxPeersFlag,
    86  		utils.MaxPendingPeersFlag,
    87  		utils.EtherbaseFlag,
    88  		utils.GasPriceFlag,
    89  		utils.MinerThreadsFlag,
    90  		utils.MiningEnabledFlag,
    91  		utils.TargetGasLimitFlag,
    92  		utils.NATFlag,
    93  		utils.NoDiscoverFlag,
    94  		utils.DiscoveryV5Flag,
    95  		utils.NetrestrictFlag,
    96  		utils.NodeKeyFileFlag,
    97  		utils.NodeKeyHexFlag,
    98  		utils.WhisperEnabledFlag,
    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  
   130  func init() {
   131  	// Initialize the CLI app and start Geth
   132  	app.Action = geth
   133  	app.HideVersion = true // we have a command to print the version
   134  	app.Copyright = "Copyright 2013-2017 The go-ethereum Authors"
   135  	app.Commands = []cli.Command{
   136  		// See chaincmd.go:
   137  		initCommand,
   138  		importCommand,
   139  		exportCommand,
   140  		removedbCommand,
   141  		dumpCommand,
   142  		// See monitorcmd.go:
   143  		monitorCommand,
   144  		// See accountcmd.go:
   145  		accountCommand,
   146  		walletCommand,
   147  		// See consolecmd.go:
   148  		consoleCommand,
   149  		attachCommand,
   150  		javascriptCommand,
   151  		// See misccmd.go:
   152  		makedagCommand,
   153  		versionCommand,
   154  		bugCommand,
   155  		licenseCommand,
   156  		// See config.go
   157  		dumpConfigCommand,
   158  	}
   159  
   160  	app.Flags = append(app.Flags, nodeFlags...)
   161  	app.Flags = append(app.Flags, rpcFlags...)
   162  	app.Flags = append(app.Flags, consoleFlags...)
   163  	app.Flags = append(app.Flags, debug.Flags...)
   164  
   165  	app.Before = func(ctx *cli.Context) error {
   166  		runtime.GOMAXPROCS(runtime.NumCPU())
   167  		if err := debug.Setup(ctx); err != nil {
   168  			return err
   169  		}
   170  		// Start system runtime metrics collection
   171  		go metrics.CollectProcessMetrics(3 * time.Second)
   172  
   173  		utils.SetupNetwork(ctx)
   174  		return nil
   175  	}
   176  
   177  	app.After = func(ctx *cli.Context) error {
   178  		debug.Exit()
   179  		console.Stdin.Close() // Resets terminal mode.
   180  		return nil
   181  	}
   182  }
   183  
   184  func main() {
   185  	if err := app.Run(os.Args); err != nil {
   186  		fmt.Fprintln(os.Stderr, err)
   187  		os.Exit(1)
   188  	}
   189  }
   190  
   191  // geth is the main entry point into the system if no special subcommand is ran.
   192  // It creates a default node based on the command line arguments and runs it in
   193  // blocking mode, waiting for it to be shut down.
   194  func geth(ctx *cli.Context) error {
   195  	node := makeFullNode(ctx)
   196  	startNode(ctx, node)
   197  	node.Wait()
   198  	return nil
   199  }
   200  
   201  // startNode boots up the system node and all registered protocols, after which
   202  // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
   203  // miner.
   204  func startNode(ctx *cli.Context, stack *node.Node) {
   205  	// Start up the node itself
   206  	utils.StartNode(stack)
   207  
   208  	// Unlock any account specifically requested
   209  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   210  
   211  	passwords := utils.MakePasswordList(ctx)
   212  	unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
   213  	for i, account := range unlocks {
   214  		if trimmed := strings.TrimSpace(account); trimmed != "" {
   215  			unlockAccount(ctx, ks, trimmed, i, passwords)
   216  		}
   217  	}
   218  	// Register wallet event handlers to open and auto-derive wallets
   219  	events := make(chan accounts.WalletEvent, 16)
   220  	stack.AccountManager().Subscribe(events)
   221  
   222  	go func() {
   223  		// Create an chain state reader for self-derivation
   224  		rpcClient, err := stack.Attach()
   225  		if err != nil {
   226  			utils.Fatalf("Failed to attach to self: %v", err)
   227  		}
   228  		stateReader := ethclient.NewClient(rpcClient)
   229  
   230  		// Open and self derive any wallets already attached
   231  		for _, wallet := range stack.AccountManager().Wallets() {
   232  			if err := wallet.Open(""); err != nil {
   233  				log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
   234  			} else {
   235  				wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
   236  			}
   237  		}
   238  		// Listen for wallet event till termination
   239  		for event := range events {
   240  			if event.Arrive {
   241  				if err := event.Wallet.Open(""); err != nil {
   242  					log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
   243  				} else {
   244  					log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", event.Wallet.Status())
   245  					event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
   246  				}
   247  			} else {
   248  				log.Info("Old wallet dropped", "url", event.Wallet.URL())
   249  				event.Wallet.Close()
   250  			}
   251  		}
   252  	}()
   253  	// Start auxiliary services if enabled
   254  	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
   255  		var ethereum *eth.Ethereum
   256  		if err := stack.Service(&ethereum); err != nil {
   257  			utils.Fatalf("ethereum service not running: %v", err)
   258  		}
   259  		if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > 0 {
   260  			type threaded interface {
   261  				SetThreads(threads int)
   262  			}
   263  			if th, ok := ethereum.Engine().(threaded); ok {
   264  				th.SetThreads(threads)
   265  			}
   266  		}
   267  		if err := ethereum.StartMining(true); err != nil {
   268  			utils.Fatalf("Failed to start mining: %v", err)
   269  		}
   270  	}
   271  }