掃碼下載
BTC $70,740.69 -2.62%
ETH $2,076.78 -2.43%
BNB $645.12 -1.41%
XRP $1.42 -4.56%
SOL $81.67 -4.53%
TRX $0.2795 -0.47%
DOGE $0.0974 -3.83%
ADA $0.2735 -4.22%
BCH $457.98 -0.19%
LINK $8.64 -2.97%
HYPE $28.98 -1.81%
AAVE $122.61 -3.42%
SUI $0.9138 -6.63%
XLM $0.1605 -4.62%
ZEC $260.31 -8.86%
BTC $70,740.69 -2.62%
ETH $2,076.78 -2.43%
BNB $645.12 -1.41%
XRP $1.42 -4.56%
SOL $81.67 -4.53%
TRX $0.2795 -0.47%
DOGE $0.0974 -3.83%
ADA $0.2735 -4.22%
BCH $457.98 -0.19%
LINK $8.64 -2.97%
HYPE $28.98 -1.81%
AAVE $122.61 -3.42%
SUI $0.9138 -6.63%
XLM $0.1605 -4.62%
ZEC $260.31 -8.86%

Geth 源碼系列:Geth 整體架構

Summary: 這篇文章是 Geth 源碼系列的第一篇,通過這個系列,我們將搭建一個研究 Geth 實現的框架,開發者可以根據這個框架深入自己感興趣的部分研究。
LXDAO
2025-08-28 21:52:39
收藏
這篇文章是 Geth 源碼系列的第一篇,通過這個系列,我們將搭建一個研究 Geth 實現的框架,開發者可以根據這個框架深入自己感興趣的部分研究。

作者:Ray,LXDAO

本文將研究執行層客戶端 Geth 的設計架構以及 Geth 節點的啟動流程。Geth 代碼更新的速度很快,後續看到的代碼可能會有所不同,但是整體的設計大體一致,新的代碼也可以用同樣的思路閱讀。

源碼版本:https://github.com/ethereum/go-ethereum/commit/c8a9a9c0917dd57d077a79044e65dbbdd421458b

1. 以太坊客戶端

以太坊在進行 The Merge 升級之前,以太坊只有一個客戶端,這個客戶端負責交易的執行,也會負責區塊鏈的共識,保證區塊鏈以一定的順序產生新的區塊。在 The Merge 升級之後,以太坊客戶端分為了執行層和共識層,執行層負責交易的執行、狀態和數據的維護,共識層則負責共識功能的實現,執行層和共識層通過 API 來通信。執行層和共識層有各自的規範,客戶端可以使用不同的語言來實現,但是要符合對應的規範,其中 Geth 就是執行層客戶端的一種實現。當前主流的執行層和共識層客戶端有如下實現:

執行層

  • Geth:由以太坊基金會直接資助的團隊維護,使用 Go 語言開發,是公認的最穩定、久經考驗的客戶端
  • Nethermind:由 Nethermind 團隊開發和維護,使用 C# 語言開發,早期獲以太坊基金會和 Gitcoin 社區資助
  • Besu:最初由 ConsenSys 的 PegaSys 團隊開發,現為 Hyperledger 社區項目,使用 Java 語言開發
  • Erigon:由 Erigon 團隊開發和維護,獲以太坊基金會、BNB Chain 資助。2017 年從 Geth 分叉而來,目標是提升同步速度和磁碟效率
  • Reth:由 Paradigm 主導開發,開發語言是 Rust,強調模組化和高性能,目前已經趨近成熟,可以在生產環境使用

共識層

  • Prysm:由 Prysmatic Labs 維護,是以太坊最早的共識層客戶端之一,用 Go 語言開發,專注於可用性和安全性,早期獲以太坊基金會資助
  • Lighthouse:由 Sigma Prime 團隊維護,使用 Rust 語言開發,主打高性能和企業級安全,適用於高負載場景
  • Teku:早期由 ConsenSys 的 PegaSys 團隊開發,後成為 Hyperledger Besu 社區的一部分,使用 Java 語言開發
  • Nimbus:由 Status Network 團隊開發和維護,使用 Nim 語言開發,專為資源受限設備(如手機、物聯網設備)優化,目標是在嵌入式系統中實現輕量化運行

