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