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(ðereum); 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 }