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 言語で開発され、リソース制約のあるデバイス(スマートフォン、IoT デバイスなど)向けに最適化されており、組み込みシステムでの軽量運用を目指しています。
2. 実行層の概要
イーサリアムの実行層は、取引駆動の状態機械と見なすことができ、実行層の最も基本的な機能は EVM を通じて取引を実行し、状態データを更新することです。取引の実行に加えて、ブロックと状態データの保存と検証、p2p ネットワークの運営、取引プールの維持などの機能もあります。
取引はユーザー(またはプログラム)がイーサリアム実行層の規範で定義された形式で生成し、ユーザーは取引に署名する必要があります。取引が合法であれば(Nonce が連続、署名が正しい、ガス料金が十分、ビジネスロジックが正しい)、取引は最終的に EVM によって実行され、イーサリアムネットワークの状態が更新されます。ここでの状態は、データ構造、データ、データベースの集合を指し、外部アカウントアドレス、コントラクトアドレス、アドレス残高、コード、データが含まれます。
実行層は取引を実行し、取引実行後の状態を維持する責任があり、コンセンサス層はどの取引を実行するかを選択する責任があります。EVM はこの状態機械の状態遷移関数であり、関数の入力は複数の場所から来る可能性があり、コンセンサス層が提供する最新のブロック情報から来ることもあれば、p2p ネットワークからダウンロードされたブロックから来ることもあります。
コンセンサス層と実行層は Engine API を通じて通信します。これは実行層とコンセンサス層の間の唯一の通信方法です。コンセンサス層がブロック生成権を取得すると、Engine API を通じて実行層に新しいブロックを生成させ、ブロック生成権を取得できなかった場合は、最新のブロックを同期して実行層に検証と実行を行わせ、イーサリアムネットワーク全体とのコンセンサスを維持します。
実行層は論理的に 6 つの部分に分けることができます:
- EVM:取引を実行し、取引の実行は状態数を変更する唯一の方法です。
- ストレージ:状態やブロックなどのデータの保存を担当します。
- 取引プール:ユーザーが提出した取引を一時的に保存し、p2p ネットワークを通じて異なるノード間で伝播します。
- p2p ネットワーク:ノードの発見、取引の同期、ブロックのダウンロードなどの機能を提供します。
- RPC サービス:ノードへのアクセス能力を提供し、ユーザーがノードに取引を送信し、コンセンサス層と実行層の間の相互作用を行います。
- BlockChain:イーサリアムのブロックチェーンデータを管理します。
下の図は実行層の重要なプロセスと各部分の機能を示しています:

実行層(ここでは Full Node のみを議論します)には 3 つの重要なプロセスがあります:
- 新しくイーサリアムに参加するノードは、p2p ネットワークを通じて他のノードからブロックと状態データを同期する必要があります。Full Sync の場合、創世ブロックから順にブロックをダウンロードし、ブロックを検証し、EVM を通じて状態データベースを再構築します。Snap Sync の場合は、すべてのブロック検証プロセスをスキップし、最新のチェックポイントの状態データとその後のブロックデータを直接ダウンロードします。
- すでに最新の状態に同期しているノードは、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 エンジンなどを含みます。
- console:インタラクティブな JavaScript コンソールを提供し、ユーザーがコマンドラインを通じて直接イーサリアムノードとインタラクションできるようにします(Web3 API の呼び出し、アカウントの管理、ブロックチェーンデータのクエリなど)。
- core:ブロックチェーンのコアロジックを処理し、ブロック/取引のライフサイクル管理、状態機械、ガス計算などを行います。
- crypto:暗号アルゴリズムの実装を含み、楕円曲線(secp256k1)、ハッシュ(Keccak-256)、署名検証などを提供します。
- docs:ドキュメント(設計規範、API 説明など)を含みます。
- eth:イーサリアムネットワークプロトコルの完全な実装を提供し、ノードサービス、ブロック同期(高速同期、アーカイブモードなど)、取引ブロードキャストなどを行います。
- ethclient:イーサリアムクライアントライブラリを実装し、JSON-RPC インターフェースをラップして Go 開発者がイーサリアムノードとインタラクションできるようにします(ブロックのクエリ、取引の送信、コントラクトのデプロイなど)。
- ethdb:データベース抽象層を提供し、LevelDB、Pebble、メモリデータベースなどをサポートし、ブロックチェーンデータ(ブロック、状態、取引)を保存します。
- ethstats:ノードの実行状態を収集し、統計サービスに報告し、ネットワークの健康状態を監視します。
- event:イベントの購読と発行メカニズムを実装し、ノード内部モジュール間の非同期通信をサポートします(新しいブロックの到着、取引プールの更新など)。
- graphql:GraphQL インターフェースを提供し、複雑なクエリをサポートします(JSON-RPC 機能の一部を代替)。
- internal:内部ツールまたは外部アクセスを制限するコードを含みます。
- log:ログシステムを提供し、階層的なログ出力、コンテキストログ記録をサポートします。
- metrics:パフォーマンス指標の収集(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
// ローカル取引を追跡および管理するためのもの
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
// ノードが受け入れる最低ガス価格
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.Addressjumpdests map[common.Hash]bitvec
analysis bitvec
// コントラクトバイトコード
Code []byte
// コードハッシュ
CodeHash common.Hash
// 呼び出し入力
Input []byte
// コントラクトデプロイかどうか
IsDeployment bool
// システム呼び出しかどうか
IsSystemCall bool
// 使用可能なガス量
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:コンセンサスエンジンインスタンスを初期化(ここでのコンセンサスエンジンは実際にはコンセンサスには参加せず、コンセンサス層の結果を検証し、バリデーターの引き出し要求を処理します)
- 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:ガス価格クエリサービスをインスタンス化
- internal/ethapi/api.go:P2P ネットワーク RPC API をインスタンス化
- node/node.go(RegisterAPIs):RPC API を登録
- node/node.go(RegisterProtocols):p2p のプロトコルを登録
- 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 構造体を初期化し、イーサリアムのさまざまなコア機能の実装を含み、Ethereum も Node に登録する必要があります。第三のステップは Engine API を Node に登録することです。
Node の初期化では Node インスタンスを作成し、p2p サーバー、アカウント管理、http などの外部に公開されるプロトコルポートを初期化します。

Ethereum の初期化は非常に複雑であり、大部分のコア機能がここで初期化されます。まず ethdb を初期化し、ストレージからチェーン設定を読み込み、次にコンセンサスエンジンを作成します。ここでのコンセンサスエンジンはコンセンサス操作を実行せず、コンセンサス層からの結果を検証するだけです。コンセンサス層で引き出し要求が発生した場合も、ここで実際の引き出し操作が行われます。次に、Block Chain 構造と取引プールを初期化します。
これらが完了した後、handler を初期化します。handler はすべての p2p ネットワークリクエストの処理エントリであり、取引同期、ブロックダウンロードなどを含み、イーサリアムの分散運用を実現するための重要なコンポーネントです。これらがすべて完了した後、devp2p の基盤の上に実装されたサブプロトコル(eth/68、snap など)を Node コンテナに登録し、最後に Ethereum がライフサイクルとして Node コンテナに登録され、Ethereum の初期化が完了します。

最後に Engine API の初期化は比較的簡単で、単に Engine API を Node に登録するだけです。これでノードの初期化はすべて完了しました。
ノードの起動
ノードの初期化が完了した後、ノードを起動する必要があります。ノードの起動プロセスは比較的簡単で、登録された RPC サービスとライフサイクルをすべて起動するだけで、ノード全体が外部にサービスを提供できるようになります。
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




