レッスン0 — P2P の基礎(devp2p、libp2p、peer discovery)
問い
新しい reth ノードを起動した直後 = peer ゼロ、ブロックゼロ、state ゼロ。数秒後にはどこかから header をダウンロードしている — peer はどこから来たか? まだネットワーク上にいないノードが、そのネットワークに peer を尋ねられるはずがない。これが bootstrapping 問題、P2P 層が他の何かを始める前に解決しなければならない。
原理(最小モデル)
- 2 層構造. Discovery(peer を見つける、discv4 / discv5 = Kademlia DHT)+ Transport(peer と話す、RLPx = 暗号化 TCP)。
- Bootstrapping は bootnode で解決. chainspec にハードコードされた既知 IP、1 つ接続 → 他 peer を教えてもらう → DHT が引き継ぐ。
- devp2p = Ethereum 専用スタック. discv5(peer discovery)+ RLPx(暗号化 TCP)+ eth/68(block + tx gossip)。
- discv5 / Kademlia の「近さ」= ノード ID 上の XOR distance. トポロジカル、地理的意味なし。ID 空間で近い同士が効率的に互いを見つけられる = O(log N) ホップ。
- ENR = Ethereum Node Record. ID + IP + port + capability。Discovery query は ENR を返す。
- RLPx ≈ Ethereum 版 TLS. ECDH + ECDSA + AES-CTR + RLP frame。peer ID = 公開鍵そのもの、中央 CA なし → TLS を使わない理由。
- eth/68 が tx を hash で先にアナウンス. 全ノード全 tx 再ブロードキャストの増幅問題を回避。
- libp2p = マルチチェーン代替. discovery / transport / encryption / multiplexing を独立分離。Polkadot、IPFS、Solana、Lighthouse 採用。Reth は歴史的経緯で devp2p。
具体例
2 層プロトコル:
| 層 | 役割 | Ethereum での実装 |
|---|---|---|
| Discovery | 「Peer を見つける」 | discv4 / discv5(Kademlia DHT) |
| Transport | 「Peer と話す」 | RLPx(暗号化 TCP) |
Reth ノード起動時のデータフロー:
flowchart LR
Boot["Bootnode"] -->|seed peer list| You["自 Reth ノード"]
You -->|discv5 ping| Peer1["Peer 1"]
You -->|discv5 ping| Peer2["Peer 2"]
Peer1 -->|RLPx ハンドシェイク| You
You -->|eth/68: ブロック、txs| Peer1
You -->|eth/68: ブロック、txs| Peer2
devp2p の 3 要素:
- discv5: Kademlia DHT 経由 peer discovery(ノード探し用の分散ハッシュテーブル)
- RLPx: 暗号化・認証付き TCP transport
- eth/68: ブロック + transaction gossip サブプロトコル
eth/68 メッセージ:
| メッセージ | 目的 |
|---|---|
| Status | Handshake — fork バージョン、chain ID、head |
| NewBlock | 新ブロックアナウンス |
| BlockBodies | ブロックボディ要求 / 応答 |
| NewPooledTransactionHashes | Pending tx(hash のみ)アナウンス |
| PooledTransactions | フル tx ボディ要求 |
| Receipts | Receipt 要求 / 応答 |
libp2p 採用例:
- Polkadot(libp2p ベース)
- IPFS(発祥地)
- Solana(transport カスタム、概念踏襲)
- Lighthouse(Ethereum consensus client)
失敗例(誤解)
「Kademlia の『近さ』は地理的」— 間違い。ノード ID 上の XOR distance、トポロジカル。地理的意味なし。ID 空間で近いノード同士が効率的に互いを見つけられる 数学的性質が O(log N) ホップを成立させる。
「Ethereum は TLS を使えば良い」— 間違い。devp2p の前提は peer ID = 公開鍵そのもの、中央 CA なし。TLS は CA 前提なので合わない。歴史的経緯(2015 年以前)+ 中央 CA なし設計の合致で RLPx 独自実装。
「全 tx を全ノードに再ブロードキャスト」— 間違い。eth/68 は tx を hash で先にアナウンス → peer は未保有なら body を要求。増幅問題を根本から潰す。
🛑 予測。 Reth ノードをゼロから sync させる。最初に見つかるのは peer かブロックか? 既知 peer 一つもない状態でどうやって peer を見つける?(答え: peer が先、ブロックは後。Bootnode = chainspec にハードコードされた既知 IP → ノード起動時にまず bootnode に接続 → bootnode が「これらの peer を試せ」とリストを返す → 各 peer に discv5 ping → 接続できた peer から更に Kademlia 経由で peer 探索 → 数十 peer 集まったら eth/68 で block 取得開始。bootnode = 鶏と卵の解、まず人間が中央集権的に提供したリストを起点に分散ネットワーク参加。chain ローンチ時の信頼基盤。)
ステップで組み立てる
Step 1: 2 層構造を即答
Discovery(discv5)+ Transport(RLPx)。
Step 2: Bootnode が解く問題
「Peer を見つけるには peer が必要」のジレンマ → chainspec に既知 IP ハードコード → 起点。
Step 3: Kademlia の「近さ」を理解
ノード ID の XOR distance、トポロジカル、O(log N) ホップ。
Step 4: RLPx ≈ TLS の違い
ECDH + ECDSA + AES-CTR + RLP。peer ID = 公開鍵、中央 CA なし → TLS 不採用。
Step 5: eth/68 の hash-first 設計
NewPooledTransactionHashes(hash アナウンス)→ PooledTransactions(必要時のみ body 要求)。
Step 6: libp2p との対比
devp2p = Ethereum 専用束ね / libp2p = マルチチェーン用にモジュール分離(discovery / transport / encryption / multiplexing)。Reth は歴史的経緯で devp2p。
Step 7: Reth ベース chain の選択肢
devp2p そのまま / カスタムサブプロトコル追加(tempo/1 など)/ libp2p sidecar 追加。
答え合わせ
- Kademlia の「近さ」が重要な理由: 単に routing のためではなく 数学的性質。ID 空間で近いノード同士が 効率的に互いを見つけられる → O(log N) ホップで任意 peer 探索可能(数百万ノード規模でスケール)。「近い」= 「ID 空間トポロジ上の局所性」。これがなければ Discovery は線形探索になる。
- Bootstrap 問題の構造: 「Peer を見つけるには peer が必要」のジレンマ = チェーンの最初は人間が解決する。Bootnode = chainspec にハードコードされた既知 IP リスト → ノード起動時の信頼起点。Bootnode が落ちると新規 join 不可だが、複数 bootnode と DNS-based fallback で冗長化。完全分散化は到達不能、Bootstrap は中央集権から始まる。
- eth/68 の hash-first 設計の効果: 「N peer × M tx × 1 リレイ = N×M」を「N peer × M tx × hash 1 つ + 必要時のみ body 取得」に削減 → 帯域 ~32 byte hash で済む。全 peer が全 body を不要に持つ問題を回避。Mempool 同期コストが O(M^2) から O(M log N) に。
合格基準
- 2 層(Discovery + Transport)と devp2p の 3 要素を即答できる。
- Bootnode が解く bootstrap 問題を 1 文で説明できる。
- Kademlia の XOR distance + O(log N) ホップの意味を言える。
- RLPx と TLS の違い(peer ID = 公開鍵、CA なし)を言える。
- eth/68 の hash-first 設計が回避する増幅問題を計算できる。
まとめ(3行)
- P2P 2 層構造(Discovery = discv5 / Kademlia DHT + Transport = RLPx)、Bootstrap 問題は bootnode で解決(chainspec ハードコード)。
- devp2p = Ethereum 専用束ね(discv5 + RLPx + eth/68)、libp2p = マルチチェーン用モジュール分離(Polkadot / Lighthouse / IPFS / Solana)。
- eth/68 の hash-first 設計で全 tx 再ブロードキャストの増幅問題を回避、Reth ベース chain はカスタムサブプロトコル追加で chain 固有 gossip を実現。