用語集 / ノードとソフトウェア
ヘッダーファースト同期
- ヘッダーファースト同期とは?
- ヘッダーファースト同期とは、ノードがブロック本体を要求する前に80バイトのヘッダーチェーン全体をダウンロードして検証し、その後でそれらの本体を並行して取得する起動戦略です。
ダウンロードを2段階に分けることが、初回同期を実用的なものにします。Bitcoin Coreは2015年2月にリリースされたバージョン0.10.0からこの方式で動作しており、それによりブロックの取得は、単一の順序付きキューから、接続中のすべてのピアに分散される処理へと変わりました。自分の残高を検証するために自身でノードを運用している場合、初回同期が数日ではなく数時間で終わるのはこのためです。
仕組み
ヘッダーファースト同期は、ピアにブロックではなくヘッダーを要求することから始まります。
ノードは、自分が現在どの位置にいると思うかを表すハッシュの簡潔なリストであるブロックロケーターを伴うgetheadersメッセージを送信します。ピアは、それぞれ80バイトのヘッダーを最大2,000件含むheadersメッセージで応答するため、1回の応答でおよそ2週間分のチェーンをカバーします。ノードは各ヘッダーについて、すでに保持している親を指していることと、そのハッシュがnBitsフィールドが示す難易度を満たしていることを確認し、どのピアもこれ以上新しいものを提供できなくなるまで、新しい先端から再び要求します。
この骨格が整って初めて、本体のダウンロードが始まります。ノードは必要なすべてのブロックのハッシュをすでに把握しているため、1つの接続の後ろに並ぶのではなく、複数のピアに異なる区間を同時に要求できます。Bitcoin Coreは、単一のピアに対して未完了のまま残すブロック要求の数を制限しており、現在のコードでは16件で、ウィンドウを停滞させるピアは切断します。親より先に到着したブロックはそのまま保持され、未検証のデータをディスクに一時保存するという以前の習慣はなくなりました。
ヘッダーには2つの安全策が伴います。ソフトウェアは、保持するヘッダーの累積プルーフ・オブ・ワークがリリースに組み込まれた最小値を上回るまでチェーンを確定せず、ピアが容易なブロックで作った安価なサイドチェーンへ新しいノードを誘い込むことはできません。また別に、assumevalid設定は各バージョンに同梱される最近のブロックハッシュを指定します。その下に埋もれたブロック内の署名は再確認されず、これにより数時間分の楕円曲線計算が省かれる一方、現在のチェーン状態に依存するすべてのルールは引き続き適用されます。
どこで確認できるか
ヘッダーファースト同期は、ノードが追いついている間に一致しない2つのカウンターとして現れます。
初回同期中にgetblockchaininfoを呼び出すと、headersフィールドはblocksフィールドよりはるかに先に進み、しばしば数十万件の差になります。グラフィカルクライアントも同じことを平易な言葉で示します。ヘッダーが到着して初めて終了時刻を推定できるのは、それまではあとどれだけ進む必要があるかを知らないためです。この2つの数値が近づいていく様子を見ることが、正直な進捗バーです。
軽量ソフトウェアは意図的に前半で止まります。SPVウォレット、コンパクトフィルタークライアント、または独自のチェーンバックエンドなしで動作するライトニングノードは、ヘッダーのみを保持し、その上にマークルプルーフやフィルターを重ねます。スマートフォンのウォレットがモバイルデータ通信で自身の履歴を確認できるのはまさにこのためです。ヘッダーは小さく固定サイズですが、ブロック本体はどちらでもありません。
ヘッダーファースト同期vsブロックファースト同期
ヘッダーファースト同期は内容をダウンロードする前にチェーンの形を把握しますが、ブロックファースト同期は両方を同時に行おうとしました。以前の方式はgetblocksメッセージを送信し、500件以下のブロックハッシュを含むinvを受信して、応答したピアから1件ずつ取得していたため、1つの遅い接続がその後ろのすべてを滞らせました。順序が狂って到着したものは、攻撃者が不要なデータで埋められるメモリ内の保持プール以外に行き場がありませんでした。Bitcoin Coreは0.10.0以降この方式で同期していませんが、古いソフトウェアが通信できるように、現在もこれらのメッセージを解釈します。