github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/cmd/geth/main.go (about)

     1  
     2  //此源码被清华学神尹成大魔王专业翻译分析并修改
     3  //尹成QQ77025077
     4  //尹成微信18510341407
     5  //尹成所在QQ群721929980
     6  //尹成邮箱 yinc13@mails.tsinghua.edu.cn
     7  //尹成毕业于清华大学,微软区块链领域全球最有价值专家
     8  //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620
     9  //版权所有2014 Go Ethereum作者
    10  //此文件是Go以太坊的一部分。
    11  //
    12  //Go以太坊是免费软件:您可以重新发布和/或修改它
    13  //根据GNU通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //Go以太坊的分布希望它会有用,
    18  //但没有任何保证;甚至没有
    19  //适销性或特定用途的适用性。见
    20  //GNU通用公共许可证了解更多详细信息。
    21  //
    22  //你应该已经收到一份GNU通用公共许可证的副本
    23  //一起去以太坊吧。如果没有,请参见<http://www.gnu.org/licenses/>。
    24  
    25  //geth是以太坊的官方命令行客户端。
    26  package main
    27  
    28  import (
    29  	"fmt"
    30  	"math"
    31  	"os"
    32  	"runtime"
    33  	godebug "runtime/debug"
    34  	"sort"
    35  	"strconv"
    36  	"strings"
    37  	"time"
    38  
    39  	"github.com/elastic/gosigar"
    40  	"github.com/ethereum/go-ethereum/accounts"
    41  	"github.com/ethereum/go-ethereum/accounts/keystore"
    42  	"github.com/ethereum/go-ethereum/cmd/utils"
    43  	"github.com/ethereum/go-ethereum/console"
    44  	"github.com/ethereum/go-ethereum/eth"
    45  	"github.com/ethereum/go-ethereum/ethclient"
    46  	"github.com/ethereum/go-ethereum/internal/debug"
    47  	"github.com/ethereum/go-ethereum/log"
    48  	"github.com/ethereum/go-ethereum/metrics"
    49  	"github.com/ethereum/go-ethereum/node"
    50  	"gopkg.in/urfave/cli.v1"
    51  )
    52  
    53  const (
    54  clientIdentifier = "geth" //要通过网络进行广告的客户端标识符
    55  )
    56  
    57  var (
    58  //git sha1提交发布的哈希(通过链接器标志设置)
    59  	gitCommit = ""
    60  //保存所有命令和标志的应用程序。
    61  	app = utils.NewApp(gitCommit, "the go-ethereum command line interface")
    62  //配置节点的标志
    63  	nodeFlags = []cli.Flag{
    64  		utils.IdentityFlag,
    65  		utils.UnlockedAccountFlag,
    66  		utils.PasswordFileFlag,
    67  		utils.BootnodesFlag,
    68  		utils.BootnodesV4Flag,
    69  		utils.BootnodesV5Flag,
    70  		utils.DataDirFlag,
    71  		utils.KeyStoreDirFlag,
    72  		utils.NoUSBFlag,
    73  		utils.DashboardEnabledFlag,
    74  		utils.DashboardAddrFlag,
    75  		utils.DashboardPortFlag,
    76  		utils.DashboardRefreshFlag,
    77  		utils.EthashCacheDirFlag,
    78  		utils.EthashCachesInMemoryFlag,
    79  		utils.EthashCachesOnDiskFlag,
    80  		utils.EthashDatasetDirFlag,
    81  		utils.EthashDatasetsInMemoryFlag,
    82  		utils.EthashDatasetsOnDiskFlag,
    83  		utils.TxPoolLocalsFlag,
    84  		utils.TxPoolNoLocalsFlag,
    85  		utils.TxPoolJournalFlag,
    86  		utils.TxPoolRejournalFlag,
    87  		utils.TxPoolPriceLimitFlag,
    88  		utils.TxPoolPriceBumpFlag,
    89  		utils.TxPoolAccountSlotsFlag,
    90  		utils.TxPoolGlobalSlotsFlag,
    91  		utils.TxPoolAccountQueueFlag,
    92  		utils.TxPoolGlobalQueueFlag,
    93  		utils.TxPoolLifetimeFlag,
    94  		utils.SyncModeFlag,
    95  		utils.GCModeFlag,
    96  		utils.LightServFlag,
    97  		utils.LightPeersFlag,
    98  		utils.LightKDFFlag,
    99  		utils.CacheFlag,
   100  		utils.CacheDatabaseFlag,
   101  		utils.CacheGCFlag,
   102  		utils.TrieCacheGenFlag,
   103  		utils.ListenPortFlag,
   104  		utils.MaxPeersFlag,
   105  		utils.MaxPendingPeersFlag,
   106  		utils.MiningEnabledFlag,
   107  		utils.MinerThreadsFlag,
   108  		utils.MinerLegacyThreadsFlag,
   109  		utils.MinerNotifyFlag,
   110  		utils.MinerGasTargetFlag,
   111  		utils.MinerLegacyGasTargetFlag,
   112  		utils.MinerGasPriceFlag,
   113  		utils.MinerLegacyGasPriceFlag,
   114  //utils.mineretherbaseflag(实用程序.mineretherbaseflag)
   115  		utils.MinerLegacyEtherbaseFlag,
   116  		utils.MinerExtraDataFlag,
   117  		utils.MinerLegacyExtraDataFlag,
   118  		utils.MinerRecommitIntervalFlag,
   119  		utils.NATFlag,
   120  		utils.NoDiscoverFlag,
   121  		utils.DiscoveryV5Flag,
   122  		utils.NetrestrictFlag,
   123  		utils.NodeKeyFileFlag,
   124  		utils.NodeKeyHexFlag,
   125  		utils.DeveloperFlag,
   126  		utils.DeveloperPeriodFlag,
   127  		utils.TestnetFlag,
   128  		utils.RinkebyFlag,
   129  		utils.VMEnableDebugFlag,
   130  		utils.NetworkIdFlag,
   131  		utils.RPCCORSDomainFlag,
   132  		utils.RPCVirtualHostsFlag,
   133  		utils.EthStatsURLFlag,
   134  		utils.MetricsEnabledFlag,
   135  		utils.FakePoWFlag,
   136  		utils.NoCompactionFlag,
   137  		utils.GpoBlocksFlag,
   138  		utils.GpoPercentileFlag,
   139  		configFileFlag,
   140  	}
   141  
   142  	rpcFlags = []cli.Flag{
   143  		utils.RPCEnabledFlag,
   144  		utils.RPCListenAddrFlag,
   145  		utils.RPCPortFlag,
   146  		utils.RPCApiFlag,
   147  		utils.WSEnabledFlag,
   148  		utils.WSListenAddrFlag,
   149  		utils.WSPortFlag,
   150  		utils.WSApiFlag,
   151  		utils.WSAllowedOriginsFlag,
   152  		utils.IPCDisabledFlag,
   153  		utils.IPCPathFlag,
   154  	}
   155  
   156  	whisperFlags = []cli.Flag{
   157  		utils.WhisperEnabledFlag,
   158  		utils.WhisperMaxMessageSizeFlag,
   159  		utils.WhisperMinPOWFlag,
   160  	}
   161  
   162  	metricsFlags = []cli.Flag{
   163  		utils.MetricsEnableInfluxDBFlag,
   164  		utils.MetricsInfluxDBEndpointFlag,
   165  		utils.MetricsInfluxDBDatabaseFlag,
   166  		utils.MetricsInfluxDBUsernameFlag,
   167  		utils.MetricsInfluxDBPasswordFlag,
   168  		utils.MetricsInfluxDBHostTagFlag,
   169  	}
   170  )
   171  
   172  func init() {
   173  //初始化cli应用程序并启动geth
   174  	app.Action = geth
   175  app.HideVersion = true //我们有打印版本的命令
   176  	app.Copyright = "Copyright 2013-2018 The go-ethereum Authors"
   177  	app.Commands = []cli.Command{
   178  //参见chainCmd.Go:
   179  		initCommand,
   180  		importCommand,
   181  		exportCommand,
   182  		importPreimagesCommand,
   183  		exportPreimagesCommand,
   184  		copydbCommand,
   185  		removedbCommand,
   186  		dumpCommand,
   187  //请参阅monitorCmd.go:
   188  		monitorCommand,
   189  //参见accountCmd.Go:
   190  		accountCommand,
   191  		walletCommand,
   192  //请参阅consoleCmd.Go:
   193  		consoleCommand,
   194  		attachCommand,
   195  		javascriptCommand,
   196  //参见MISCCM.Do:
   197  		makecacheCommand,
   198  		makedagCommand,
   199  		versionCommand,
   200  		bugCommand,
   201  		licenseCommand,
   202  //参见CONG.GO
   203  		dumpConfigCommand,
   204  	}
   205  	sort.Sort(cli.CommandsByName(app.Commands))
   206  
   207  	app.Flags = append(app.Flags, nodeFlags...)
   208  	app.Flags = append(app.Flags, rpcFlags...)
   209  	app.Flags = append(app.Flags, consoleFlags...)
   210  	app.Flags = append(app.Flags, debug.Flags...)
   211  	app.Flags = append(app.Flags, whisperFlags...)
   212  	app.Flags = append(app.Flags, metricsFlags...)
   213  
   214  	app.Before = func(ctx *cli.Context) error {
   215  		runtime.GOMAXPROCS(runtime.NumCPU())
   216  
   217  		logdir := ""
   218  		if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
   219  			logdir = (&node.Config{DataDir: utils.MakeDataDir(ctx)}).ResolvePath("logs")
   220  		}
   221  		if err := debug.Setup(ctx, logdir); err != nil {
   222  			return err
   223  		}
   224  //限制缓存容量并优化垃圾收集器
   225  		var mem gosigar.Mem
   226  		if err := mem.Get(); err == nil {
   227  			allowance := int(mem.Total / 1024 / 1024 / 3)
   228  			if cache := ctx.GlobalInt(utils.CacheFlag.Name); cache > allowance {
   229  				log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
   230  				ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(allowance))
   231  			}
   232  		}
   233  //确保go的gc忽略触发器百分比的数据库缓存
   234  		cache := ctx.GlobalInt(utils.CacheFlag.Name)
   235  		gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))
   236  
   237  		log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
   238  		godebug.SetGCPercent(int(gogc))
   239  
   240  //如果启用,则启动度量导出
   241  		utils.SetupMetrics(ctx)
   242  
   243  //启动系统运行时度量集合
   244  		go metrics.CollectProcessMetrics(3 * time.Second)
   245  
   246  		utils.SetupNetwork(ctx)
   247  		return nil
   248  	}
   249  
   250  	app.After = func(ctx *cli.Context) error {
   251  		debug.Exit()
   252  console.Stdin.Close() //重置终端模式。
   253  		return nil
   254  	}
   255  }
   256  
   257  func main() {
   258  	if err := app.Run(os.Args); err != nil {
   259  		fmt.Fprintln(os.Stderr, err)
   260  		os.Exit(1)
   261  	}
   262  }
   263  
   264  //如果没有运行特殊的子命令,geth是进入系统的主要入口点。
   265  //它基于命令行参数创建默认节点并在
   266  //阻塞模式,等待关闭。
   267  func geth(ctx *cli.Context) error {
   268  	if args := ctx.Args(); len(args) > 0 {
   269  		return fmt.Errorf("invalid command: %q", args[0])
   270  	}
   271  	node := makeFullNode(ctx)
   272  	startNode(ctx, node)
   273  	node.Wait()
   274  	return nil
   275  }
   276  
   277  //startnode启动系统节点和所有注册的协议,之后
   278  //它解锁所有请求的帐户,并启动RPC/IPC接口和
   279  //
   280  func startNode(ctx *cli.Context, stack *node.Node) {
   281  	debug.Memsize.Add("node", stack)
   282  
   283  //
   284  	utils.StartNode(stack)
   285  
   286  //
   287  	ks := stack.AccountManager().Backends(keystore.KeyStoreType)[0].(*keystore.KeyStore)
   288  
   289  	passwords := utils.MakePasswordList(ctx)
   290  	unlocks := strings.Split(ctx.GlobalString(utils.UnlockedAccountFlag.Name), ",")
   291  	for i, account := range unlocks {
   292  		if trimmed := strings.TrimSpace(account); trimmed != "" {
   293  			unlockAccount(ctx, ks, trimmed, i, passwords)
   294  		}
   295  	}
   296  //注册钱包事件处理程序以打开和自动派生钱包
   297  	events := make(chan accounts.WalletEvent, 16)
   298  	stack.AccountManager().Subscribe(events)
   299  
   300  	go func() {
   301  //创建用于自派生的链状态读取器
   302  		rpcClient, err := stack.Attach()
   303  		if err != nil {
   304  			utils.Fatalf("Failed to attach to self: %v", err)
   305  		}
   306  		stateReader := ethclient.NewClient(rpcClient)
   307  
   308  //打开所有已连接的钱包
   309  		for _, wallet := range stack.AccountManager().Wallets() {
   310  			if err := wallet.Open(""); err != nil {
   311  				log.Warn("Failed to open wallet", "url", wallet.URL(), "err", err)
   312  			}
   313  		}
   314  //听钱包事件直到终止
   315  		for event := range events {
   316  			switch event.Kind {
   317  			case accounts.WalletArrived:
   318  				if err := event.Wallet.Open(""); err != nil {
   319  					log.Warn("New wallet appeared, failed to open", "url", event.Wallet.URL(), "err", err)
   320  				}
   321  			case accounts.WalletOpened:
   322  				status, _ := event.Wallet.Status()
   323  				log.Info("New wallet appeared", "url", event.Wallet.URL(), "status", status)
   324  
   325  				derivationPath := accounts.DefaultBaseDerivationPath
   326  				if event.Wallet.URL().Scheme == "ledger" {
   327  					derivationPath = accounts.DefaultLedgerBaseDerivationPath
   328  				}
   329  				event.Wallet.SelfDerive(derivationPath, stateReader)
   330  
   331  			case accounts.WalletDropped:
   332  				log.Info("Old wallet dropped", "url", event.Wallet.URL())
   333  				event.Wallet.Close()
   334  			}
   335  		}
   336  	}()
   337  //启动辅助服务(如果启用)
   338  	if ctx.GlobalBool(utils.MiningEnabledFlag.Name) || ctx.GlobalBool(utils.DeveloperFlag.Name) {
   339  //只有当一个完整的以太坊节点正在运行时,挖掘才有意义。
   340  		if ctx.GlobalString(utils.SyncModeFlag.Name) == "light" {
   341  			utils.Fatalf("Light clients do not support mining")
   342  		}
   343  		var ethereum *eth.Ethereum
   344  		if err := stack.Service(&ethereum); err != nil {
   345  			utils.Fatalf("Ethereum service not running: %v", err)
   346  		}
   347  //如果请求,请使用减少的线程数
   348  		threads := ctx.GlobalInt(utils.MinerLegacyThreadsFlag.Name)
   349  		if ctx.GlobalIsSet(utils.MinerThreadsFlag.Name) {
   350  			threads = ctx.GlobalInt(utils.MinerThreadsFlag.Name)
   351  		}
   352  		if threads > 0 {
   353  			type threaded interface {
   354  				SetThreads(threads int)
   355  			}
   356  			if th, ok := ethereum.Engine().(threaded); ok {
   357  				th.SetThreads(threads)
   358  			}
   359  		}
   360  //将天然气价格设置为CLI的限制,然后开始开采。
   361  		gasprice := utils.GlobalBig(ctx, utils.MinerLegacyGasPriceFlag.Name)
   362  		if ctx.IsSet(utils.MinerGasPriceFlag.Name) {
   363  			gasprice = utils.GlobalBig(ctx, utils.MinerGasPriceFlag.Name)
   364  		}
   365  		ethereum.TxPool().SetGasPrice(gasprice)
   366  		if err := ethereum.StartMining(true); err != nil {
   367  			utils.Fatalf("Failed to start mining: %v", err)
   368  		}
   369  	}
   370  }