github.com/Elemental-core/elementalcore@v0.0.0-20191206075037-63891242267a/cmd/geth/main.go (about)

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