Abel'Blog

我干了什么?究竟拿了时间换了什么?

0%

源码阅读-geth

阅读源代码,学习go语言如何写大框架。

路线图

“main.go → 初始化 → 启动节点 → 启动 P2P/RPC/共识”的全路径。

1️⃣ 找到入口

cmd/geth/main.go

全部服务器都是从 *cli.App 派生出来。 使用了 “github.com/urfave/cli/v2” 库。

CLI11
• 网址:https://github.com/CLIUtils/CLI11

•    现代 C++17 设计,支持子命令、参数验证、自动生成帮助信息。

•    使用简单,支持多种参数类型,解析丰富。

•    类似 Go 的 urfave/cli,功能全面。

里面有个version的子命令,用于记录当前的版本,git commit信息之类的。我们这里也可以仿照制作一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package version

var (
GitCommit string // commit hash
GitDate string // commit date
BuildTime string // build time (额外的构建时间,可选)
)

package main

import (
"fmt"
"your_project/version"
)

func main() {
fmt.Printf("Git Commit: %s\n", version.GitCommit)
fmt.Printf("Git Date: %s\n", version.GitDate)
fmt.Printf("Build Time: %s\n", version.BuildTime)
}
1
2
3
4
go build -ldflags "\
-X your_project/version.GitCommit=$(git rev-parse HEAD) \
-X your_project/version.GitDate=$(git show -s --format=%cd --date=format:%Y-%m-%d) \
-X your_project/version.BuildTime=$(date +%Y-%m-%dT%H:%M:%S)"

main() 函数会调用 cmd/utils 来解析命令行参数,然后进入 geth 的 app.Run()。

主要作用:CLI 初始化 → 配置解析 → 启动服务(节点、控制台、RPC 等)。

Geth 启动流程图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
flowchart TD
A[main.go - 程序入口] --> B[解析命令行参数 & 构建 node.Config]
B --> C[makeFullNode() → node.New(config)]
C --> D[初始化 Node 基础结构 & 服务注册表]
D --> E[stack.Start() - 启动节点]

