ビットコインの​ P2P ネットワーク設計 — ノード発見、​メッセージ中継、​ブロック伝播

淡く光るノードが線で結ばれた網目状のネットワーク図。起点ノードから同心円状の波が広がり、ノード間を破線の矢印とパケットのアイコンが行き来し、平文接続と暗号化接続を南京錠の開閉で対比させたパネルが添えられている

はじめに

本ページは設計文書シリーズL1 #1 — P2P ネットワーク設計 である。ネットワーク層を端から端まで解説する。ノードがどのように互いを発見し、メッセージをどのように交換し、トランザクションとブロックがピアツーピアのゴシップネットワークをどのように伝播するかを扱う。

ネットワーク層は合意形成層、トランザクション層、ブロック層の下に位置する。他のすべてが動作するためのトランスポートを提供する。信頼できるピアツーピア通信がなければ、合意形成設計トランザクション設計ブロック・チェーン設計の各ページに記述される決定論的検証規則は、処理すべきデータを持たないことになる。

サトシ時代の実装(v0.1、2009 年 1 月)と現行の Bitcoin Core(v27 以降基準)で挙動が異なる場合は、両方を記す。

1. ネットワークトポロジー

ビットコインは非構造的ゴシップネットワークを用いる。ノードは TCP 接続のランダムなメッシュを形成し、データをピアに中継し、ピアはさらにそのピアに中継する。中央サーバー、ルーティングテーブル、分散ハッシュテーブル (DHT)、ノード間の階層構造は存在しない。すべてのフルノードは等しく権威を持つ。

ノード A

ノード B

ノード C

ノード D

ノード E

ノード F

ノード G

ノード H

特性設計上の選択
構造非構造的ランダムグラフ — DHT なし、スーパーノード階層なし
ノードあたりの接続数各ノードが少数のピアを維持(既定: v27 以降で出方向 11 + 入方向最大 125)
中継モデル蓄積転送型ゴシップ — 各ノードが中継前に独立して検証
冗長性メッセージは複数の経路を伝播する。単一のリンクが不可欠ということはない
分断耐性ランダムなピア選択が標的型ネットワーク分割を困難にする

ゴシップであり構造化ルーティングでない理由。 DHT や階層的トポロジーはメッセージの冗長性を減らすが、単一障害点も生み出し、ネットワークの分断が容易になる。ビットコインのフラットなゴシップモデルは、攻撃者がノードの見る情報を制御するにはそのピアの大部分を侵害しなければならないことを保証する。これが日食攻撃耐性の基盤である。

2. ノード発見

ネットワークに新規参加するノードはブートストラップ問題に直面する。最低 1 つの既存ピアを見つける必要があるが、ネットワークの構成員に関する事前知識を持たない。

発見メカニズム

