この記事はGethソースコードシリーズの第一篇であり、このシリーズを通じて、Gethの実装を研究するためのフレームワークを構築します。開発者はこのフレームワークに基づいて、自分が興味のある部分を深く研究することができます。このシリーズは全部で六篇の記事から成り立っており、第一篇では実行層クライアントGethの設計アーキテクチャとGethノードの起動プロセスを研究します。Gethのコード更新は非常に速く、今後見るコードは若干異なる可能性がありますが、全体的な設計は概ね一致しており、新しいコードも同じ考え方で読むことができます。### 01\イーサリアムクライアントイーサリアムのマージアップグレード前は、イーサリアムには1つのクライアントしかなく、トランザクションの実行とブロックチェーンのコンセンサスを担当し、ブロックチェーンが特定の順序で新しいブロックを生成するようにしていました。 マージのアップグレード後、イーサリアムクライアントは実行レイヤーとコンセンサスレイヤーに分かれ、実行レイヤーはトランザクションの実行、状態とデータの維持を担当し、コンセンサスレイヤーはコンセンサス機能の実装を担当し、実行レイヤーとコンセンサスレイヤーはAPIを介して通信します。 実行層とコンセンサス層には独自の仕様があり、クライアントはそれらを異なる言語で実装できますが、対応する仕様に準拠する必要があり、Gethは実行層クライアントの実装です。 現在、メインストリームの実行レイヤーとコンセンサスレイヤーのクライアントには、次の実装があります。#### **実行レイヤー*** Geth:イーサリアム財団から直接資金提供を受けているチームによって維持され、Go言語で開発されており、認められた最も安定した、実績のあるクライアントです。* Nethermind:Nethermind チームによって開発および維持されており、C# 言語で開発されています。初期には Ethereum 財団と Gitcoin コミュニティから資金提供を受けました。* Besu:最初にConsenSysのPegaSysチームによって開発され、現在はHyperledgerコミュニティプロジェクトであり、Java言語で開発されています。* Erigon:Erigon チームによって開発および維持されており、Ethereum Foundation と BNB Chain の資金提供を受けています。2017 年に Geth からフォークされ、同期速度とディスク効率の向上を目指しています。* Reth:Paradigmが主導して開発したもので、開発言語はRustです。モジュール化と高性能を強調しており、現在は成熟に近づいており、プロダクション環境で使用できます。#### **コンセンサス層*** Prysm:Prysmatic Labsによって維持されている、イーサリアムの最初のコンセンサスレイヤークライアントの一つで、Go言語で開発され、可用性と安全性に重点を置き、初期にイーサリアム財団からの資金を受けた* Lighthouse:Sigma Prime チームによって維持され、Rust 言語で開発され、高性能とエンタープライズレベルのセキュリティを特徴としており、高負荷シナリオに適しています。* Teku:早起は ConenSys の PegaSys チームによって開発され、その後 Hyperledger Besu コミュニティの一部となり、Java 言語で開発されています。* Nimbus:Status Network チームによって開発および維持され、Nim 言語で開発され、リソース制約のあるデバイス(スマートフォンや IoT デバイスなど)向けに最適化され、組み込みシステムでの軽量運用を目指しています。### 02\実行レイヤーの概要イーサリアムの実行層は、取引によって駆動される状態機械と見なすことができます。実行層の最も基本的な機能は、EVMを介して取引を実行し、状態データを更新することです。取引の実行に加えて、ブロックおよび状態データの保存と検証、p2pネットワークの運営、取引プールの維持などの機能もあります。取引は、ユーザー(またはプログラム)がイーサリアムの実行層規範で定義された形式に従って生成します。ユーザーは取引に署名する必要があります。取引が合法である場合(Nonceが連続している、署名が正しい、ガス料金が十分、ビジネスロジックが正しい)、取引は最終的にEVMによって実行され、イーサリアムネットワークの状態が更新されます。ここでの状態とは、外部アカウントアドレス、コントラクトアドレス、アドレス残高、コードおよびデータを含むデータ構造、データ、およびデータベースの集合を指します。実行レイヤーは、トランザクションを実行し、実行後のトランザクションの状態を維持する役割を担い、コンセンサス層は、実行するトランザクションを選択する役割を担います。 EVMは、このステートマシンの状態遷移関数であり、関数の入力は、コンセンサス層によって提供される最新のブロック情報、またはP2Pネットワークによってダウンロードされたブロックのいずれかから、複数の場所から得られます。コンセンサス層と実行層は Engine API を通じて通信します。これは実行層とコンセンサス層の間の唯一の通信方法です。コンセンサス層がブロック生成権を取得すると、Engine API を通じて実行層に新しいブロックを生成させます。ブロック生成権を取得できなかった場合は、最新のブロックを同期させて実行層に検証と実行を行わせ、全体のイーサリアムネットワークとコンセンサスを維持します。実行層は論理的に6つの部分に分けることができます:* EVM:トランザクションを実行する責任があり、トランザクションの実行は状態数を変更する唯一の方法でもある* ストレージ:stateやブロックなどのデータのストレージを担当*トランザクションプール:ユーザーによって送信され、一時的に保存され、P2Pネットワークを介して異なるノード間で伝播されるトランザクションに使用されます* p2pネットワーク:ノードを発見し、取引を同期し、ブロックをダウンロードするなどの機能に使用されます* RPCサービス:ノードへのアクセス能力を提供します。たとえば、ユーザーがノードにトランザクションを送信することや、コンセンサス層と実行層の間の相互作用などです。* BlockChain:イーサリアムのブロックチェーンデータの管理を担当下の図は、実行層の重要なプロセスと各部分の機能を示しています:! [イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ](https://img.gateio.im/social/moments-7098ac605c6db99b4ec8644e45de6d4f)実行レイヤー (ここではフル ノードについてのみ説明しましょう) には、次の 3 つの主要なプロセスがあります。* 新たにイーサリアムのノードに参加する場合、p2pネットワークを通じて他のノードからブロックと状態データを同期する必要があります。Full Syncの場合、創世ブロックから順にブロックをダウンロードし、ブロックを検証してEVMを通じて状態データベースを再構築します。Snap Syncの場合、すべてのブロック検証プロセスをスキップし、最新のチェックポイントの状態データとその後のブロックデータを直接ダウンロードします。* 最新の状態に同期されたノードであれば、Engine APIを通じてコンセンサス層から現在の最新生成ブロックを継続的に取得し、ブロックを検証し、EVMを介してブロック内のすべての取引を実行して状態データベースを更新し、ブロックをローカルチェーンに書き込む。※最新の状態に同期されたノードで、コンセンサス層がブロック生成権を取得している場合、実行層を駆動してエンジンAPIを介して最新のブロックを生成し、実行層がトランザクションプールからトランザクションを取得して実行した後、ブロックにアセンブルしてエンジンAPIを介してコンセンサス層に渡し、コンセンサス層がブロックをコンセンサス層のP2Pネットワークにブロードキャストします### 03\ソースコードの構造go-ethereumのコード構造は非常に大きいですが、その中の多くのコードは補助コードやユニットテストに属しています。Gethのソースコードを研究する際には、プロトコルのコア実装にのみ注目する必要があり、各モジュールの機能は以下の通りです。core、eth、ethdb、ノード、p2p、rlp、trie & triedbなどのモジュールに重点を置く必要があります。* アカウント:Ethereumアカウントの管理、公開鍵と秘密鍵の生成、署名検証、アドレスの派生など* beacon:イーサリアムのビーコンサインチェーン(Beacon Chain)とのインタラクションロジックを処理し、プルーフ・オブ・ステーク(PoS)コンセンサスのマージ(The Merge)後の機能をサポートします。* build:スクリプトとコンパイル設定(例:Dockerfile、クロスプラットフォームコンパイルサポート)* cmd:コマンドラインツールの入り口で、複数のサブコマンドを含みます* common:汎用ツールクラス、バイト処理、アドレスフォーマット変換、数学関数*コンセンサス:以前のプルーフ・オブ・ワーク(Ethash)、シングルノード・プルーフ・オブ・ステーク(クリーク)、ビーコンエンジンなどを含むコンセンサスエンジンを定義します* コンソール:インタラクティブな JavaScript コンソールを提供し、ユーザーがコマンドラインを介してイーサリアムノードと直接対話できるようにします(例えば、Web3 API の呼び出し、アカウントの管理、ブロックチェーンデータの照会など)。* コア:ブロックチェーンのコアロジック、ブロック/トランザクションのライフサイクル管理、ステートマシン、Gas計算など* crypto: 楕円曲線 (secp256k1)、ハッシュ (Keccak-256)、署名検証を含む暗号アルゴリズムの実装* docs:ドキュメント(設計仕様書、API 説明など)* eth:イーサリアムネットワークプロトコルの完全な実装であり、ノードサービス、ブロック同期(高速同期、アーカイブモードなど)、取引ブロードキャストなどを含みます。* ethclient:Ethereumクライアントライブラリを実装し、JSON-RPCインターフェースをラップして、Go開発者がEthereumノードと対話できるようにします(ブロックの照会、トランザクションの送信、コントラクトのデプロイなど)。* ethdb:データベース抽象レイヤーで、LevelDB、Pebble、インメモリデータベースなどをサポートし、ブロックチェーンデータ(ブロック、状態、トランザクション)を保存します。* ethstats:ノードの実行状態を収集し、統計サービスに報告してネットワークの健康状態を監視します* イベント:イベントの購読と公開メカニズムを実現し、ノード内部のモジュール間の非同期通信(新しいブロックの到着、トランザクションプールの更新など)をサポートします。* 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:マークル・パトリシア・トライの実装で、アカウントの状態や契約のストレージを効率的に保存・管理するためのものです。### 04\実行層モジュールの分割Geth ノードへの外部アクセスには2つの形式があります。1つはRPCを介して、もう1つはConsoleを介してです。RPCは外部のユーザーが使用するために開放するのに適しており、Consoleはノードの管理者が使用するのに適しています。しかし、RPCを通じてでもConsoleを通じてでも、内部で既にパッケージ化された機能を使用しており、これらの機能は階層的な方法で構築されています。最も外側のレイヤーは、外部アクセスノード用のAPI、実行レイヤーとコンセンサスレイヤー間の通信用のエンジンAPI、外部ユーザーまたはプログラムがトランザクションを送信してブロック情報を取得するためのEth API、P2Pネットワークの状態を取得するためのNet APIなどの機能です。 たとえば、ユーザーがAPIを介してトランザクションを送信した場合、トランザクションは最終的にトランザクションプールに送信され、トランザクションプールを介して管理されます。API の次のレイヤーでは、コア機能の実装が行われます。これには、取引プール、取引のパッケージ化、ブロックの生成、ブロックと状態の同期などが含まれます。これらの機能はさらに下層の能力に依存する必要があります。たとえば、取引プール、ブロックおよび状態の同期は p2p ネットワークの能力に依存します。ブロックの生成および他のノードから同期されたブロックは、ローカルデータベースに書き込む前に検証される必要があります。これには EVM およびデータストレージの能力が必要です。! [イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ](https://img.gateio.im/social/moments-8623b98c40da999f29cfac32025b6264)#### **実行層コアデータ構造****イーサリアム**eth/backend.go の Ethereum 構造体は、全体のイーサリアムプロトコルの抽象であり、基本的にイーサリアムの主要コンポーネントを含んでいますが、EVM は例外であり、取引を処理するたびにインスタンス化され、全ノードの初期化と共に必要ではありません。以下の Ethereum はこの構造体を指します:type Ethereum struct { // チェーンコンフィグを含むイーサリアムコンフィグ \*ethconfig. Config // トランザクション プール、ユーザーのトランザクションが送信された後、トランザクション プールに移動します txPool \*txpool。 TxPool // ローカルトランザクションの追跡と管理に使用 localTxTracker \*locals. TxTracker // ブロックチェーン構造 blockchain \*core. ブロックチェーンは、イーサリアムノードのネットワーク層のコアコンポーネントであり、ブロックの同期、トランザクションのブロードキャスト、受信など、他のノードとのすべての通信を処理し、 // ノードの検出とノードソース管理ディスクミックス \*enode を担当するピアノード接続ハンドラーの管理を担当します。 FairMix // ブロックチェーンデータチェーンの永続ストレージを担当しますDb ethdb。 データベース // eventMux \*event へのさまざまな内部イベントの発行とサブスクライブの処理を担当します。 TypeMux // エンジンのコンセンサス。 Engine // ユーザー アカウントとキーを管理します accountManager \*accounts. Manager // ログフィルタとチャンクフィルタを管理します \*filtermaps. FilterMaps // filterMaps を安全にシャットダウンするためのチャネルで、ノードのシャットダウン時にリソースが正しくクリーンアップされるようにします closeFilterMaps chan struct{} // RPC API のバックエンドサポートを提供します APIBackend \*EthAPIBackend // PoS では、コンセンサス エンジンと連携してブロック マイナーを検証します \*miner. Miner // ノードが受け入れる最低ガス価格は gasPrice \*big です。 Int // ネットワーク ID networkID uint64 // ネットワーク関連の RPC サービスを提供し、RPC netRPCService を介してネットワークの状態を照会できるようにします \*ethapi. NetAPI // P2P ネットワーク接続の管理、ノードの検出と接続の確立の処理、およびアンダーレイ ネットワーク トランスポート機能の提供 p2pServer \*p2p. Server // 変更可能なフィールドへの同時アクセスを保護し、同期をロックします。 RWMutex // ノードが正常にダウンしているかどうかを追跡し、異常シャットダウン後の shutdownTracker の復元を支援します \*shutdowncheck. シャットダウントラッカー }**ノード**node/node.goのノードは、さまざまなサービスの運用を管理および調整するためのコンテナとして機能する別のコアデータ構造です。 以下の構造では、ライフサイクルが内部関数のライフサイクルを管理するために使用するライフサイクルフィールドに焦点を当てることが重要です。 たとえば、上記のイーサリアムの抽象化は、ライフサイクルの開始と登録をNodeに依存する必要があります。 このようにして、特定の機能をノードの抽象化から分離し、アーキテクチャ全体のスケーラビリティを差別化する必要があり、devp2pのノードと区別する必要があります。type Node struct { eventmux \*event. TypeMux config \*Config // ウォレットとアカウントの管理を担当するアカウントマネージャー accman \*accounts. マネージャのログログ。 ロガー keyDir string keyDirTemp bool dirLock \*flock. Flock stop chan struct{} // P2P ネットワークインスタンスサーバ \*p2p. サーバーのstartStopLock同期。 Mutex // ノードのライフサイクル状態 (初期化済み、実行中、クローズ済み) 状態を追跡します int lock sync. Mutex // 登録されているすべてのバックエンド、サービス、および補助サービスのライフサイクル []Lifecycle // 現在利用可能な API のリスト rpcAPI []rpc. API // RPC http \*httpServer ws \*httpServer httpAuth \*httpServer wsAuth \*httpServer ipc \*ipcServer inprocHandler \*rpc. サーバー・データベース・マップ[\*closeTrackingDB]struct{} }抽象的な次元でイーサリアムの実行層を見ると、イーサリアムは世界コンピュータとして、ネットワーク、計算、ストレージの3つの部分を含む必要があります。したがって、イーサリアムの実行層におけるこれら3つの部分に対応するコンポーネントは次のとおりです:* ネットワーク:devp2p* 計算方法: EVM* ストレージ:ethdb**devp2p**イーサリアムは本質的に分散型システムであり、各ノードはp2pネットワークを介して他のノードと接続されています。イーサリアムにおけるp2pネットワークプロトコルの実装はdevp2pです。devp2p には 2 つのコア機能があります: 1 つはノード検出で、ノードがネットワークに接続するときに他のノードと接続できるようにします。 もう一つはデータ通信サービスで、他のノードと連絡を取り合った後、好きなようにデータをやり取りすることができます。p2p/enode/node.go の Node 構造は、p2p ネットワーク内のノードを表します。 Record構造には、ID情報(ノードのIDで使用される署名アルゴリズム、公開鍵)、ネットワーク情報(IPアドレス、ポート番号)、サポートされているプロトコル情報(eth/68やsnapプロトコルのサポートなど)、その他のカスタム情報など、RLPでエンコードされ、EIP-778で定義されているノードの詳細のキーと値のペアが格納されます。type Node struct { // ノードのさまざまなプロパティを含むノードレコード r enr. レコード // ノードの一意の識別子、32 バイト長 id ID // ホスト名 ノードの DNS 名をトレースします hostname string // ノードの IP アドレス ip netip. Addr // UDP ポート udp uint16 // TCP ポート tcp uint16 }// enr. レコードタイプ Record struct { // シリアル番号 seq uint64 // 署名署名 []byte // RLP エンコードされたレコード raw []byte // すべてのキーと値のペアのソートされたリスト []pair }p2p/discover/table.go における Table 構造体は devp2p におけるノード発見プロトコルのコアデータ構造であり、ネットワーク内のノード情報を維持・管理するために Kademlia に類似した分散ハッシュテーブルを実装しています。printf("type Table struct { mutex sync. Mutex // 既知のノードバケットを距離でインデックス化 [nBuckets]\*bucket // ブートストラップノードナーサリ []\*enode. ノード rand reseedingRandom ips netutil。 DistinctNetSet revalidation tableRevalidation // 既知のノードのデータベース db \*enode. DB net transport cfg Configログログ。 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(\*バケツ、\*tableNode)} ワールド!」 );**ethdb**ethdbはEthereumデータストレージの抽象を完了し、統一されたストレージインターフェースを提供します。基盤となる具体的なデータベースはleveldb、pebble、またはその他のデータベースである可能性があります。インターフェースレベルでの統一を維持する限り、多くの拡張が可能です。一部のデータ(例えばブロックデータ)はethdbインターフェースを介して直接基盤データベースに読み書きできますが、他のデータストレージインターフェースはethdbを基盤に構築されています。たとえば、データベースの大部分のデータは状態データであり、これらのデータはMPT構造に組織されます。Gethでの対応する実装はtrieです。ノードが実行される過程で、trieデータは多くの中間状態を生成し、これらのデータは直接ethdbを介して読み書きできず、triedbを使用してこれらのデータと中間状態を管理する必要があります。最終的にはethdbを介して永続化されます。ethdb/database.go において、基盤となるデータベースの読み書き能力のインターフェースが定義されていますが、具体的な実装は含まれておらず、それぞれのデータベース自身によって実装されます。例えば、leveldb や pebble データベースです。Database では、二層のデータ読み書きインターフェースが定義されており、その中で KeyValueStore インターフェースは、最新のブロックや状態など、アクティブで頻繁に変化する可能性のあるデータを保存するために使用されます。AncientStore は、歴史的なブロックデータを処理するために使用され、これらのデータは一度書き込まれるとほとんど変更されることはありません。type Database interface { KeyValueStore AncientStore}// 型 KeyValueStore interface { KeyValueReader, KeyValueWriter, KeyValueStater, KeyValueRangeDeleter Batcher Iteratee Compacter io. Closer}// 型 AncientStore interface { AncientReader AncientWriter AncientStater io. 閉じる}**EVM**EVMはEthereumのこの状態機械の状態遷移関数であり、すべての状態データの更新はEVMを介してのみ行われます。p2pネットワークは取引とブロック情報を受信することができ、これらの情報がEVMによって処理された後、状態データベースの一部となります。EVMは基盤となるハードウェアの違いを隠蔽し、異なるプラットフォームのEVM上でプログラムを実行しても一貫した結果を得られます。これは非常に成熟した設計方式であり、Java言語のJVMも同様の設計です。core/vm/evm.go の EVM 構造は、実行コンテキスト、状態データベースの依存関係など、EVM の全体的な構造と依存関係を定義します。 core/vm/interpreter.go の EVMInterpreter 構造体は、インタプリタの実装を定義し、EVM バイトコードの実行を担当します。 core/vm/contract.go の Contract 構造体は、呼び出し元、コントラクト コード、入力など、コントラクト呼び出しの特定のパラメーターをカプセル化し、core/vm/opcodes.go の現在のすべてのオペコードを定義します。EVMtype EVM struct { // ブロック関連情報を含むブロックコンテキスト Context BlockContext // トランザクション関連情報を含むトランザクションコンテキスト TxContext // アカウント状態へのアクセスと変更に使用される状態データベース StateDB StateDB // 現在の呼び出し深度 int // チェーン構成パラメータ chainConfig \*params. ChainConfig chainRules paramsです。 Rules // EVM Config Config // バイトコードインタプリタインタプリタ \*EVMInterpreter // 実行中止フラグ abort atomic. Bool callGasTemp uint64 // プリコンパイル map[common. Address]プリコンパイル済みコントラクト jumpDests map[common. Hash]bitvec }type EVMInterpreter struct { // EVM が属する EVM インスタンスを指す evm \*EVM // オペコードジャンプテーブルテーブル \*JumpTable // Keccak256 hasher インスタンス、オペコード間で hasher crypto を共有する。 KeccakState // Keccak256 ハッシュ結果バッファ hasherBuf common. Hash // 読み取り専用モードかどうか、読み取り専用モードでは状態変更は許可されません readOnly bool // 最後のCALLの戻りデータは、その後の再利用に使用されます returnData []byte }type Contract struct { // 呼び出し元のアドレス caller common. 住所 // 契約先住所 共通。 アドレス jumpdests map[common. Hash]bitvec analysis bitvec // コントラクトバイトコード Code []byte // コードハッシュ CodeHash common. Hash // 呼び出し入力 []byte // コントラクトに IsDeployment をデプロイするかどうか bool // IsSystemCall を呼び出すかどうか bool // 利用可能なガス gas uint64 // 呼び出し値に付随する ETH の量 \*uint256. int型 }#### **他のモジュールの実装**実行層の機能は、階層的な方法によって実現され、他のモジュールや機能はこの3つのコアコンポーネントを基に構築されています。ここでは、いくつかのコアモジュールを紹介します。eth/protocolsの下には、現在のイーサリアムのp2pネットワークサブプロトコルの実装があります。eth/68およびsnapサブプロトコルは、これらのサブプロトコルはdevp2pの上に構築されています。eth/68はイーサリアムのコアプロトコルで、プロトコル名はeth、68はそのバージョン番号です。そして、このプロトコルの基盤の上にトランザクションプール(TxPool)、ブロック同期(Downloader)、トランザクション同期(Fetcher)などの機能が実装されています。snapプロトコルは新しいノードがネットワークに参加する際にブロックと状態データを迅速に同期するために使用され、新しいノードの起動時間を大幅に短縮することができます。ethdbは、基盤となるデータベースの読み書き機能を提供しますが、イーサリアムプロトコルには多くの複雑なデータ構造があるため、ethdbを介してこれらのデータを直接管理することはできません。したがって、ethdbの上にrawdbとstatedbを実装して、ブロックと状態データをそれぞれ管理しています。EVMはすべてのメインプロセスを貫通し、ブロックの構築であれブロックの検証であれ、EVMを用いてトランザクションを実行する必要があります。### 05\Geth ノード起動プロセスGethの起動は二つの段階に分かれています。第一段階ではノードに必要なコンポーネントとリソースを初期化し、第二段階ではノードを正式に起動し、対外サービスを提供します。! [イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ](https://img.gateio.im/social/moments-010b31482a80a9c45a34cf25ea2cc89e)#### **ノードの初期化**geth ノードを起動する際には、以下のコードが関与します:! [イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ](https://img.gateio.im/social/moments-05135e9c19d879198f87ec00286ceb4d)各モジュールの初期化は以下の通りです:* cmd/geth/main.go: geth ノード起動エントリ* cmd/geth/config.go(makeFullNode): コンフィグをロードし、ノードを初期化します。* node/node.go:イーサリアムノードのコアコンテナを初期化する1. node.rpcstack.go:RPCモジュールを初期化します2. accounts.manager.go:アカウントマネージャーを初期化する* eth/backend.go: イーサリアムのインスタンスを初期化する1. node/node.go OpenDatabaseWithFreezer:chaindbを初期化します2. eth/ethconfig/config.go:コンセンサスエンジンインスタンスの初期化(ここでのコンセンサスエンジンは実際にはコンセンサスに参加せず、コンセンサスレイヤーの結果を検証し、バリデーターの引き出しリクエストを処理します)3. core/blockchain.go: ブロックチェーンの初期化4. core/filterMaps.go: フィルタマップの初期化5. core/txpool/blobpool/blobpool.go: BLOB トランザクション プールを初期化します6. core/txpool/legacypool/legacypool.go: 通常のトランザクションプールを初期化します。7. cord/txpool/locals/tx\_tracker.go:ローカルトランザクション追跡(ローカルトランザクション追跡を有効にする必要があります。ローカルトランザクションは、より高い優先度で処理されます)8. eth/handler.go:プロトコルの Handler インスタンスを初期化する9. miner/miner.go:取引パッキングのモジュールをインスタンス化する(元のマイニングモジュール)10. eth/api\_backend.go:RPCサービスをインスタンス化する11. eth/gasprice/gasprice.go: ガス価格クエリサービスをインスタンス化します。12. internal/ethapi/api.go:P2PネットワークRPC APIをインスタンス化します13. node/node.go(RegisterAPIs):RPC APIを登録します14. node/node.go(RegisterProtocols): Ptotocols for p2p15. ノード/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: エンジン API の登録ノードの初期化は、cmd/geth/config.go の makeFullNode で、次の 3 つのモジュールを中心に行われます! [イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ](https://img.gateio.im/social/moments-ab9c73c26403456c5b38dd4fdf565645)最初のステップでは、node/node.go の Node 構造体を初期化します。これは全体のノードコンテナであり、すべての機能はこのコンテナ内で実行する必要があります。次のステップでは、Ethereum 構造体を初期化します。これには Ethereum のさまざまなコア機能の実装が含まれており、Etherereum も Node に登録する必要があります。三番目のステップは、Node に Engine API を登録することです。その中でノードの初期化は、ノードインスタンスを作成し、その後p2pサーバー、アカウント管理、そして外部に公開されるhttpなどのプロトコルポートを初期化することです。! [イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ](https://img.gateio.im/social/moments-87beedb3183420239be022fb67c99278)Ethereumの初期化は非常に複雑になり、多くのコア機能がここで初期化されます。まず、ethdbが初期化され、ストレージからチェーン設定がロードされ、その後、コンセンサスエンジンが作成されます。ここでのコンセンサスエンジンはコンセンサス操作を実行せず、単にコンセンサス層から返された結果を検証します。もしコンセンサス層で引き出しリクエストが発生した場合も、ここで実際の引き出し操作が完了します。それから、ブロックチェーン構造とトランザクションプールが初期化されます。これが完了すると、トランザクションの同期、ブロックのダウンロードなどを含むすべてのP2Pネットワークリクエストのエントリポイントであるハンドラーが初期化され、イーサリアムの分散型操作の重要なコンポーネントです。 これらが完了すると、eth/68やsnapなど、devp2pに基づいて実装されたいくつかのサブプロトコルがNodeコンテナに登録され、最終的にEthereumがNodeコンテナにライフサイクルとして登録され、Ethereumの初期化が完了します。! [イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ](https://img.gateio.im/social/moments-769461459755f934e50ac478e91a6d53)最後に、Engine APIの初期化は比較的簡単で、Engine APIをノードに登録するだけです。これで、ノードの初期化はすべて完了しました。#### **ノード起動**ノードの初期化が完了したら、ノードを起動する必要があります。ノードの起動プロセスは比較的簡単で、登録済みのRPCサービスとライフサイクルをすべて起動するだけで、ノードは外部にサービスを提供できるようになります。! [イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ](https://img.gateio.im/social/moments-ff5ef98dd75f46be80f5c958e2b1bae2)### 06\まとめイーサリアムの実行層の実装を深く理解する前に、イーサリアム全体についての認識が必要です。イーサリアム全体を取引駆動の状態機として見ることができ、実行層は取引の実行と状態の変化を担当し、コンセンサス層は実行層の動作を促進します。これには、実行層にブロックを生成させ、取引の順序を決定し、ブロックに投票し、ブロックの最終性を確保することが含まれます。この状態機は分散化されているため、p2pネットワークを通じて他のノードと通信し、状態データの一貫性を共同で維持する必要があります。実行レイヤーは、トランザクションの順序を決定する役割を担うのではなく、トランザクションの実行と実行後の状態の変化の記録のみを担当します。 ここでの記録には2つの形式があり、1つはすべての状態変化をブロックの形式で記録する方法、もう1つは現在の状態をデータベースに記録する方法です。 同時に、実行層はトランザクションのエントリポイントでもあり、まだブロックにパックされていないトランザクションはトランザクションプールを介して格納されます。 他のノードがブロック、状態、およびトランザクションデータにアクセスする必要がある場合、実行レイヤーはP2Pネットワークを介してその情報を送信します。実行層には、計算、ストレージ、ネットワークの3つのコアモジュールがあります。計算はEVMの実装に対応し、ストレージはethdbの実装に対応し、ネットワークはdevp2pの実装に対応します。このような全体的な理解を得た後で、各サブモジュールを深く理解することができ、具体的な詳細に迷うことはありません。 ### 07\参照[1][2][3][4][5][6]· 終わり·内容 | レイ編集 & レイアウト | 環環デザイン | デイジー
イーサリアム主流クライアント:Geth全体アーキテクチャ
この記事はGethソースコードシリーズの第一篇であり、このシリーズを通じて、Gethの実装を研究するためのフレームワークを構築します。開発者はこのフレームワークに基づいて、自分が興味のある部分を深く研究することができます。このシリーズは全部で六篇の記事から成り立っており、第一篇では実行層クライアントGethの設計アーキテクチャとGethノードの起動プロセスを研究します。Gethのコード更新は非常に速く、今後見るコードは若干異なる可能性がありますが、全体的な設計は概ね一致しており、新しいコードも同じ考え方で読むことができます。
01\イーサリアムクライアント
イーサリアムのマージアップグレード前は、イーサリアムには1つのクライアントしかなく、トランザクションの実行とブロックチェーンのコンセンサスを担当し、ブロックチェーンが特定の順序で新しいブロックを生成するようにしていました。 マージのアップグレード後、イーサリアムクライアントは実行レイヤーとコンセンサスレイヤーに分かれ、実行レイヤーはトランザクションの実行、状態とデータの維持を担当し、コンセンサスレイヤーはコンセンサス機能の実装を担当し、実行レイヤーとコンセンサスレイヤーはAPIを介して通信します。 実行層とコンセンサス層には独自の仕様があり、クライアントはそれらを異なる言語で実装できますが、対応する仕様に準拠する必要があり、Gethは実行層クライアントの実装です。 現在、メインストリームの実行レイヤーとコンセンサスレイヤーのクライアントには、次の実装があります。
実行レイヤー
コンセンサス層
02\実行レイヤーの概要
イーサリアムの実行層は、取引によって駆動される状態機械と見なすことができます。実行層の最も基本的な機能は、EVMを介して取引を実行し、状態データを更新することです。取引の実行に加えて、ブロックおよび状態データの保存と検証、p2pネットワークの運営、取引プールの維持などの機能もあります。
取引は、ユーザー(またはプログラム)がイーサリアムの実行層規範で定義された形式に従って生成します。ユーザーは取引に署名する必要があります。取引が合法である場合(Nonceが連続している、署名が正しい、ガス料金が十分、ビジネスロジックが正しい)、取引は最終的にEVMによって実行され、イーサリアムネットワークの状態が更新されます。ここでの状態とは、外部アカウントアドレス、コントラクトアドレス、アドレス残高、コードおよびデータを含むデータ構造、データ、およびデータベースの集合を指します。
実行レイヤーは、トランザクションを実行し、実行後のトランザクションの状態を維持する役割を担い、コンセンサス層は、実行するトランザクションを選択する役割を担います。 EVMは、このステートマシンの状態遷移関数であり、関数の入力は、コンセンサス層によって提供される最新のブロック情報、またはP2Pネットワークによってダウンロードされたブロックのいずれかから、複数の場所から得られます。
コンセンサス層と実行層は Engine API を通じて通信します。これは実行層とコンセンサス層の間の唯一の通信方法です。コンセンサス層がブロック生成権を取得すると、Engine API を通じて実行層に新しいブロックを生成させます。ブロック生成権を取得できなかった場合は、最新のブロックを同期させて実行層に検証と実行を行わせ、全体のイーサリアムネットワークとコンセンサスを維持します。
実行層は論理的に6つの部分に分けることができます:
下の図は、実行層の重要なプロセスと各部分の機能を示しています:
! イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ
実行レイヤー (ここではフル ノードについてのみ説明しましょう) には、次の 3 つの主要なプロセスがあります。
03\ソースコードの構造
go-ethereumのコード構造は非常に大きいですが、その中の多くのコードは補助コードやユニットテストに属しています。Gethのソースコードを研究する際には、プロトコルのコア実装にのみ注目する必要があり、各モジュールの機能は以下の通りです。core、eth、ethdb、ノード、p2p、rlp、trie & triedbなどのモジュールに重点を置く必要があります。
04\実行層モジュールの分割
Geth ノードへの外部アクセスには2つの形式があります。1つはRPCを介して、もう1つはConsoleを介してです。RPCは外部のユーザーが使用するために開放するのに適しており、Consoleはノードの管理者が使用するのに適しています。しかし、RPCを通じてでもConsoleを通じてでも、内部で既にパッケージ化された機能を使用しており、これらの機能は階層的な方法で構築されています。
最も外側のレイヤーは、外部アクセスノード用のAPI、実行レイヤーとコンセンサスレイヤー間の通信用のエンジンAPI、外部ユーザーまたはプログラムがトランザクションを送信してブロック情報を取得するためのEth API、P2Pネットワークの状態を取得するためのNet APIなどの機能です。 たとえば、ユーザーがAPIを介してトランザクションを送信した場合、トランザクションは最終的にトランザクションプールに送信され、トランザクションプールを介して管理されます。
API の次のレイヤーでは、コア機能の実装が行われます。これには、取引プール、取引のパッケージ化、ブロックの生成、ブロックと状態の同期などが含まれます。これらの機能はさらに下層の能力に依存する必要があります。たとえば、取引プール、ブロックおよび状態の同期は p2p ネットワークの能力に依存します。ブロックの生成および他のノードから同期されたブロックは、ローカルデータベースに書き込む前に検証される必要があります。これには EVM およびデータストレージの能力が必要です。
! イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ
実行層コアデータ構造
イーサリアム
eth/backend.go の Ethereum 構造体は、全体のイーサリアムプロトコルの抽象であり、基本的にイーサリアムの主要コンポーネントを含んでいますが、EVM は例外であり、取引を処理するたびにインスタンス化され、全ノードの初期化と共に必要ではありません。以下の Ethereum はこの構造体を指します:
type Ethereum struct { // チェーンコンフィグを含むイーサリアムコンフィグ *ethconfig. Config // トランザクション プール、ユーザーのトランザクションが送信された後、トランザクション プールに移動します txPool *txpool。 TxPool // ローカルトランザクションの追跡と管理に使用 localTxTracker *locals. TxTracker // ブロックチェーン構造 blockchain *core. ブロックチェーンは、イーサリアムノードのネットワーク層のコアコンポーネントであり、ブロックの同期、トランザクションのブロードキャスト、受信など、他のノードとのすべての通信を処理し、 // ノードの検出とノードソース管理ディスクミックス *enode を担当するピアノード接続ハンドラーの管理を担当します。 FairMix // ブロックチェーンデータチェーンの永続ストレージを担当しますDb ethdb。 データベース // eventMux *event へのさまざまな内部イベントの発行とサブスクライブの処理を担当します。 TypeMux // エンジンのコンセンサス。 Engine // ユーザー アカウントとキーを管理します accountManager *accounts. Manager // ログフィルタとチャンクフィルタを管理します *filtermaps. FilterMaps // filterMaps を安全にシャットダウンするためのチャネルで、ノードのシャットダウン時にリソースが正しくクリーンアップされるようにします closeFilterMaps chan struct{} // RPC API のバックエンドサポートを提供します APIBackend *EthAPIBackend // PoS では、コンセンサス エンジンと連携してブロック マイナーを検証します *miner. Miner // ノードが受け入れる最低ガス価格は gasPrice *big です。 Int // ネットワーク ID networkID uint64 // ネットワーク関連の RPC サービスを提供し、RPC netRPCService を介してネットワークの状態を照会できるようにします *ethapi. NetAPI // P2P ネットワーク接続の管理、ノードの検出と接続の確立の処理、およびアンダーレイ ネットワーク トランスポート機能の提供 p2pServer *p2p. Server // 変更可能なフィールドへの同時アクセスを保護し、同期をロックします。 RWMutex // ノードが正常にダウンしているかどうかを追跡し、異常シャットダウン後の shutdownTracker の復元を支援します *shutdowncheck. シャットダウントラッカー }
ノード
node/node.goのノードは、さまざまなサービスの運用を管理および調整するためのコンテナとして機能する別のコアデータ構造です。 以下の構造では、ライフサイクルが内部関数のライフサイクルを管理するために使用するライフサイクルフィールドに焦点を当てることが重要です。 たとえば、上記のイーサリアムの抽象化は、ライフサイクルの開始と登録をNodeに依存する必要があります。 このようにして、特定の機能をノードの抽象化から分離し、アーキテクチャ全体のスケーラビリティを差別化する必要があり、devp2pのノードと区別する必要があります。
type Node struct { eventmux *event. TypeMux config *Config // ウォレットとアカウントの管理を担当するアカウントマネージャー accman *accounts. マネージャのログログ。 ロガー keyDir string keyDirTemp bool dirLock *flock. Flock stop chan struct{} // P2P ネットワークインスタンスサーバ *p2p. サーバーのstartStopLock同期。 Mutex // ノードのライフサイクル状態 (初期化済み、実行中、クローズ済み) 状態を追跡します int lock sync. Mutex // 登録されているすべてのバックエンド、サービス、および補助サービスのライフサイクル []Lifecycle // 現在利用可能な API のリスト rpcAPI []rpc. API // RPC http *httpServer ws *httpServer httpAuth *httpServer wsAuth *httpServer ipc *ipcServer inprocHandler *rpc. サーバー・データベース・マップ[*closeTrackingDB]struct{} }
抽象的な次元でイーサリアムの実行層を見ると、イーサリアムは世界コンピュータとして、ネットワーク、計算、ストレージの3つの部分を含む必要があります。したがって、イーサリアムの実行層におけるこれら3つの部分に対応するコンポーネントは次のとおりです:
devp2p
イーサリアムは本質的に分散型システムであり、各ノードはp2pネットワークを介して他のノードと接続されています。イーサリアムにおけるp2pネットワークプロトコルの実装はdevp2pです。
devp2p には 2 つのコア機能があります: 1 つはノード検出で、ノードがネットワークに接続するときに他のノードと接続できるようにします。 もう一つはデータ通信サービスで、他のノードと連絡を取り合った後、好きなようにデータをやり取りすることができます。
p2p/enode/node.go の Node 構造は、p2p ネットワーク内のノードを表します。 Record構造には、ID情報(ノードのIDで使用される署名アルゴリズム、公開鍵)、ネットワーク情報(IPアドレス、ポート番号)、サポートされているプロトコル情報(eth/68やsnapプロトコルのサポートなど)、その他のカスタム情報など、RLPでエンコードされ、EIP-778で定義されているノードの詳細のキーと値のペアが格納されます。
type Node struct { // ノードのさまざまなプロパティを含むノードレコード r enr. レコード // ノードの一意の識別子、32 バイト長 id ID // ホスト名 ノードの DNS 名をトレースします hostname string // ノードの IP アドレス ip netip. Addr // UDP ポート udp uint16 // TCP ポート tcp uint16 }// enr. レコードタイプ Record struct { // シリアル番号 seq uint64 // 署名署名 []byte // RLP エンコードされたレコード raw []byte // すべてのキーと値のペアのソートされたリスト []pair }
p2p/discover/table.go における Table 構造体は devp2p におけるノード発見プロトコルのコアデータ構造であり、ネットワーク内のノード情報を維持・管理するために Kademlia に類似した分散ハッシュテーブルを実装しています。
printf("type Table struct { mutex sync. Mutex // 既知のノードバケットを距離でインデックス化 [nBuckets]*bucket // ブートストラップノードナーサリ []*enode. ノード rand reseedingRandom ips netutil。 DistinctNetSet revalidation tableRevalidation // 既知のノードのデータベース db *enode. DB net transport cfg Configログログ。 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(*バケツ、*tableNode)} ワールド!」 );
ethdb
ethdbはEthereumデータストレージの抽象を完了し、統一されたストレージインターフェースを提供します。基盤となる具体的なデータベースはleveldb、pebble、またはその他のデータベースである可能性があります。インターフェースレベルでの統一を維持する限り、多くの拡張が可能です。
一部のデータ(例えばブロックデータ)はethdbインターフェースを介して直接基盤データベースに読み書きできますが、他のデータストレージインターフェースはethdbを基盤に構築されています。たとえば、データベースの大部分のデータは状態データであり、これらのデータはMPT構造に組織されます。Gethでの対応する実装はtrieです。ノードが実行される過程で、trieデータは多くの中間状態を生成し、これらのデータは直接ethdbを介して読み書きできず、triedbを使用してこれらのデータと中間状態を管理する必要があります。最終的にはethdbを介して永続化されます。
ethdb/database.go において、基盤となるデータベースの読み書き能力のインターフェースが定義されていますが、具体的な実装は含まれておらず、それぞれのデータベース自身によって実装されます。例えば、leveldb や pebble データベースです。Database では、二層のデータ読み書きインターフェースが定義されており、その中で KeyValueStore インターフェースは、最新のブロックや状態など、アクティブで頻繁に変化する可能性のあるデータを保存するために使用されます。AncientStore は、歴史的なブロックデータを処理するために使用され、これらのデータは一度書き込まれるとほとんど変更されることはありません。
type Database interface { KeyValueStore AncientStore}// 型 KeyValueStore interface { KeyValueReader, KeyValueWriter, KeyValueStater, KeyValueRangeDeleter Batcher Iteratee Compacter io. Closer}// 型 AncientStore interface { AncientReader AncientWriter AncientStater io. 閉じる}
EVM
EVMはEthereumのこの状態機械の状態遷移関数であり、すべての状態データの更新はEVMを介してのみ行われます。p2pネットワークは取引とブロック情報を受信することができ、これらの情報がEVMによって処理された後、状態データベースの一部となります。EVMは基盤となるハードウェアの違いを隠蔽し、異なるプラットフォームのEVM上でプログラムを実行しても一貫した結果を得られます。これは非常に成熟した設計方式であり、Java言語のJVMも同様の設計です。
core/vm/evm.go の EVM 構造は、実行コンテキスト、状態データベースの依存関係など、EVM の全体的な構造と依存関係を定義します。 core/vm/interpreter.go の EVMInterpreter 構造体は、インタプリタの実装を定義し、EVM バイトコードの実行を担当します。 core/vm/contract.go の Contract 構造体は、呼び出し元、コントラクト コード、入力など、コントラクト呼び出しの特定のパラメーターをカプセル化し、core/vm/opcodes.go の現在のすべてのオペコードを定義します。
EVMtype EVM struct { // ブロック関連情報を含むブロックコンテキスト Context BlockContext // トランザクション関連情報を含むトランザクションコンテキスト TxContext // アカウント状態へのアクセスと変更に使用される状態データベース StateDB StateDB // 現在の呼び出し深度 int // チェーン構成パラメータ chainConfig *params. ChainConfig chainRules paramsです。 Rules // EVM Config Config // バイトコードインタプリタインタプリタ *EVMInterpreter // 実行中止フラグ abort atomic. Bool callGasTemp uint64 // プリコンパイル map[common. Address]プリコンパイル済みコントラクト jumpDests map[common. Hash]bitvec }type EVMInterpreter struct { // EVM が属する EVM インスタンスを指す evm *EVM // オペコードジャンプテーブルテーブル *JumpTable // Keccak256 hasher インスタンス、オペコード間で hasher crypto を共有する。 KeccakState // Keccak256 ハッシュ結果バッファ hasherBuf common. Hash // 読み取り専用モードかどうか、読み取り専用モードでは状態変更は許可されません readOnly bool // 最後のCALLの戻りデータは、その後の再利用に使用されます returnData []byte }type Contract struct { // 呼び出し元のアドレス caller common. 住所 // 契約先住所 共通。 アドレス jumpdests map[common. Hash]bitvec analysis bitvec // コントラクトバイトコード Code []byte // コードハッシュ CodeHash common. Hash // 呼び出し入力 []byte // コントラクトに IsDeployment をデプロイするかどうか bool // IsSystemCall を呼び出すかどうか bool // 利用可能なガス gas uint64 // 呼び出し値に付随する ETH の量 *uint256. int型 }
他のモジュールの実装
実行層の機能は、階層的な方法によって実現され、他のモジュールや機能はこの3つのコアコンポーネントを基に構築されています。ここでは、いくつかのコアモジュールを紹介します。
eth/protocolsの下には、現在のイーサリアムのp2pネットワークサブプロトコルの実装があります。eth/68およびsnapサブプロトコルは、これらのサブプロトコルはdevp2pの上に構築されています。
eth/68はイーサリアムのコアプロトコルで、プロトコル名はeth、68はそのバージョン番号です。そして、このプロトコルの基盤の上にトランザクションプール(TxPool)、ブロック同期(Downloader)、トランザクション同期(Fetcher)などの機能が実装されています。snapプロトコルは新しいノードがネットワークに参加する際にブロックと状態データを迅速に同期するために使用され、新しいノードの起動時間を大幅に短縮することができます。
ethdbは、基盤となるデータベースの読み書き機能を提供しますが、イーサリアムプロトコルには多くの複雑なデータ構造があるため、ethdbを介してこれらのデータを直接管理することはできません。したがって、ethdbの上にrawdbとstatedbを実装して、ブロックと状態データをそれぞれ管理しています。
EVMはすべてのメインプロセスを貫通し、ブロックの構築であれブロックの検証であれ、EVMを用いてトランザクションを実行する必要があります。
05\Geth ノード起動プロセス
Gethの起動は二つの段階に分かれています。第一段階ではノードに必要なコンポーネントとリソースを初期化し、第二段階ではノードを正式に起動し、対外サービスを提供します。
! イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ
ノードの初期化
geth ノードを起動する際には、以下のコードが関与します:
! イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ
各モジュールの初期化は以下の通りです:
ノードの初期化は、cmd/geth/config.go の makeFullNode で、次の 3 つのモジュールを中心に行われます
! イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ
最初のステップでは、node/node.go の Node 構造体を初期化します。これは全体のノードコンテナであり、すべての機能はこのコンテナ内で実行する必要があります。次のステップでは、Ethereum 構造体を初期化します。これには Ethereum のさまざまなコア機能の実装が含まれており、Etherereum も Node に登録する必要があります。三番目のステップは、Node に Engine API を登録することです。
その中でノードの初期化は、ノードインスタンスを作成し、その後p2pサーバー、アカウント管理、そして外部に公開されるhttpなどのプロトコルポートを初期化することです。
! イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ
Ethereumの初期化は非常に複雑になり、多くのコア機能がここで初期化されます。まず、ethdbが初期化され、ストレージからチェーン設定がロードされ、その後、コンセンサスエンジンが作成されます。ここでのコンセンサスエンジンはコンセンサス操作を実行せず、単にコンセンサス層から返された結果を検証します。もしコンセンサス層で引き出しリクエストが発生した場合も、ここで実際の引き出し操作が完了します。それから、ブロックチェーン構造とトランザクションプールが初期化されます。
これが完了すると、トランザクションの同期、ブロックのダウンロードなどを含むすべてのP2Pネットワークリクエストのエントリポイントであるハンドラーが初期化され、イーサリアムの分散型操作の重要なコンポーネントです。 これらが完了すると、eth/68やsnapなど、devp2pに基づいて実装されたいくつかのサブプロトコルがNodeコンテナに登録され、最終的にEthereumがNodeコンテナにライフサイクルとして登録され、Ethereumの初期化が完了します。
! イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ
最後に、Engine APIの初期化は比較的簡単で、Engine APIをノードに登録するだけです。これで、ノードの初期化はすべて完了しました。
ノード起動
ノードの初期化が完了したら、ノードを起動する必要があります。ノードの起動プロセスは比較的簡単で、登録済みのRPCサービスとライフサイクルをすべて起動するだけで、ノードは外部にサービスを提供できるようになります。
! イーサリアムメインストリームクライアント:ゲス全体のアーキテクチャ
06\まとめ
イーサリアムの実行層の実装を深く理解する前に、イーサリアム全体についての認識が必要です。イーサリアム全体を取引駆動の状態機として見ることができ、実行層は取引の実行と状態の変化を担当し、コンセンサス層は実行層の動作を促進します。これには、実行層にブロックを生成させ、取引の順序を決定し、ブロックに投票し、ブロックの最終性を確保することが含まれます。この状態機は分散化されているため、p2pネットワークを通じて他のノードと通信し、状態データの一貫性を共同で維持する必要があります。
実行レイヤーは、トランザクションの順序を決定する役割を担うのではなく、トランザクションの実行と実行後の状態の変化の記録のみを担当します。 ここでの記録には2つの形式があり、1つはすべての状態変化をブロックの形式で記録する方法、もう1つは現在の状態をデータベースに記録する方法です。 同時に、実行層はトランザクションのエントリポイントでもあり、まだブロックにパックされていないトランザクションはトランザクションプールを介して格納されます。 他のノードがブロック、状態、およびトランザクションデータにアクセスする必要がある場合、実行レイヤーはP2Pネットワークを介してその情報を送信します。
実行層には、計算、ストレージ、ネットワークの3つのコアモジュールがあります。計算はEVMの実装に対応し、ストレージはethdbの実装に対応し、ネットワークはdevp2pの実装に対応します。このような全体的な理解を得た後で、各サブモジュールを深く理解することができ、具体的な詳細に迷うことはありません。
07\参照
[1]
[2]
[3]
[4]
[5]
[6]
· 終わり·
内容 | レイ
編集 & レイアウト | 環環
デザイン | デイジー