2. 執行層簡介

可以將以太坊執行層看作是一個由交易驅動的狀態機,執行層最基礎的職能就是通過 EVM 執行交易來更新狀態數據。除了交易執行之外,還有保存並驗證區塊和狀態數據,運行 p2p 網路並維護交易池等功能。

交易由用戶(或者程序)按照以太坊執行層規範定義的格式生成,用戶需要對交易進行簽名,如果交易是合法的(Nonce 連續、簽名正確、gas fee 足夠、業務邏輯正確),那麼交易最終就會被 EVM 執行,從而更新以太坊網路的狀態。這裡的狀態是指數據結構、數據和數據庫的集合,包括外部賬戶地址、合約地址、地址餘額以及代碼和數據。

執行層負責執行交易以及維護交易執行之後的狀態,共識層負責選擇哪些交易來執行。EVM 則是這個狀態機中的狀態轉換函數,函數的輸入會來自於多個地方,有可能來自於共識層提供的最新區塊信息,也有可能來自於 p2p 網路下載的區塊。

共識層和執行層通過 Engine API 來進行通信,這是執行層和共識層之間唯一的通信方式。如果共識層拿到了出塊權,就會通過 Engine API 讓執行層產出新的區塊,如果沒有拿到出塊權,就會同步最新的區塊讓執行層驗證和執行,從而與整個以太坊網路保持共識。

執行層從邏輯上可以分為 6 個部分:

  • EVM:負責執行交易,交易執行也是修改狀態數的唯一方式
  • 存儲:負責 state 以及區塊等數據的存儲
  • 交易池:用於用戶提交的交易,暫時存儲,並且會通過 p2p 網路在不同節點之間傳播
  • p2p 網路:用於發現節點、同步交易、下載區塊等等功能
  • RPC 服務:提供訪問節點的能力,比如用戶向節點發送交易,共識層和執行層之間的交互
  • BlockChain:負責管理以太坊的區塊鏈數據

下圖展示了執行層的關鍵流程,以及每個部分的職能:

對於執行層(這裡暫時只討論 Full Node),有三個關鍵流程:

  • 如果是新加入以太坊的節點,需要通過 p2p 網路從其他的節點同步區塊和狀態數據,如果是 Full Sync,會從創世區塊開始逐個下載區塊,驗證區塊並通過 EVM 重建狀態數據庫,如果是 Snap Sync,則跳過全部區塊驗證的過程,直接下載最新 checkpoint 的狀態數據和以後的區塊數據
  • 如果是已經同步到最新狀態的節點,那麼就會持續通過 Engine API 從共識層獲取到當前最新產出的區塊,並驗證區塊,然後通過 EVM 執行區塊中所有的交易來更新狀態數據庫,並將區塊寫入本地鏈
  • 如果是已經同步到最新狀態,並且共識層拿到了出塊權的節點,就會通過 Engine API 驅動執行層產出最新的區塊,執行層從交易池獲取交易並執行,然後組裝成區塊通過 Engine API 傳遞給共識層,由共識層將區塊廣播到共識層 p2p 網路

3. 源碼結構

