github.com/bamzi/go-ethereum@v1.6.7-0.20170704111104-138f26c93af1/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.DevModeFlag,
    99  		utils.TestnetFlag,
   100  		utils.RinkebyFlag,
   101  		utils.VMEnableDebugFlag,
   102  		utils.NetworkIdFlag,
   103  		utils.RPCCORSDomainFlag,
   104  		utils.EthStatsURLFlag,
   105  		utils.MetricsEnabledFlag,
   106  		utils.FakePoWFlag,
   107  		utils.NoCompactionFlag,
   108  		utils.GpoBlocksFlag,
   109  		utils.GpoPercentileFlag,
   110  		utils.ExtraDataFlag,
   111  		configFileFlag,
   112  	}
   113  
   114  	rpcFlags = []cli.Flag{
   115  		utils.RPCEnabledFlag,
   116  		utils.RPCListenAddrFlag,
   117  		utils.RPCPortFlag,
   118  		utils.RPCApiFlag,
   119  		utils.WSEnabledFlag,
   120  		utils.WSListenAddrFlag,
   121  		utils.WSPortFlag,
   122  		utils.WSApiFlag,
   123  		utils.WSAllowedOriginsFlag,
   124  		utils.IPCDisabledFlag,
   125  		utils.IPCPathFlag,
   126  	}
   127  
   128  	whisperFlags = []cli.Flag{
   129  		utils.WhisperEnabledFlag,
   130  		utils.WhisperMaxMessageSizeFlag,
   131  		utils.WhisperMinPOWFlag,
   132  	}
   133  )
   134  
   135  func init() {
   136  	// Initialize the CLI app and start Geth
   137  	app.Action = geth
   138  	app.HideVersion = true // we have a command to print the version
   139  	app.Copyright = "Copyright 2013-2017 The go-ethereum Authors"
   140  	app.Commands = []cli.Command{
   141  		// See chaincmd.go:
   142  		initCommand,
   143  		importCommand,
   144  		exportCommand,
   145  		removedbCommand,
   146  		dumpCommand,
   147  		// See monitorcmd.go:
   148  		monitorCommand,
   149  		// See accountcmd.go:
   150  		accountCommand,
   151  		walletCommand,
   152  		// See consolecmd.go:
   153  		consoleCommand,
   154  		attachCommand,
   155  		javascriptCommand,
   156  		// See misccmd.go:
   157  		makedagCommand,
   158  		versionCommand,
   159  		bugCommand,
   160  		licenseCommand,
   161  		// See config.go
   162  		dumpConfigCommand,
   163  	}
   164  
   165  	app.Flags = append(app.Flags, nodeFlags...)
   166  	app.Flags = append(app.Flags, rpcFlags...)
   167  	app.Flags = append(app.Flags, consoleFlags...)
   168  	app.Flags = append(app.Flags, debug.Flags...)
   169  	app.Flags = append(app.Flags, whisperFlags...)
   170  
   171  	app.Before = func(ctx *cli.Context) error {
   172  		runtime.GOMAXPROCS(runtime.NumCPU())
   173  		if err := debug.Setup(ctx); err != nil {
   174  			return err
   175  		}
   176  		// Start system runtime metrics collection
   177  		go metrics.CollectProcessMetrics(3 * time.Second)
   178  
   179  		utils.SetupNetwork(ctx)
   180  		return nil
   181  	}
   182  
   183  	app.After = func(ctx *cli.Context) error {
   184  		debug.Exit()
   185  		console.Stdin.Close() // Resets terminal mode.
   186  		return nil
   187  	}
   188  }
   189  
   190  func main() {
   191  	if err := app.Run(os.Args); err != nil {
   192  		fmt.Fprintln(os.Stderr, err)
   193  		os.Exit(1)
   194  	}
   195  }
   196  
   197  // geth is the main entry point into the system if no special subcommand is ran.
   198  // It creates a default node based on the command line arguments and runs it in
   199  // blocking mode, waiting for it to be shut down.
   200  func geth(ctx *cli.Context) error {
   201  	node := makeFullNode(ctx)
   202  	startNode(ctx, node)
   203  	node.Wait()
   204  	return nil
   205  }
   206  
   207  // startNode boots up the system node and all registered protocols, after which
   208  // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
   209  // miner.
   210  func startNode(ctx *cli.Context, stack *node.Node) {
   211  	// Start up the node itself
   212  	utils.StartNode(stack)
   213  
   214  	// Unlock any account specifically requested
   215  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   216  
   217  	passwords := utils.MakePasswordList(ctx)
   218  	unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
   219  	for i, account := range unlocks {
   220  		if trimmed := strings.TrimSpace(account); trimmed != "" {
   221  			unlockAccount(ctx, ks, trimmed, i, passwords)
   222  		}
   223  	}
   224  	// Register wallet event handlers to open and auto-derive wallets
   225  	events := make(chan accounts.WalletEvent, 16)
   226  	stack.AccountManager().Subscribe(events)
   227  
   228  	go func() {
   229  		// Create an chain state reader for self-derivation
   230  		rpcClient, err := stack.Attach()
   231  		if err != nil {
   232  			utils.Fatalf("Failed to attach to self: %v", err)
   233  		}
   234  		stateReader := ethclient.NewClient(rpcClient)
   235  
   236  		// Open and self derive any wallets already attached
   237  		for _, wallet := range stack.AccountManager().Wallets() {
   238  			if err := wallet.Open(""); err != nil {
   239  				log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
   240  			} else {
   241  				wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
   242  			}
   243  		}
   244  		// Listen for wallet event till termination
   245  		for event := range events {
   246  			if event.Arrive {
   247  				if err := event.Wallet.Open(""); err != nil {
   248  					log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
   249  				} else {
   250  					log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", event.Wallet.Status())
   251  					event.Wallet.SelfDerive(accounts.DefaultBaseDerivationPath, stateReader)
   252  				}
   253  			} else {
   254  				log.Info("Old wallet dropped", "url", event.Wallet.URL())
   255  				event.Wallet.Close()
   256  			}
   257  		}
   258  	}()
   259  	// Start auxiliary services if enabled
   260  	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) {
   261  		// Mining only makes sense if a full Ethereum node is running
   262  		var ethereum *eth.Ethereum
   263  		if err := stack.Service(&ethereum); err != nil {
   264  			utils.Fatalf("ethereum service not running: %v", err)
   265  		}
   266  		// Use a reduced number of threads if requested
   267  		if threads := ctx.GlobalInt(utils.MinerThreadsFlag.Name); threads > 0 {
   268  			type threaded interface {
   269  				SetThreads(threads int)
   270  			}
   271  			if th, ok := ethereum.Engine().(threaded); ok {
   272  				th.SetThreads(threads)
   273  			}
   274  		}
   275  		// Set the gas price to the limits from the CLI and start mining
   276  		ethereum.TxPool().SetGasPrice(utils.GlobalBig(ctx, utils.GasPriceFlag.Name))
   277  		if err := ethereum.StartMining(true); err != nil {
   278  			utils.Fatalf("Failed to start mining: %v", err)
   279  		}
   280  	}
   281  }