以太坊源码学习(二)geth启动

geth命令

cmd/main/main.go

func main() {
   if err := app.Run(os.Args); err != nil { // app是三方包,用于接收客户端命令
      fmt.Fprintln(os.Stderr, err)
      os.Exit(1)
   }
}
func init() { // init方法先于main方法执行
   // Initialize the CLI app and start Geth
   app.Action = geth // 设置的geth,会自行下面的geth方法
   app.HideVersion = true // we have a command to print the version
   app.Copyright = "Copyright 2013-2018 The go-ethereum Authors"
   app.Commands = []cli.Command{ // 支持的子命令
      // See chaincmd.go:
      initCommand,// 客户端init命令 初始化创始区块
      importCommand,
      exportCommand,
      importPreimagesCommand,
      exportPreimagesCommand,
      copydbCommand,
      removedbCommand,
      dumpCommand,
      // See monitorcmd.go:
      monitorCommand,
      // See accountcmd.go:
      accountCommand,
      walletCommand,
      // See consolecmd.go:
      consoleCommand,
      attachCommand,
      javascriptCommand,
      // See misccmd.go:
      makecacheCommand,
      makedagCommand,
      versionCommand,
      bugCommand,
      licenseCommand,
      // See config.go
      dumpConfigCommand,
   }
   sort.Sort(cli.CommandsByName(app.Commands)) //命令排序

   app.Flags = append(app.Flags, nodeFlags...)
   app.Flags = append(app.Flags, rpcFlags...)
   app.Flags = append(app.Flags, consoleFlags...)
   app.Flags = append(app.Flags, debug.Flags...)
   app.Flags = append(app.Flags, whisperFlags...)
   app.Flags = append(app.Flags, metricsFlags...) //追加var变量中定义的Flags

   app.Before = func(ctx *cli.Context) error {
      logdir := ""
      if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
         logdir = (&node.Config{DataDir: utils.MakeDataDir(ctx)}).ResolvePath("logs")
      }
      if err := debug.Setup(ctx, logdir); err != nil {
         return err
      }
      // Cap the cache allowance and tune the garbage collector
      var mem gosigar.Mem
      if err := mem.Get(); err == nil {
         allowance := int(mem.Total / 1024 / 1024 / 3)
         if cache := ctx.GlobalInt(utils.CacheFlag.Name); cache > allowance {
            log.Warn("Sanitizing cache to Go's GC limits", "provided", cache, "updated", allowance)
            ctx.GlobalSet(utils.CacheFlag.Name, strconv.Itoa(allowance))
         }
      }
      // Ensure Go's GC ignores the database cache for trigger percentage
      cache := ctx.GlobalInt(utils.CacheFlag.Name)
      gogc := math.Max(20, math.Min(100, 100/(float64(cache)/1024)))

      log.Debug("Sanitizing Go's GC trigger", "percent", int(gogc))
      godebug.SetGCPercent(int(gogc))

      // Start metrics export if enabled
      utils.SetupMetrics(ctx)

      // Start system runtime metrics collection
      go metrics.CollectProcessMetrics(3 * time.Second)

      return nil
   }

   app.After = func(ctx *cli.Context) error {
      debug.Exit()
      console.Stdin.Close() // Resets terminal mode.
      return nil
   }
}
// geth is the main entry point into the system if no special subcommand is ran.
// It creates a default node based on the command line arguments and runs it in
// blocking mode, waiting for it to be shut down.
func geth(ctx *cli.Context) error {
   if args := ctx.Args(); len(args) > 0 {
      return fmt.Errorf("invalid command: %q", args[0])
   }
   node := makeFullNode(ctx)  // 创建全节点
   startNode(ctx, node)// 阻塞的模式运行节点,直到节点被终止
   node.Wait() 
   return nil
}
func makeFullNode(ctx *cli.Context) *node.Node {
   // 配置节点
   stack, cfg := makeConfigNode(ctx)
   if ctx.GlobalIsSet(utils.ConstantinopleOverrideFlag.Name) {
      cfg.Eth.ConstantinopleOverride = new(big.Int).SetUint64(ctx.GlobalUint64(utils.ConstantinopleOverrideFlag.Name))
   }
   // 注册eth
   utils.RegisterEthService(stack, &cfg.Eth)

   if ctx.GlobalBool(utils.DashboardEnabledFlag.Name) {
      utils.RegisterDashboardService(stack, &cfg.Dashboard, gitCommit)
   }
   // Whisper节点间通信安全协议
   // Whisper must be explicitly enabled by specifying at least 1 whisper flag or in dev mode
   shhEnabled := enableWhisper(ctx)
   shhAutoEnabled := !ctx.GlobalIsSet(utils.WhisperEnabledFlag.Name) && ctx.GlobalIsSet(utils.DeveloperFlag.Name)
   if shhEnabled || shhAutoEnabled {
      if ctx.GlobalIsSet(utils.WhisperMaxMessageSizeFlag.Name) {
         cfg.Shh.MaxMessageSize = uint32(ctx.Int(utils.WhisperMaxMessageSizeFlag.Name))
      }
      if ctx.GlobalIsSet(utils.WhisperMinPOWFlag.Name) {
         cfg.Shh.MinimumAcceptedPOW = ctx.Float64(utils.WhisperMinPOWFlag.Name)
      }
      if ctx.GlobalIsSet(utils.WhisperRestrictConnectionBetweenLightClientsFlag.Name) {
         cfg.Shh.RestrictConnectionBetweenLightClients = true
      }
      utils.RegisterShhService(stack, &cfg.Shh)
   }

   // Add the Ethereum Stats daemon if requested.
   if cfg.Ethstats.URL != "" {
      utils.RegisterEthStatsService(stack, cfg.Ethstats.URL)
   }
   return stack
}
// RegisterEthService adds an Ethereum client to the stack.
func RegisterEthService(stack *node.Node, cfg *eth.Config) {
   var err error
   // 同步模式是轻量级,注册轻量级客户端
   if cfg.SyncMode == downloader.LightSync {
      err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
         return les.New(ctx, cfg)
      })
   } else { // 全节点
      err = stack.Register(func(ctx *node.ServiceContext) (node.Service, error) {
         fullNode, err := eth.New(ctx, cfg)
         // LightServ 默认为0
         if fullNode != nil && cfg.LightServ > 0 {
            ls, _ := les.NewLesServer(fullNode, cfg)
            fullNode.AddLesServer(ls)
         }
         return fullNode, err
      })
   }
   if err != nil {
      Fatalf("Failed to register the Ethereum service: %v", err)
   }
}

 

 

 

你可能感兴趣的:(区块链)