go-ethereum 的代碼結構很龐大,但其中很多代碼屬於輔助代碼和單元測試,在研究 Geth 源碼時,只需要關注協議的核心實現,各個模組功能如下。需要重點關注 core、eth、ethdb、node、p2p、rlp、trie \& triedb 等模組:

  • accounts:管理以太坊賬戶,包括公私鑰對的生成、簽名驗證、地址派生等
  • beacon:處理與以太坊信標鏈(Beacon Chain)的交互邏輯,支持權益證明(PoS)共識的合併(The Merge)後功能
  • build:構建腳本和編譯配置(如 Dockerfile、跨平台編譯支持)
  • cmd:命令行工具入口,包含多個子命令
  • common:通用工具類,如字節處理、地址格式轉換、數學函數
  • consensus:定義共識引擎,包括之前的工作量證明(Ethash)和單機權益證明(Clique)以及 Beacon engine 等
  • console:提供交互式 JavaScript 控制台,允許用戶通過命令行直接與以太坊節點交互(如調用 Web3 API、管理賬戶、查詢區塊鏈數據)
  • core:區塊鏈核心邏輯,處理區塊/交易的生命週期管理、狀態機、Gas計算等
  • crypto:加密算法實現,包括橢圓曲線(secp256k1)、哈希(Keccak-256)、簽名驗證
  • docs:文檔(如設計規範、API 說明)
  • eth:以太坊網路協議的完整實現,包括節點服務、區塊同步(如快速同步、歸檔模式)、交易廣播等
  • ethclient:實現以太坊客戶端庫,封裝 JSON-RPC 接口,供 Go 開發者與以太坊節點交互(如查詢區塊、發送交易、部署合約)
  • ethdb:數據庫抽象層,支持 LevelDB、Pebble、內存數據庫等,存儲區塊鏈數據(區塊、狀態、交易)
  • ethstats:收集並上報節點運行狀態到統計服務,用於監控網路健康狀態
  • event:實現事件訂閱與發布機制,支持節點內部模組間的異步通信(如新區塊到達、交易池更新)
  • graphql:提供 GraphQL 接口,支持複雜查詢(替代部分 JSON-RPC 功能)
  • internal:內部工具或限制外部訪問的代碼
  • log:日誌系統,支持分級日誌輸出、上下文日誌記錄
  • mertrics:性能指標收集(Prometheus 支持)
  • miner:挖礦相關邏輯,生成新區塊並打包交易(PoW 場景下)
  • node:節點服務管理,整合 p2p、RPC、數據庫等模組的啟動與配置
  • p2p:點對點網路協議實現,支持節點發現、數據傳輸、加密通信
  • params:定義以太坊網路參數(主網、測試網、創世區塊配置)
  • rlp:實現以太坊專用的數據序列化協議 RLP(Recursive Length Prefix),用於編碼/解碼區塊、交易等數據結構
  • rpc:實現 JSON-RPC 和 IPC 接口,供外部程序與節點交互
  • signer:交易簽名管理(硬體錢包集成)
  • tests:集成測試和狀態測試,驗證協議兼容性
  • trie \& triedb:默克爾帕特里夏樹(Merkle Patricia Trie)的實現,用於高效存儲和管理賬戶狀態、合約存儲

4. 執行層模組劃分

外部訪問 Geth 節點有兩種形式,一種是通過 RPC,另外一種是通過 Console。RPC 適合開放給外部的用戶來使用,Console 適合節點的管理者使用。但無論是通過 RPC 還是 Console,都是使用內部已經封裝好的能力,這些能力通過分層的方式來構建。

最外層就是 API 用於外部訪問節點的各項能力,Engine API 用於執行層和共識層之間的通信,Eth API 用於外部用戶或者程序發送交易,獲取區塊信息,Net API 用於獲取 p2p 網路的狀態等等。比如用戶通過 API 發送了一個交易,那麼這個交易最終會被提交到交易池中,通過交易池來管理,再比如用戶需要獲取一個區塊數據,那麼就需要調用數據庫的能力去獲取對應的區塊。

在 API 的下一層就是核心功能的實現,包括交易池、交易打包、產出區塊、區塊和狀態的同步等等。這些功能再往下就需要依賴更底層的能力,比如交易池、區塊和狀態的同步需要依賴 p2p 網路的能力,區塊的產生以及從其他節點同步過來的區塊需要被驗證才能寫入到本地的數據庫,這些就需要依賴 EVM 和數據存儲的能力。

執行層核心數據結構

Ethereum

eth/backend.go 中的 Ethereum 結構是整個以太坊協議的抽象,基本包括了以太坊中的主要組件,但 EVM 是一個例外,它會在每次處理交易的時候實例化,不需要隨著整個節點初始化,下文中的 Ethereum 都是指這個結構體:

