github.com/hyperion-hyn/go-ethereum@v2.4.0+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  	"errors"
    22  	"fmt"
    23  	"math"
    24  	"os"
    25  	godebug "runtime/debug"
    26  	"sort"
    27  	"strconv"
    28  	"strings"
    29  	"time"
    30  
    31  	"github.com/elastic/gosigar"
    32  	"github.com/ethereum/go-ethereum/accounts"
    33  	"github.com/ethereum/go-ethereum/accounts/keystore"
    34  	"github.com/ethereum/go-ethereum/cmd/utils"
    35  	"github.com/ethereum/go-ethereum/console"
    36  	"github.com/ethereum/go-ethereum/eth"
    37  	"github.com/ethereum/go-ethereum/ethclient"
    38  	"github.com/ethereum/go-ethereum/internal/debug"
    39  	"github.com/ethereum/go-ethereum/log"
    40  	"github.com/ethereum/go-ethereum/metrics"
    41  	"github.com/ethereum/go-ethereum/node"
    42  	"github.com/ethereum/go-ethereum/permission"
    43  	"gopkg.in/urfave/cli.v1"
    44  )
    45  
    46  const (
    47  	clientIdentifier = "geth" // Client identifier to advertise over the network
    48  )
    49  
    50  var (
    51  	// Git SHA1 commit hash of the release (set via linker flags)
    52  	gitCommit = ""
    53  	// The app that holds all commands and flags.
    54  	app = utils.NewApp(gitCommit, "the go-ethereum command line interface")
    55  	// flags that configure the node
    56  	nodeFlags = []cli.Flag{
    57  		utils.IdentityFlag,
    58  		utils.UnlockedAccountFlag,
    59  		utils.PasswordFileFlag,
    60  		utils.BootnodesFlag,
    61  		utils.BootnodesV4Flag,
    62  		utils.BootnodesV5Flag,
    63  		utils.DataDirFlag,
    64  		utils.KeyStoreDirFlag,
    65  		utils.NoUSBFlag,
    66  		utils.DashboardEnabledFlag,
    67  		utils.DashboardAddrFlag,
    68  		utils.DashboardPortFlag,
    69  		utils.DashboardRefreshFlag,
    70  		utils.EthashCacheDirFlag,
    71  		utils.EthashCachesInMemoryFlag,
    72  		utils.EthashCachesOnDiskFlag,
    73  		utils.EthashDatasetDirFlag,
    74  		utils.EthashDatasetsInMemoryFlag,
    75  		utils.EthashDatasetsOnDiskFlag,
    76  		utils.TxPoolLocalsFlag,
    77  		utils.TxPoolNoLocalsFlag,
    78  		utils.TxPoolJournalFlag,
    79  		utils.TxPoolRejournalFlag,
    80  		utils.TxPoolPriceLimitFlag,
    81  		utils.TxPoolPriceBumpFlag,
    82  		utils.TxPoolAccountSlotsFlag,
    83  		utils.TxPoolGlobalSlotsFlag,
    84  		utils.TxPoolAccountQueueFlag,
    85  		utils.TxPoolGlobalQueueFlag,
    86  		utils.TxPoolLifetimeFlag,
    87  		utils.SyncModeFlag,
    88  		utils.GCModeFlag,
    89  		utils.LightServFlag,
    90  		utils.LightPeersFlag,
    91  		utils.LightKDFFlag,
    92  		utils.CacheFlag,
    93  		utils.CacheDatabaseFlag,
    94  		utils.CacheGCFlag,
    95  		utils.TrieCacheGenFlag,
    96  		utils.ListenPortFlag,
    97  		utils.MaxPeersFlag,
    98  		utils.MaxPendingPeersFlag,
    99  		utils.MiningEnabledFlag,
   100  		utils.MinerThreadsFlag,
   101  		utils.MinerLegacyThreadsFlag,
   102  		utils.MinerNotifyFlag,
   103  		utils.MinerGasTargetFlag,
   104  		utils.MinerLegacyGasTargetFlag,
   105  		utils.MinerGasLimitFlag,
   106  		utils.MinerGasPriceFlag,
   107  		utils.MinerLegacyGasPriceFlag,
   108  		utils.MinerEtherbaseFlag,
   109  		utils.MinerLegacyEtherbaseFlag,
   110  		utils.MinerExtraDataFlag,
   111  		utils.MinerLegacyExtraDataFlag,
   112  		utils.MinerRecommitIntervalFlag,
   113  		utils.MinerNoVerfiyFlag,
   114  		utils.NATFlag,
   115  		utils.NoDiscoverFlag,
   116  		utils.DiscoveryV5Flag,
   117  		utils.NetrestrictFlag,
   118  		utils.NodeKeyFileFlag,
   119  		utils.NodeKeyHexFlag,
   120  		utils.DeveloperFlag,
   121  		utils.DeveloperPeriodFlag,
   122  		utils.TestnetFlag,
   123  		utils.RinkebyFlag,
   124  		utils.OttomanFlag,
   125  		utils.VMEnableDebugFlag,
   126  		utils.NetworkIdFlag,
   127  		utils.RPCCORSDomainFlag,
   128  		utils.RPCVirtualHostsFlag,
   129  		utils.EthStatsURLFlag,
   130  		utils.MetricsEnabledFlag,
   131  		utils.FakePoWFlag,
   132  		utils.NoCompactionFlag,
   133  		utils.GpoBlocksFlag,
   134  		utils.GpoPercentileFlag,
   135  		utils.EWASMInterpreterFlag,
   136  		utils.EVMInterpreterFlag,
   137  		configFileFlag,
   138  		// Quorum
   139  		utils.EnableNodePermissionFlag,
   140  		utils.RaftModeFlag,
   141  		utils.RaftBlockTimeFlag,
   142  		utils.RaftJoinExistingFlag,
   143  		utils.RaftPortFlag,
   144  		utils.RaftDNSEnabledFlag,
   145  		utils.EmitCheckpointsFlag,
   146  		utils.IstanbulRequestTimeoutFlag,
   147  		utils.IstanbulBlockPeriodFlag,
   148  		// End-Quorum
   149  	}
   150  
   151  	rpcFlags = []cli.Flag{
   152  		utils.RPCEnabledFlag,
   153  		utils.RPCListenAddrFlag,
   154  		utils.RPCPortFlag,
   155  		utils.RPCApiFlag,
   156  		utils.WSEnabledFlag,
   157  		utils.WSListenAddrFlag,
   158  		utils.WSPortFlag,
   159  		utils.WSApiFlag,
   160  		utils.WSAllowedOriginsFlag,
   161  		utils.IPCDisabledFlag,
   162  		utils.IPCPathFlag,
   163  	}
   164  
   165  	whisperFlags = []cli.Flag{
   166  		utils.WhisperEnabledFlag,
   167  		utils.WhisperMaxMessageSizeFlag,
   168  		utils.WhisperMinPOWFlag,
   169  		utils.WhisperRestrictConnectionBetweenLightClientsFlag,
   170  	}
   171  
   172  	metricsFlags = []cli.Flag{
   173  		utils.MetricsEnableInfluxDBFlag,
   174  		utils.MetricsInfluxDBEndpointFlag,
   175  		utils.MetricsInfluxDBDatabaseFlag,
   176  		utils.MetricsInfluxDBUsernameFlag,
   177  		utils.MetricsInfluxDBPasswordFlag,
   178  		utils.MetricsInfluxDBHostTagFlag,
   179  	}
   180  )
   181  
   182  func init() {
   183  	// Initialize the CLI app and start Geth
   184  	app.Action = geth
   185  	app.HideVersion = true // we have a command to print the version
   186  	app.Copyright = "Copyright 2013-2018 The go-ethereum Authors"
   187  	app.Commands = []cli.Command{
   188  		// See chaincmd.go:
   189  		initCommand,
   190  		importCommand,
   191  		exportCommand,
   192  		importPreimagesCommand,
   193  		exportPreimagesCommand,
   194  		copydbCommand,
   195  		removedbCommand,
   196  		dumpCommand,
   197  		// See monitorcmd.go:
   198  		monitorCommand,
   199  		// See accountcmd.go:
   200  		accountCommand,
   201  		walletCommand,
   202  		// See consolecmd.go:
   203  		consoleCommand,
   204  		attachCommand,
   205  		javascriptCommand,
   206  		// See misccmd.go:
   207  		makecacheCommand,
   208  		makedagCommand,
   209  		versionCommand,
   210  		bugCommand,
   211  		licenseCommand,
   212  		// See config.go
   213  		dumpConfigCommand,
   214  	}
   215  	sort.Sort(cli.CommandsByName(app.Commands))
   216  
   217  	app.Flags = append(app.Flags, nodeFlags...)
   218  	app.Flags = append(app.Flags, rpcFlags...)
   219  	app.Flags = append(app.Flags, consoleFlags...)
   220  	app.Flags = append(app.Flags, debug.Flags...)
   221  	app.Flags = append(app.Flags, whisperFlags...)
   222  	app.Flags = append(app.Flags, metricsFlags...)
   223  
   224  	app.Before = func(ctx *cli.Context) error {
   225  		logdir := ""
   226  		if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
   227  			logdir = (&node.Config{DataDir: utils.MakeDataDir(ctx)}).ResolvePath("logs")
   228  		}
   229  		if err := debug.Setup(ctx, logdir); err != nil {
   230  			return err
   231  		}
   232  		// Cap the cache allowance and tune the garbage collector
   233  		var mem gosigar.Mem
   234  		if err := mem.Get(); err == nil {
   235  			allowance := int(mem.Total / 1024 / 1024 / 3)
   236  			if cache := ctx.GlobalInt(utils.CacheFlag.Name); cache > allowance {
   237  				log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
   238  				ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(allowance))
   239  			}
   240  		}
   241  		// Ensure Go's GC ignores the database cache for trigger percentage
   242  		cache := ctx.GlobalInt(utils.CacheFlag.Name)
   243  		gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))
   244  
   245  		log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
   246  		godebug.SetGCPercent(int(gogc))
   247  
   248  		// Start metrics export if enabled
   249  		utils.SetupMetrics(ctx)
   250  
   251  		// Start system runtime metrics collection
   252  		go metrics.CollectProcessMetrics(3 * time.Second)
   253  
   254  		return nil
   255  	}
   256  
   257  	app.After = func(ctx *cli.Context) error {
   258  		debug.Exit()
   259  		console.Stdin.Close() // Resets terminal mode.
   260  		return nil
   261  	}
   262  }
   263  
   264  func main() {
   265  	if err := app.Run(os.Args); err != nil {
   266  		fmt.Fprintln(os.Stderr, err)
   267  		os.Exit(1)
   268  	}
   269  }
   270  
   271  // geth is the main entry point into the system if no special subcommand is ran.
   272  // It creates a default node based on the command line arguments and runs it in
   273  // blocking mode, waiting for it to be shut down.
   274  func geth(ctx *cli.Context) error {
   275  	if args := ctx.Args(); len(args) > 0 {
   276  		return fmt.Errorf("invalid command: %q", args[0])
   277  	}
   278  
   279  	if !quorumValidatePrivateTransactionManager() {
   280  		return errors.New("the PRIVATE_CONFIG environment variable must be specified for Quorum")
   281  	}
   282  
   283  	node := makeFullNode(ctx)
   284  	startNode(ctx, node)
   285  
   286  	// Check if a valid consensus is used
   287  	quorumValidateConsensus(node, ctx.GlobalBool(utils.RaftModeFlag.Name))
   288  
   289  	node.Wait()
   290  	return nil
   291  }
   292  
   293  // startNode boots up the system node and all registered protocols, after which
   294  // it unlocks any requested accounts, and starts the RPC/IPC interfaces and the
   295  // miner.
   296  func startNode(ctx *cli.Context, stack *node.Node) {
   297  	log.DoEmitCheckpoints = ctx.GlobalBool(utils.EmitCheckpointsFlag.Name)
   298  	debug.Memsize.Add("node", stack)
   299  
   300  	// Start up the node itself
   301  	utils.StartNode(stack)
   302  
   303  	// Unlock any account specifically requested
   304  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   305  
   306  	passwords := utils.MakePasswordList(ctx)
   307  	unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
   308  	for i, account := range unlocks {
   309  		if trimmed := strings.TrimSpace(account); trimmed != "" {
   310  			unlockAccount(ctx, ks, trimmed, i, passwords)
   311  		}
   312  	}
   313  	// Register wallet event handlers to open and auto-derive wallets
   314  	events := make(chan accounts.WalletEvent, 16)
   315  	stack.AccountManager().Subscribe(events)
   316  
   317  	go func() {
   318  		// Create a chain state reader for self-derivation
   319  		rpcClient, err := stack.Attach()
   320  		if err != nil {
   321  			utils.Fatalf("Failed to attach to self: %v", err)
   322  		}
   323  		stateReader := ethclient.NewClient(rpcClient)
   324  
   325  		// Open any wallets already attached
   326  		for _, wallet := range stack.AccountManager().Wallets() {
   327  			if err := wallet.Open(""); err != nil {
   328  				log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
   329  			}
   330  		}
   331  		// Listen for wallet event till termination
   332  		for event := range events {
   333  			switch event.Kind {
   334  			case accounts.WalletArrived:
   335  				if err := event.Wallet.Open(""); err != nil {
   336  					log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
   337  				}
   338  			case accounts.WalletOpened:
   339  				status, _ := event.Wallet.Status()
   340  				log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status)
   341  
   342  				derivationPath := accounts.DefaultBaseDerivationPath
   343  				if event.Wallet.URL().Scheme == "ledger" {
   344  					derivationPath = accounts.DefaultLedgerBaseDerivationPath
   345  				}
   346  				event.Wallet.SelfDerive(derivationPath, stateReader)
   347  
   348  			case accounts.WalletDropped:
   349  				log.Info("Old wallet dropped", "url", event.Wallet.URL())
   350  				event.Wallet.Close()
   351  			}
   352  		}
   353  	}()
   354  
   355  	// Quorum
   356  	//
   357  	// checking if permissions is enabled and staring the permissions service
   358  	if stack.IsPermissionEnabled() {
   359  		var permissionService *permission.PermissionCtrl
   360  		if err := stack.Service(&permissionService); err != nil {
   361  			utils.Fatalf("Permission service not runnning: %v", err)
   362  		}
   363  		if err := permissionService.AfterStart(); err != nil {
   364  			utils.Fatalf("Permission service post construct failure: %v", err)
   365  		}
   366  	}
   367  
   368  	// Start auxiliary services if enabled
   369  	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) {
   370  		// Mining only makes sense if a full Ethereum node is running
   371  		if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
   372  			utils.Fatalf("Light clients do not support mining")
   373  		}
   374  		var ethereum *eth.Ethereum
   375  		if err := stack.Service(&ethereum); err != nil {
   376  			utils.Fatalf("Ethereum service not running: %v", err)
   377  		}
   378  		// Set the gas price to the limits from the CLI and start mining
   379  		gasprice := utils.GlobalBig(ctx, utils.MinerLegacyGasPriceFlag.Name)
   380  		if ctx.IsSet(utils.MinerGasPriceFlag.Name) {
   381  			gasprice = utils.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
   382  		}
   383  		ethereum.TxPool().SetGasPrice(gasprice)
   384  
   385  		threads := ctx.GlobalInt(utils.MinerLegacyThreadsFlag.Name)
   386  		if ctx.GlobalIsSet(utils.MinerThreadsFlag.Name) {
   387  			threads = ctx.GlobalInt(utils.MinerThreadsFlag.Name)
   388  		}
   389  		if err := ethereum.StartMining(threads); err != nil {
   390  			utils.Fatalf("Failed to start mining: %v", err)
   391  		}
   392  	}
   393  
   394  }