以太坊启动源码分析

今天正式开始撸以太坊代码了。

以太坊入口代码位于cmd/geth/main.go,先看一下main()函数:

func main() {
    if err := app.Run(os.Args); err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}

显然,使用了urfave/cli库,具体可以参见之前一篇博文:
https://blog.csdn.net/turkeycock/article/details/80359654

这里有个疑问,为什么没有看到app的flag和command配置呢?我们了解一下Go语言的执行流程就明白了,借用网上的一张神图:

可以看到,main()并不是真正意义上的入口,在初始化完常量和变量以后,会先调用模块的init()函数,然后才是main()函数。所以初始化的工作是在init()函数里完成的:

func init() {
    // Initialize the CLI app and start Geth
    app.Action = 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,
        ……
    }
    sort.Sort(cli.CommandsByName(app.Commands))

    app.Flags = append(app.Flags, nodeFlags...)
    ……

    app.Before = func(ctx *cli.Context) error {
        runtime.GOMAXPROCS(runtime.NumCPU())
        if err := debug.Setup(ctx); err != nil {
            return err
        }
        // Start system runtime metrics collection
        go metrics.CollectProcessMetrics(3 * time.Second)

        utils.SetupNetwork(ctx)
        return nil
    }

    app.After = func(ctx *cli.Context) error {
        debug.Exit()
        console.Stdin.Close() // Resets terminal mode.
        return nil
    }
}

 

可以看到:app.Action=geth,如果没有添加任何command参数的话,主入口是geth()函数。

flag的配置代码位于cmd/utils/flags.go,command的配置代码跟main.go在同一个包中,分散在不同的文件里。

在进入主入口之前,app.Before做了3件事情:

I. runtime.GOMAXPROCS():设置最大可用处理器数

II. metrics.CollectProcessMetrics():创建一个goroutine,每3秒监测一次系统的ram和disk状态

III. utils.SetupNetwork():配置gas limit值

下面开始看geth()函数:

func geth(ctx *cli.Context) error {
    node := makeFullNode(ctx)
    startNode(ctx, node)
    node.Wait()
    return nil
}

 

可以看到,主要做了3件事情:

I. 创建结点

II. 启动结点

III. 结点进入等待状态

下面一个一个的分析:

1. 创建结点

func makeFullNode(ctx *cli.Context) *node.Node {
    stack, cfg := makeConfigNode(ctx)
    utils.RegisterEthService(stack, &cfg.Eth)
    ……
    return stack
}

中间一堆代码默认情况下不会走进去,先忽略~ 

所以这个函数就干了2件事:创建结点、注册EthService。

1.1 创建结点

先看makeConfigNode()函数:

func makeConfigNode(ctx *cli.Context) (*node.Node, gethConfig) {
    // Load defaults.
    cfg := gethConfig{
        Eth:       eth.DefaultConfig,
        Shh:       whisper.DefaultConfig,
        Node:      defaultNodeConfig(),
        Dashboard: dashboard.DefaultConfig,
    }

    // Load config file.
    if file := ctx.GlobalString(configFileFlag.Name); file != "" {
        if err := loadConfig(file, &cfg); err != nil {
            utils.Fatalf("%v", err)
        }
    }

    // Apply flags.
    utils.SetNodeConfig(ctx, &cfg.Node)
    stack, err := node.New(&cfg.Node)
    if err != nil {
        utils.Fatalf("Failed to create the protocol stack: %v", err)
    }
    utils.SetEthConfig(ctx, stack, &cfg.Eth)
    if ctx.GlobalIsSet(utils.EthStatsURLFlag.Name) {
        cfg.Ethstats.URL = ctx.GlobalString(utils.EthStatsURLFlag.Name)
    }

    utils.SetShhConfig(ctx, stack, &cfg.Shh)
    utils.SetDashboardConfig(ctx, &cfg.Dashboard)

    return stack, cfg
}

主要是初始化和

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值