type Ethereum struct {
// 以太坊配置,包括鏈配置
config *ethconfig.Config
// 交易池,用戶的交易提交之後先到交易池
txPool *txpool.TxPool
// 用於跟蹤和管理本地交易(local transactions)
localTxTracker *locals.TxTracker
// 區塊鏈結構
blockchain *core.BlockChain
// 是以太坊節點的網路層核心組件,負責處理所有與其他節點的通信,包括區塊同步、交易廣播和接收,以及管理對等節點連接
handler *handler
// 負責節點發現和節點源管理
discmix *enode.FairMix
// 負責區塊鏈數據的持久化存儲
chainDb ethdb.Database
// 負責處理各種內部事件的發布和訂閱
eventMux *event.TypeMux
// 共識引擎
engine consensus.Engine
// 管理用戶賬戶和密鑰
accountManager *accounts.Manager
// 管理日誌過濾器和區塊過濾器
filterMaps *filtermaps.FilterMaps
// 用於安全關閉 filterMaps 的通道,確保在節點關閉時正確清理資源
closeFilterMaps chan chan struct{}
// 為 RPC API 提供後端支持
APIBackend *EthAPIBackend
// 在 PoS 下,與共識引擎協作驗證區塊
miner *miner.Miner
// 節點接受的最低gas價格
gasPrice *big.Int
// 網路 ID
networkID uint64
// 提供網路相關的 RPC 服務,允許通過 RPC 查詢網路狀態
netRPCService *ethapi.NetAPI
// 管理P2P網路連接,處理節點發現和連接建立並提供底層網路傳輸功能
p2pServer *p2p.Server
// 保護可變字段的並發訪問
lock sync.RWMutex
// 跟蹤節點是否正常關閉,在異常關閉後幫助恢復
shutdownTracker *shutdowncheck.ShutdownTracker
}

Node

node/node.go 中的 Node 是另一個核心的數據結構,它作為一個容器,負責管理和協調各種服務的運行。在下面的結構中,需要關注一下 lifecycles 字段,Lifecycle 用來管理內部功能的生命週期。比如上面的 Ethereum 抽象就需要依賴 Node 才能啟動,並且在 lifecycles 中註冊。這樣可以將具體的功能與節點的抽象分離,提升整個架構的擴展性,這個 Node 需要與 devp2p 中的 Node 區分開。

type Node struct {
eventmux *event.TypeMux
config *Config
// 賬戶管理器,負責管理錢包和賬戶
accman *accounts.Manager
log log.Logger
keyDir string
keyDirTemp bool
dirLock *flock.Flock
stop chan struct{}
// p2p 網路實例
server *p2p.Server
startStopLock sync.Mutex
// 跟蹤節點生命週期狀態(初始化、運行中、已關閉)
state int
lock sync.Mutex
// 所有註冊的後端、服務和輔助服務
lifecycles []Lifecycle
// 當前提供的 API 列表
rpcAPIs []rpc.API
// 為 RPC 提供的不同訪問方式
http *httpServer
ws *httpServer
httpAuth *httpServer
wsAuth *httpServer
ipc *ipcServer
inprocHandler *rpc.Server
databases map[*closeTrackingDB]struct{}
}
如果以一個抽象的維度來看以太坊的執行層,以太坊作為一台世界計算機,需要包括三個部分,網路、計算和存儲,那麼以太坊執行層中與這三個部分相對應的組件是:

  • 網路:devp2p
  • 計算:EVM
  • 存儲:ethdb

devp2p

以太坊本質還是一個分佈式系統,每個節點通過 p2p 網路與其他節點相連。以太坊中的 p2p 網路協議的實現就是 devp2p。

devp2p 有兩個核心功能,一個是節點發現,讓節點在接入網路時能夠與其他節點建立聯繫;另一個是數據傳輸服務,在與其他節點建立聯繫之後,就可以進行數據交換。

p2p/enode/node.go 中的 Node 結構代表了 p2p 網路中一個節點,其中 enr.Record 結構中存儲了節點詳細信息的鍵值對,包括身份信息(節點身份所使用的簽名算法、公鑰)、網路信息(IP 地址,端口號)、支持的協議信息(比如支持 eth/68 和 snap 協議)和其他的自定義信息,這些信息通過 RLP 的方式編碼,具體的規範在 eip-778 中定義:

type Node struct {
// 節點記錄,包含節點的各種屬性
r enr.Record
// 節點的唯一標識符,32字節長度
id ID

// hostname 跟蹤節點的DNS名稱
hostname string

// 節點的IP地址
ip netip.Addr
// UDP端口
udp uint16
// TCP端口
tcp uint16
}

