0%

《7天以太坊源码解读》 — 2、节点是如何编译以及启动的

>>> geth 可执行文件怎么构建出来的?

上篇文章中讲,我们是通过 make all 构建出所有可执行文件。那么它到底做了些什么呢?

make是一个构建工具,它依据指定规则来构建目标,而构建什么目标以及如何构建目标都写在了 makefile 文件中(当然你也可以不叫makefile)

推荐大家阅读这篇文章 http://www.ruanyifeng.com/blog/2015/02/make.html ,学习 makefile 文件的编写

可以看到以太坊源码根目录存在一个makefile文件,通过上面的学习应该知道了 make all 到底做了什么

1
2
3
4
GORUN = env GO111MODULE=on go run
...
all:
$(GORUN) build/ci.go install

make all执行的其实就是

1
env GO111MODULE=on go run build/ci.go install

意思是开启 golang 的 modules 特性,运行 build 文件夹下的 ci.go 文件,并传递参数 install

下面可以查看 ci.go 文件是如何运行的了。

首先找到 main 函数,往下开始分析代码。

传递的是install,所以找到 doInstall 函数

  1. 检查本机 golang 版本,如果版本不满足要求就直接退出,编译失败
  2. 检查指定的编译目标架构,如果未指定,默认是amd64,根据目标架构组装相应的命令选项以及参数

可以得到最终得到的编译命令是

1
go install -ldflags -X main.gitCommit=58cf5686eab9019cc01e202e846a6bbc70a3301d -X main.gitDate= -s -v ./...

就是编译根目录的所有包。

同理 make geth 最终的构建命令就是

1
go install -ldflags -X main.gitCommit=58cf5686eab9019cc01e202e846a6bbc70a3301d -X main.gitDate= -s -v ./cmd/geth

所以可以看出 ./cmd/geth 包就是 geth 的入口。我们就可以从这开始阅读源码了。

如果还有人不知道 go 可执行文件如何编译的,不知道go install的用法,可以网上学习,篇幅关系,这里不讲了。

>>> 节点是如何启动的?

现在从 cmd/geth/main.go 文件开始

  1. 通过 main 函数以及 init 函数对 geth 的各种参数以及选项进行配置,就是什么命令执行什么样的动作。如果没有指定子命令,默认执行 geth 函数中的代码。

上篇文章中的

1
./build/bin/geth --datadir=./private/ --mine --miner.threads=1 --etherbase=0x0000000000000000000000000000000000000003 --port 33303 --rpc --rpcport 8545 --rpcapi eth,web3,net,rpc,admin --ethash.dagdir ./private/tagdir/

就执行的是 geth 函数中的代码。接下来看 geth 函数

1
2
3
4
5
6
7
8
9
10
11
func geth(ctx *cli.Context) error {
if args := ctx.Args(); len(args) > 0 {
return fmt.Errorf("invalid command: %q", args[0])
}
prepare(ctx)
node := makeFullNode(ctx)
defer node.Close()
startNode(ctx, node)
node.Wait()
return nil
}
  1. 配置内存缓存限额(配置go gc的回收百分比),并安装运行时指标收集系统
  2. 准备构建一个全节点。首先会注册一个Eth服务(以太坊中每个模块都被称作为一个服务),Eth服务中,如果指定了使用轻量协议(–light.serve设置如果大于0就是使用了,默认是0),则会开启一个LES(以太坊客户端的轻量级的子协议)服务器提供服务。
  3. 如果启用了Whisper协议(–shh选项),则注册Whisper服务。
  4. 如果启用了GraphQL功能,则注册一个GraphQL服务。
  5. 如果启用了ethstats功能,则注册ethstats服务。
  6. 启动全节点
  • 启动p2p服务器
  • 依次启动前面注册过的所有服务
  • 按需启动各种api端点服务器(HTTP、WS、RPC等)
  • 开启一个协程拦截终止命令(SIGINT和SIGTERM),用于优雅关闭退出
  • 解锁钱包账户(如果参数指定了的话),便于余额操作
  • 设置新建钱包、开启钱包、关闭钱包事件的处理器
  • 配置eth服务和les服务的与节点交互的rpc客户端
  • 订阅同步完成的事件。处理–exitwhensynced选项,同步完成就退出节点
  • 如果开启了挖矿,则启动挖矿
  1. 等待节点运行结束(关闭或异常退出)

文章仅供参考,若有错误,还望不吝指正 !!!




微信关注我,及时接收最新技术文章