subgraph Ethereum 服务
E --> F[eth.New() - 初始化 Ethereum 服务]
F --> G[Blockchain 管理器 (core/blockchain.go)]
F --> H[交易池 TxPool (core/tx_pool.go)]
F --> I[共识机制 Consensus (consensus/*)]
F --> J[P2P Handler (eth/handler.go)]
end

subgraph RPC 服务
E --> K[rpc/server.go - 启动 RPC 服务]
K --> L[注册 eth_* API]
K --> M[注册 net_* API]
K --> N[启动 HTTP / WS / IPC 监听]
end

subgraph P2P 网络
E --> O[p2p/server.go - 启动 P2P 网络]
O --> P[节点发现 (Kademlia DHT)]
O --> Q[节点握手 (TCP handshake)]
O --> R[消息循环 (协议消息处理)]
end

subgraph 异步模块
E --> S[区块同步器 (eth/sync.go)]
S --> T[获取区块头]
S --> U[下载完整区块]
S --> V[验证区块与交易]
S --> W[更新状态树 & 写入数据库 (rawdb)]
E --> X[交易池监听器 (TxPool)]
end
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
sequenceDiagram
loop events扫描
alt http定时拉取,runScaner
scaner ->> process: 定时获取events
else websocket订阅,runSubscriber
scaner -->> process: 第三方主动推送events
end

process ->> process: abi根据事件ID解析具体事件内容
alt 订单事件,procOrderEventLog
process ->> repository: 市价单、现价单
par 用户数据
repository ->> db: 订单表,事件表
end
else 仓位事件,procPositionEventLog
process -->> repository: 开仓、平仓
par 用户数据
repository ->> db: 成交表,事件表
repository ->> db: 成交积分,推荐积分
end
else 池子事件,procPoolEventLog
process -x repository: 添加、移除流动性
par 用户数据
repository ->> db: 池子订单表,事件表
end
end

process ->> repository: 更新已消费区块号
end

loop 合约扫描,pairStatSchedule
scaner ->> process: 定时获取池子统计数据
alt 是否零点
process ->> repository: 写入天表daily
else
process -->> repository: 写入分钟表timely
end
end

loop tx扫描,chainTxCostSchedule
scaner ->> repository: 定时获取tx的gas
alt 是否用户下单
repository ->> db: 用户tx_cost累加
end
end

loop block扫描,chainBlockSchedule
scaner ->> repository: 定时获取区块中失败的tx的gas
alt 是否用户下单
repository ->> db: 用户tx_cost_failed累加
end
end

loop 统计数据推送,procDailyStat
statistics ->> repository: 北京时间8点推送统计数据
alt LP积分汇总
repository ->> db: 用户stacked_points累加
end
alt NFT快照
repository ->> db: 用户积分累加
end
end

Note over repository: 缓存数据,批量写入表

2️⃣ 配置和启动流程

• 配置结构:

1
2
node/config.go
eth/config.go

• 启动节点:

•    node.New() → 创建节点实例

•    stack.Register() → 注册子服务(如 Ethereum 协议)

•    stack.Start() → 启动服务(会开启 P2P、RPC、共识等)

3️⃣ 网络层(P2P)

1
p2p/

核心文件:
• server.go:P2P 服务管理器,负责节点发现(discovery)、握手、数据传输。

•    peer.go:单个节点的连接和会话处理。

建议先看 节点启动时是怎么找到其他节点的(Kademlia DHT 发现协议)。

4️⃣ 协议层(Ethereum)

目录:

1
eth/

• backend.go:Ethereum 服务的主要逻辑(同步区块、处理交易、共识)。

• handler.go:处理来自 P2P 的 Ethereum 协议消息(新区块、交易广播等)。

5️⃣ 共识层

Geth 默认是 Ethash(PoW),但现在主网切到 PoS(Beacon Chain),PoW 部分成了历史代码。

• PoW 共识:consensus/ethash/

• PoS 相关的:现在主要通过外部 Beacon Chain 驱动执行层,可以在 consensus/ 下找 clique(PoA 测试链) 或 ethash(历史 PoW)。

6️⃣ 区块链存储

关键文件:

• blockchain.go:区块链管理核心(区块验证、插入、重组)。

• tx_pool.go:交易池逻辑。

• state/:账户状态(Trie 存储)。

• rawdb/:LevelDB 数据存储接口。

7️⃣ RPC 层

目录:

1
2
rpc/
internal/web3ext/

• 提供 JSON-RPC 服务给外部(例如 web3.js)。

• rpc/server.go 是启动点。

• eth/api.go、eth/api_backend.go 提供具体方法(eth_getBlockByNumber 等)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
flowchart TD
A[cmd/geth/main.go] --> B[解析命令行参数 & 配置]
B --> C[创建 Node 实例\nnode.New()]
C --> D[注册 Ethereum 服务\nstack.Register(eth)]
D --> E[启动节点 stack.Start()]

subgraph Ethereum 服务启动
E --> F[eth.New() - 创建以太坊服务]
F --> G[初始化区块链 core/blockchain.go]
F --> H[初始化交易池 core/tx_pool.go]
F --> I[初始化共识 consensus/*]
F --> J[初始化 P2P 协议 eth/handler.go]
end

subgraph P2P 网络
J --> K[p2p/server.go - 启动 P2P Server]
K --> L[节点发现\nKademlia DHT]
K --> M[握手 & 同步协议]
end

subgraph 区块链同步
M --> N[区块同步器 eth/sync.go]
N --> O[区块验证\ncore/block_validator.go]
O --> P[写入数据库 rawdb/*]
end

subgraph RPC 服务
E --> Q[rpc/server.go - 启动 RPC]
Q --> R[注册 API\neth/api.go]
R --> S[对外提供 JSON-RPC/HTTP/WebSocket]
end