// enr.Record
type Record struct {
// 序列號
seq uint64
// 簽名
signature []byte
// RLP 編碼後的記錄
raw []byte
// 所有鍵值對的排序列表
pairs []pair
}
在p2p/discover/table.go中的 Table 結構是 devp2p 實現節點發現協議的核心數據結構,它實現了類似 Kademlia 的分佈式哈希表,用於維護和管理網路中的節點信息。
type Table struct {
mutex sync.Mutex
// 按距離索引已知節點
buckets [nBuckets]*bucket
// 引導節點
nursery []*enode.Node
rand reseedingRandom
ips netutil.DistinctNetSet
revalidation tableRevalidation
// 已知節點的數據庫
db *enode.DB
net transport
cfg Config
log log.Logger
// 週期性的處理網路中的各種事件
refreshReq chan chan struct{}
revalResponseCh chan revalidationResponse
addNodeCh chan addNodeOp
addNodeHandled chan bool
trackRequestCh chan trackRequestOp
initDone chan struct{}
closeReq chan struct{}
closed chan struct{}
// 增加和移除節點的接口
nodeAddedHook func(*bucket, *tableNode)
nodeRemovedHook func(*bucket, *tableNode)
}

ethdb

ethdb 完成以太坊數據存儲的抽象,提供統一的存儲接口,底層具體的數據庫可以是 leveldb,也可以是 pebble 或者其他的數據庫。可以有很多的擴展,只要在接口層面保持統一。

有些數據(如區塊數據)可以通過 ethdb 接口直接對底層數據庫進行讀寫,其他的數據存儲接口都是建立的 ethdb 的基礎上,比如數據庫有很大部分的數據是狀態數據,這些數據會被組織成 MPT 結構,在 Geth 中對應的實現是 trie,在節點運行的過程中,trie 數據會產生很多中間狀態,這些數據不能直接調用 ethdb 進行讀寫,需要 triedb 來管理這些數據和中間狀態,最後才通過 ethdb 來持久化。

ethdb/database.go 中定義底層數據庫的讀寫能力的接口,但沒有包括具體的實現,具體的實現將由不同的數據庫自身來實現。比如 leveldb 或者 pebble 數據庫。在 Database 中定義了兩層數據讀寫的接口,其中 KeyValueStore 接口用於存儲活躍的、可能頻繁變化的數據,如最新的區塊、狀態等。AncientStore 則用於處理歷史區塊數據,這些數據一旦寫入就很少改變。

// 數據庫的頂層接口
type Database interface {
KeyValueStore
AncientStore
}
// KV 數據的讀寫接口
type KeyValueStore interface {
KeyValueReader
KeyValueWriter
KeyValueStater
KeyValueRangeDeleter
Batcher
Iteratee
Compacter
io.Closer
}
// 處理老數據的讀寫的接口
type AncientStore interface {
AncientReader
AncientWriter
AncientStater
io.Closer
}

EVM

EVM 是以太坊這個狀態機的狀態轉換函數,所有狀態數據的更新都只能通過 EVM 來進行,p2p 網路可以接受到交易和區塊信息,這些信息被 EVM 處理之後會成為狀態數據庫的一部分。EVM 屏蔽了底層硬體的不同,讓程序在不同平台的 EVM 上執行都能得到一致的結果。這是一種很成熟的設計方式,Java 語言中 JVM 也是類似的設計。

EVM 的實現有三個主要的組件,core/vm/evm.go 中的 EVM 結構體定義了 EVM 的總體結構及依賴,包括執行上下文,狀態數據庫依賴等等; core/vm/interpreter.go 中的 EVMInterpreter 結構體定義了解釋器的實現,負責執行 EVM 字節碼;core/vm/contract.go 中的 Contract 結構體封裝合約調用的具體參數,包括調用者、合約代碼、輸入等等,並且在 core/vm/opcodes.go 中定義了當前所有的操作碼:

// EVM
type EVM struct {
// 區塊上下文,包含區塊相關信息
Context BlockContext
// 交易上下文,包含交易相關信息
TxContext
// 狀態數據庫,用於訪問和修改賬戶狀態
StateDB StateDB
// 當前調用深度
depth int
// 鏈配置參數
chainConfig *params.ChainConfig
chainRules params.Rules
// EVM配置
Config Config
// 字節碼解釋器
interpreter *EVMInterpreter
// 中止執行的標誌
abort atomic.Bool
callGasTemp uint64
// 預編譯合約映射
precompiles map[common.Address]PrecompiledContract
jumpDests map[common.Hash]bitvec
}

type EVMInterpreter struct {
// 指向所屬的EVM實例
evm *EVM
// 操作碼跳轉表
table *JumpTable
// Keccak256哈希器實例,在操作碼間共享
hasher crypto.KeccakState
// Keccak256哈希結果緩衝區
hasherBuf common.Hash
// 是否為只讀模式,只讀模式下不允許狀態修改
readOnly bool
// 上一次CALL的返回數據,用於後續重用
returnData []byte
}

type Contract struct {
// 調用者地址
caller common.Address
// 合約地址
address common.Address

jumpdests map[common.Hash]bitvec
analysis bitvec
// 合約字節碼
Code []byte
// 代碼哈希
CodeHash common.Hash
// 調用輸入
Input []byte
// 是否為合約部署
IsDeployment bool
// 是否為系統調用
IsSystemCall bool
// 可用gas量
Gas uint64
// 調用附帶的 ETH 數量
value *uint256.Int
}

其他模組實現

執行層的功能通過分層的方式來實現,其他的模組和功能都是在這三個核心組件的基礎之上構建起來的。這裡介紹一下幾個核心的模組。

在 eth/protocols 下有當前以太坊的p2p網路子協議的實現。有 eth/68 和 snap 子協議,這些子協議都是在 devp2p 上構建的。

eth/68 是以太坊的核心協議,協議名稱就是 eth,68 是它的版本號,然後在這個協議的基礎之上又實現了交易池(TxPool)、區塊同步(Downloader)和交易同步(Fetcher)等功能。snap 協議用於新節點加入網路時快速同步區塊和狀態數據的,可以大大減少新節點啟動的時間。

ethdb 提供了底層數據庫的讀寫能力,由於以太坊協議中有很多複雜的數據結構,直接通過 ethdb 無法實現這些數據的管理,所以在 ethdb 上又實現了 rawdb 和 statedb 來分別管理區塊和狀態數據。

EVM 則貫穿所有的主流程,無論是區塊構建還是區塊驗證,都需要用 EVM 執行交易。

5. Geth 節點啟動流程

Geth 的啟動會分為兩個階段,第一階段會初始化節點所需要啟動的組件和資源,第二階段會正式啟動節點,然後對外服務。

節點初始化

在啟動一個 geth 節點時,會涉及到以下的代碼:

各模組的初始化如下:

  • cmd/geth/main.go:geth 節點啟動入口
  • cmd/geth/config.go(makeFullNode):加載配置,初始化節點
  • node/node.go:初始化以太坊節點的核心容器
    • node.rpcstack.go:初始化 RPC 模組
    • accounts.manager.go:初始化 accountManager
  • eth/backend.go:初始化 Ethereum 實例
    • node/node.go OpenDatabaseWithFreezer:初始化 chaindb
    • eth/ethconfig/config.go:初始化共識引擎實例(這裡的共識引擎並不真正參與共識,只是會驗證共識層的結果,以及處理 validator 的提款請求)
    • core/blockchain.go:初始化 blockchain
    • core/filterMaps.go:初始化 filtermaps
    • core/txpool/blobpool/blobpool.go:初始化 blob 交易池
    • core/txpool/legacypool/legacypool.go:初始化普通交易池
    • cord/txpool/locals/tx_tracker.go:本地交易追蹤(需要配置開啟本地交易追蹤,本地交易會被更高優先級處理)
    • eth/handler.go:初始化協議的 Handler 實例
    • miner/miner.go:實例化交易打包的模組(原挖礦模組)
    • eth/api_backend.go:實例化 RPC 服務
    • eth/gasprice/gasprice.go:實例化 gas 價格查詢服務
    • internal/ethapi/api.go:實例化 P2P 網路 RPC API
    • node/node.go(RegisterAPIs):註冊 RPC API
    • node/node.go(RegisterProtocols):註冊 p2p 的 Ptotocols
    • node/node.go(RegisterLifecycle):註冊各個組件的生命週期
  • cmd/utils/flags.go(RegisterFilterAPI):註冊 Filter RPC API
  • cmd/utils/flags.go(RegisterGraphQLService):註冊 GraphQL RPC API(如果配置了的話)
  • cmd/utils/flags.go(RegisterEthStatsService):註冊 EthStats RPC API(如果配置了的話)
  • eth/catalyst/api.go:註冊 Engine API

