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