メカニズム時代仕組み
IRC ブートストラップv0.1 (2009 年)ノードが特定の IRC チャネル(irc.lfnet.org の #bitcoin)に参加し、IP アドレスを告知した。他のノードはチャネルを読んでピアを発見した。v0.8.2 (2013 年) で廃止。
ハードコードされたシードノードv0.1 → 現在バイナリにコンパイルされた信頼性の高い既知 IP アドレスの一覧。DNS シードとキャッシュ済みピアが利用不能な場合の最終手段。
DNS シードv0.6 以降 (2012 年)ホスト名(例: seed.bitcoin.sipa.be)が現在アクティブなノードの IP アドレスに解決される。現行 Bitcoin Core の主要なブートストラップ手段。
addr / addrv2 中継v0.1 → 現在接続済みピアが、既知の他のノードの IP アドレスを含む addr メッセージを交換する。addrv2 (BIP 155、v22.0 以降) は Tor v3、I2P、CJDNS アドレスに対応を拡張。
ローカルピアデータベースv0.1 → 現在ノードが既知のピアアドレスを peers.dat に永続化し、再起動時に再接続を試みる。正常に動作するノードは時間とともに数千のアドレスを蓄積する。

ブートストラップ手順(v27 以降基準)

あり

なし

あり

なし

ノード起動

peers.dat に

アドレスあり?

キャッシュ済みピアに

接続試行

DNS シードに

問い合わせ

1 ピア以上に

接続できた?

接続済みピアから

addr メッセージを要求

返されたアドレスに

接続

安定ピア集合

確立

ハードコードシード

(最終手段)

サトシ時代と v27 以降基準の比較。 元の v0.1 クライアントは主要な発見メカニズムとして IRC に依存していた。これは単純だが、IRC サーバーのダウンタイムやチャネル追放に脆弱な中央集権的アプローチであった。現行の Bitcoin Core は独立したコミュニティメンバーが運営する DNS シードで IRC を置き換えている。DNS シード運営者はネットワークを継続的に探索するクローラーソフトウェアを動作させており、DNS レコードには現在到達可能で互換性のあるプロトコルバージョンを実行しているノードのみが反映される。

3. 接続管理

各ノードは 2 種類の TCP 接続を維持する。ノードが開始する出方向接続と、他のノードがノードに対して開始する入方向接続である。

接続種別方向既定上限(v27 以降)目的
全中継出方向出方向8トランザクションとブロックを中継するための主要ピア
ブロック中継専用出方向出方向2ブロックのみを中継(トランザクション/addr 中継なし)。メモリープール情報を漏洩せずにブロック接続性を向上
フィーラー出方向(短命)同時に 1候補アドレスが到達可能かを検査。ハンドシェイク成功後即座に切断
入方向入方向最大 125他のノードからの接続。ノードは誰が接続するかを制御しない
アンカー出方向(永続)2(ブロック中継専用集合から)再起動をまたいで保存され、最低 2 つの信頼できる出方向ピアを維持。再起動時の日食攻撃に抵抗

出方向と入方向: 設計による非対称性。 ノードは自身の出方向接続を入方向接続よりも信頼する。出方向ピアは自分自身が選んだものだからである。ノードを孤立させたい攻撃者(日食攻撃)が取れる道は二つしかない。すべての出方向ピアを制御するか、攻撃者制御の入方向接続でノードを溢れさせるかである。前者を果たすには、ノードのアドレス選択を予測または操作できなければならない。出方向数の少なさ(合計 10)と独立したアドレス選択アルゴリズムが、これを困難にしている。後者は入方向の退去ロジックによって維持コストがかさむ。

退去

ノードの入方向スロットが満杯の状態で新しい入方向接続が到着すると、ノードは既存ピアの 1 つを切断するかどうかを決定する退去アルゴリズムを実行する。このアルゴリズムは望ましい特性を持つピアを保護する:

  • 低レイテンシ(最近有用なデータを送信した)
  • 長い接続期間
  • ネットワークグループの多様性(異なる /16 サブネット、異なる自律システム)
  • 最近有効なブロックまたはトランザクションを中継した

この多様性保持型退去は、攻撃者がノードの入方向スロットを独占するコストを高くする。攻撃者の接続は、保護されるすべての次元で正直なピアに同時に勝つことが難しいためである。

4. メッセージプロトコル

ピア間のすべての通信はバイナリメッセージプロトコルを使用する。すべてのメッセージは 24 バイトのヘッダー(4 バイトのネットワークマジック + 12 バイトのコマンド名 + 4 バイトのペイロード長 + 4 バイトのチェックサム)に続くペイロードで構成される。

バージョンハンドシェイクとブロック中継

ノード B(応答側)ノード A(開始側)ノード B(応答側)ノード A(開始側)TCP 接続確立ハンドシェイク完了 — ピア稼働中後刻 — 新ブロック発見version(プロトコル版、サービス、最良ブロック高)version(プロトコル版、サービス、最良ブロック高)verackveracksendcmpct(コンパクトブロック対応を通知)sendcmpctcmpctblock(ヘッダー + 短縮 tx ID)メモリープールからブロックを再構築getblocktxn(不足トランザクションを要求)blocktxn(不足トランザクション)完全ブロックを検証

主要メッセージ型

メッセージペイロード役割
versionプロトコルバージョン、サービスビットマスク、最良ブロック高、ノードのタイムスタンプハンドシェイクを開始。ピア間で機能を交換
verackversion メッセージを確認。ハンドシェイクを完了
invインベントリベクター(型 + ハッシュ)のリストデータ送信なしで既知のトランザクションまたはブロックを告知
getdataインベントリベクターのリスト告知された項目の完全データを要求
tx直列化されたトランザクションgetdata に応じてトランザクションを配信
block直列化された完全ブロック完全ブロックを配信(従来型中継モード)
headers最大 2,000 件のブロックヘッダーヘッダー先行同期用にブロックヘッダーを配信
getheadersロケーターハッシュ + 停止ハッシュブロックヘッダーの範囲を要求
cmpctblockヘッダー + 短縮トランザクション ID (BIP 152)コンパクトブロック告知。受信側がメモリープールから再構築
getblocktxnブロックハッシュ + 不足トランザクションのインデックス受信側のメモリープールに存在しなかったトランザクションを要求
blocktxnブロックハッシュ + 不足トランザクションgetblocktxn で要求されたトランザクションを配信
addr / addrv2タイムスタンプ付きピアアドレスのリストネットワーク全体に既知のピアアドレスを伝播
ping / pongナンスレイテンシ測定と生存確認
feefilter最低手数料率(サトシ/kB)この手数料率を下回るトランザクションを中継しないようピアに通知
sendheadersinv ではなく headers メッセージで新規ブロックを告知するようピアに要求

サトシ時代と v27 以降基準の比較。 v0.1 プロトコルは 12 種のメッセージ型を定義し、完全ブロックをすべてのピアに中継していた。現行の Bitcoin Core(v27 以降基準)は 27 種以上のメッセージ型に対応し、既定の中継方式としてコンパクトブロック (BIP 152) を使用する。メモリープールが重複する接続良好なノードでは、ブロック中継の帯域幅を約 90% 削減する。

5. トランザクション中継

ノードがトランザクションをメモリープールに受理すると、ゴシップネットワークを通じてそのトランザクションをピアに告知する。

inv (txid)

inv (txid)

getdata

tx(完全

トランザクション)

検証 → メモリープール

inv (txid)

getdata

tx

ウォレットが

トランザクションを送信

ノード A:

検証 → メモリープールに受理

ノード B

ノード C

ノード D

中継プロセスは告知後要求パターンに従う:

  1. 告知。 ノードがトランザクションのハッシュを含む inv メッセージを各ピアに送信する。
  2. 要求。 このハッシュを見たことがないピアが getdata で応答する。
  3. 配信。 告知側のノードが完全な tx メッセージを送信する。
  4. 検証と伝播。 受信側のピアがトランザクションを独立して検証する。有効であれば自身のメモリープールに受理し、そのピアに対して告知サイクルを繰り返す。

プライバシー保護型中継。 ネットワーク観察者がトランザクションを発信元ノードまで追跡するのを防ぐため、Bitcoin Core は各ピアへのトランザクション告知前にランダムな遅延を追加する(ポアソン分布タイマー)。各ピアはわずかに異なる時点で、場合によっては異なる先行中継者集合から告知を受け取るため、発信元の推定が困難になる。

手数料フィルター。 feefilter メッセージ (BIP 133) により、ノードは自身の最低許容手数料率をピアに通知できる。ピアはその閾値を下回るトランザクションの告知を省略し、受信側ノードがどのみち拒否するトランザクションに帯域幅を浪費しなくなる。

孤児トランザクション。 親トランザクションが不明な入力を参照するトランザクションは孤児と呼ばれる。ノードは孤児を限定的なキャッシュに保持する。親トランザクションが後から到着すれば、孤児は再評価される。キャッシュが満杯になると、最も古い孤児が退去される。このメカニズムは順序外で到着するトランザクションに対応しつつ、無効な孤児の大量送信によるメモリー枯渇を防止する。

6. ブロック伝播

ブロック伝播はネットワーク内で最もレイテンシに敏感な操作である。伝播が遅いと失効ブロック率が上昇し、接続状態の良いマイナーに有利になり、マイニング競争の公平性を損なう。

伝播モード

コンパクトブロック (BIP 152, v0.13 以降)

あり

なし

マイナーが

ブロック発見

cmpctblock

(ヘッダー + 短縮 tx ID)

約 20 kB

ピアがメモリープール

からブロック再構築

全 tx

あり?

ブロックを検証

getblocktxn

(不足分を要求)

blocktxn

(不足 tx のみ)

ヘッダー先行同期 (v0.10 以降)

ノードが IBD 開始

getheaders

(ヘッダーチェーンを

要求)

headers

(最大 2,000 ヘッダー)

ヘッダーチェーン構築、

PoW を検証

getdata(

複数ピアから

並列ブロック要求)

チェーン順に

完全ブロック検証

従来: 完全ブロック中継 (v0.1)

マイナーが

ブロック発見

inv(

ブロックハッシュ)

を全ピアへ

ピア: getdata

block(完全直列化

ブロック)

約 1〜2 MB

ピアが検証し

中継

モードブロックあたり帯域幅レイテンシ使用場面
従来の完全ブロック中継約 1〜2 MB(ブロック全体)高い — 完全な直列化 + 転送サトシ時代 (v0.1)。フォールバックとして引き続き利用可能
ヘッダー先行同期ヘッダー: 各 80 バイト、ブロック: 完全サイズだが並列要求中程度 — 並列性が完全ブロックのサイズを補償初期ブロックダウンロード (IBD) — ジェネシスからチェーン先端までの同期
コンパクトブロック (BIP 152)標準的に約 20 kB(ヘッダー + 短縮 ID)。不足トランザクションはオンデマンド低い — 大半のトランザクションは既にメモリープール内同期済みノード間の定常的ブロック中継(v27 以降の既定)

コンパクトブロックが約 90% 節約を達成する仕組み。 2 つのピアのメモリープールが類似している場合(接続良好なノードでは一般的)、受信側はブロック内のトランザクションの大半を既に持っている。cmpctblock メッセージはブロックヘッダーと各トランザクションの 6 バイト短縮 ID のみを送信する。受信側はこれらの ID をメモリープールと照合し、ローカルでブロックを再構築し、不足しているわずかなトランザクションのみを要求する。2,000 件のトランザクションを含むブロックの場合、cmpctblock メッセージは 1〜2 MB ではなく約 20 kB となる。

高帯域幅モードと低帯域幅モード (BIP 152)。 コンパクトブロックは 2 つのモードで動作する。高帯域幅モードでは、送信側ピアは検証完了と同時に cmpctblock をプッシュする。受信側が inv/getdata で要求するのを待たない。ノードは通常 3 つのピアを高帯域幅モードに指定し、新規ブロックの中継レイテンシを最小化する。低帯域幅モードでは、まず inv を送る標準的な告知後要求パターンを使用し、残りのピアとの間でレイテンシを帯域幅節約と引き換えにする。

7. トランスポート層: 平文と暗号化

サトシ時代の設計では、すべてのピアツーピア通信が平文で送信されていた。ISP、国家レベルの敵対者、ローカルネットワーク上の中間者など、あらゆるネットワーク観察者がすべてのメッセージを読み取り、ノードが中継しているトランザクションを特定し、ネットワークトポロジーをマッピングし、メッセージを選択的に遮断または遅延させることができた。

BIP 324 v2 トランスポート(v26.0 以降で対応、v27 以降で既定有効)は、双方がこれに対応するピア間で日和見的な暗号化トランスポート層を導入する。

側面サトシ時代 (v0.1)v27 以降基準 (BIP 324)
トランスポート平文 TCP日和見的暗号化トランスポート(v2 プロトコル)
機密性なし — すべてのメッセージが任意のネットワーク観察者に可読メッセージを ChaCha20-Poly1305 で暗号化。観察者には内容が不透明
認証なし任意のセッション ID 比較により手動ピア認証が可能。中間者攻撃に対抗
パケット構造平文のコマンド名を含む固定 24 バイトヘッダー可変長暗号化パケット。コマンド ID は 1 バイト(外部から読み取り不能)
検出可能性ネットワークマジックバイトによりビットコイン通信として容易に識別可能ランダムバイトに見えるよう設計。トラフィック分析分類に抵抗
後方互換性該当なしノードは接続開始時に v2 を交渉。ピアが非対応であれば v1(平文)にフォールバック

暗号化トランスポートが重要な理由。 平文通信は、ビットコインの設計が意図していない 3 つの能力をネットワーク層の敵対者に与える: (1) 監視。 ISP がノードの中継するトランザクションを記録し、IP アドレスと関連付けられる。 (2) 標的型検閲。 国家がプロトコルの特徴的なヘッダーをパターン照合してビットコイン通信を特定し遮断できる。 (3) 中間者操作。 中間者がブロックやトランザクションを選択的に遅延させ、特定のマイナーを有利にしたり特定のノードを分断したりできる。暗号化トランスポートはこれらの脅威をすべて排除するわけではない(持続的な敵対者は依然として接続パターンを観察できる)が、そのコストを大幅に引き上げる。

8. 二時代比較

機能サトシ時代 (v0.1、2009 年 1 月)現行 Bitcoin Core、v27 以降基準
ピア発見IRC チャネルブートストラップ + addr メッセージDNS シード + addr/addrv2 中継 + peers.dat キャッシュ
対応アドレス型IPv4 のみIPv4、IPv6、Tor v3 (onion)、I2P、CJDNS (addrv2、BIP 155 経由)
出方向接続8 件の全中継8 件の全中継 + 2 件のブロック中継専用 + フィーラー + アンカー接続
入方向接続最大約 125最大 125、多様性保持型退去アルゴリズム付き
メッセージ型約 7 (version、verack、addr、inv、getdata、block、tx)27 種以上
トランザクション中継inv 後に直接 tx をプッシュポアソンタイマー遅延付き告知後要求、wtxid 中継、feefilter
ブロック中継全ピアへの完全ブロック送信コンパクトブロック (BIP 152)。高帯域幅モードと低帯域幅モード
初期同期逐次: 1 ブロックずつダウンロードして検証ヘッダー先行: 全ヘッダーをダウンロード後、ブロックを並列要求
トランスポート平文 TCP日和見的暗号化トランスポート (BIP 324、ChaCha20-Poly1305)
日食耐性最小限 — 少数のピア集合、退去の多様性なし出方向ピアの回転、多様性退去、アンカー接続、ブロック中継専用ピア
プロトコルバージョニングバージョン 1ハンドシェイク時にインクリメンタルにバージョンを交渉。サービスビットで機能を告知

9. 本ページの範囲

本ページはネットワーク層を独立して扱う。以下のトピックは本ページの範囲外であり、設計文書シリーズ内のそれぞれのドメインページで扱う:

  • トランザクション検証と UTXO モデル: トランザクションがメモリープールに入る前に何がそれを有効にするか。トランザクション設計ページで扱う。
  • ブロック検証と合意規則: ネットワークから受信したすべてのブロックにノードが適用する決定論的検査。合意形成設計ページで扱う。
  • ブロック構造マークルツリー: トランザクションがブロックヘッダー内でどのようにコミットされるか。ブロック・チェーン設計ページで扱う。
  • マイニングとプルーフ・オブ・ワーク: ブロックテンプレート構築、ハッシュパズル、プールプロトコル。
  • 日食攻撃とシビル攻撃の経済学: ネットワーク層攻撃の完全な脅威モデル。L2 セキュリティモデル深掘りに委ねる。
  • メモリープールポリシーの詳細: パッケージ中継、手数料引上げによる置換の仕組み、手数料率バケット推定。

参照元の外部ソース

https://bitcoin.org/bitcoin.pdf