節點的初始化會在 cmd/geth/config.go 中的 makeFullNode 中完成,重點會初始化以下三個模組

在第一步會初始化 node/node.go 中的 Node 結構,就是整個節點容器,所有的功能都需要在這個容器中運行,第二步會初始化 Ethereum 結構,其中包括以太坊各種核心功能的實現,Etherereum 也需要註冊到 Node 中,第三步就是註冊 Engine API 到 Node 中。

其中 Node 初始化就是創建了一個 Node 實例,然後初始化 p2p server、賬號管理以及 http 等暴露給外部的協議端口。

Ethereum 的初始化就會複雜很多,大多數的核心功能都是在這裡初始化。首先會初始化 ethdb,並從存儲中加載鏈配置,然後創建共識引擎,這裡的共識引擎不會執行共識操作,而只是會對共識層返回的結果進行驗證,如果共識層發生了提款請求,也會在這裡完成實際的提款操作。然後再初始化 Block Chain 結構和交易池。

這些都完成之後就會初始化 handler,handler 是所有 p2p 網路請求的處理入口,包括交易同步、區塊下載等等,是以太坊實現去中心化運行的關鍵組件。在這些都完成之後,就會將一些在 devp2p 基礎之上實現的子協議,比如 eth/68、snap 等註冊到 Node 容器中,最後 Ethereum 會作為一個 lifecycle 註冊到 Node 容器中,Ethereum 初始化完成。


最後 Engine API 的初始化相對簡單,只是將 Engine API 註冊到 Node 中。到這裡,節點初始化就全部完成了。

節點啟動

在完成節點的初始化之後,就需要啟動節點了,節點啟動的流程相對簡單,只需要將已經註冊的 RPC 服務和 Lifecycle 全部啟動,那麼整個節點就可以向外部提供服務了。

6. 總結

在深入理解以太坊執行層的實現之前,需要對以太坊有一個整體的認識,可以將以太坊整體看作是一個交易驅動的狀態機,執行層負責交易的執行和狀態的變更,共識層則負責驅動執行層運行,包括讓執行層產出區塊、決定交易的順序、為區塊投票、以及讓區塊獲得最終性。由於這個狀態機是去中心化的,所以需要通過 p2p 網路與其他的節點通信,共同維護狀態數據的一致性。

在執行層不負責決定交易的順序,只負責執行交易並記錄交易執行之後的狀態變化。這裡的記錄有兩種形式,一種是以區塊的方式將所有的狀態變化都記錄下來,另一種是在數據庫中記錄當前的狀態。同時執行層也是交易的入口,通過交易池來存儲還沒有被打包進區塊的交易。如果其他的節點需要獲取區塊、狀態和交易數據,執行層就會通過 p2p 網路將這些信息發送出去。

對於執行層,有三個核心模組:計算、存儲和網路。計算對應 EVM 的實現,存儲則對應了 ethdb 的實現,網路對了 devp2p 的實現。有了這樣的整體認識之後,就可以深入去理解每一個子模組,而不會迷失在具體的細節中。

Ref

[1]https://ethereum.org/zh/what-is-ethereum/

[2]https://epf.wiki/#/wiki/protocol/architecture

[3]https://clientdiversity.org/#distribution

[4]https://github.com/ethereum/devp2p

[5]https://github.com/ethereum/execution-specs

[6]https://github.com/ethereum/consensus-specs

關聯標籤
warnning 風險提示
app_icon
ChainCatcher 與創新者共建Web3世界