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