マークル木と包含証明
台帳全体を持たなくても「その取引は確かに入っている」と証明できるのがマークル木です。ハッシュを木状に畳んでルート一つに要約し、対数個のハッシュだけで包含を検証する仕組みを原理から解きます。
- 1.マークル木は葉のデータをハッシュ化し、隣同士を連結して再ハッシュ、を繰り返して単一のルートハッシュに畳み込む二分木。ルートは全データの改竄検知用の要約になる。
- 2.包含証明(マークルproof)は、対象の葉から根までの経路に必要な兄弟ハッシュだけを並べたもの。葉数 n に対し約 log2(n) 個で足り、O(n) の全走査なしに検証できる。
- 3.軽量クライアント(SPV)はブロックヘッダのルートだけを保持し、フルノードから受け取ったproofでルートを再計算・照合することで、台帳全体を持たずに取引の包含を確かめる。
マークル木とは何か
ブロックチェーンのブロックには数千件の取引が入りますが、その中身を一切持たずに「特定の取引がブロックに含まれるか」を検証したい場面があります。これを可能にするのがマークル木(Merkle tree、ハッシュ木)です。Ralph Merkle が1979年に出願(米国特許 4,309,569、成立は1982年)したデータ構造で、暗号学的ハッシュ関数(/security/ の領域)を木状に積み上げ、任意個のデータを単一のルートハッシュに要約します。
構成は単純です。まず各データ(取引)をハッシュ化して葉とします。次に葉を左右のペアにまとめ、2つのハッシュを連結して再度ハッシュした値を親ノードにします。これを1つのノードになるまで繰り返した最上位がマークルルート(ルートハッシュ)です。ビットコインの場合、ハッシュ関数は SHA-256 を2回かける double-SHA256 が使われます。
Root = H( H12 || H34 )
/ \
H12 = H(H1||H2) H34 = H(H3||H4)
/ \ / \
H1=H(Tx1) H2=H(Tx2) H3=H(Tx3) H4=H(Tx4)
| | | |
Tx1 Tx2 Tx3 Tx4
ルートは全葉の内容に依存する一方向の要約です。どれか1件の取引を1ビットでも書き換えると、その葉のハッシュが変わり、親、さらに上と連鎖的にルートまで伝播して別の値になります。つまりルートを固定しておけば、下にぶら下がる全データの改竄を検知できる。逆にルートが一致するなら、木全体が元のままだと(衝突困難性の仮定のもとで)確信できます。
包含証明(マークルproof)の仕組み
マークル木の真価は包含証明(inclusion proof / Merkle proof)にあります。「Tx3 がこの木に含まれる」ことを、木全体を渡さずに証明したい。必要なのは、対象の葉から根へ登る経路上で、各段の兄弟(sibling)ノードのハッシュだけです。
上図で Tx3 の包含を示すには、検証者に H4(同じ段の兄弟)と H12(1つ上の段の兄弟)を渡します。検証者は手元の Tx3 から以下を再計算します。
h = H(Tx3) # 検証者が対象データから自分で計算
h = H(h || H4) # 兄弟 H4 と連結 → H34 を得る
h = H(H12 || h) # 兄弟 H12 と連結 → Root を得る
Root' == Root ? # 既知の正しいルートと一致すれば包含が成立
ここで連結の左右が重要です。対象が右の子なら H(sibling || h)、左の子なら H(h || sibling) となり、順序を間違えると別のハッシュになります。そのため proof の各要素には、その兄弟が左右どちらかを示すフラグ(またはインデックスの偶奇)を添えます。
H(A||B) と H(B||A) は一般に別の値です。包含証明は「どの高さで、対象が左右どちらにいて、兄弟は何か」の三点セットで初めて意味を持ちます。実装で proof の並び順や左右フラグを誤ると、正しいデータでもルートが合わず、あるいは(設計次第では)攻撃者に第二原像や重複葉の余地を与えかねません。
証明サイズが対数で済むのが決定的な利点です。葉が n 枚の平衡二分木の高さは約 log2(n) なので、proof に含める兄弟ハッシュも約 log2(n) 個。検証計算も同じく約 log2(n) 回のハッシュで完了します。
| 方式 | 検証に必要なデータ | 計算量 | 備考 |
|---|---|---|---|
| 全データ照合 | n 件すべて | O(n) | ブロック全体をダウンロードして再構成する必要がある |
| マークル包含証明 | 約 log2(n) 個の兄弟ハッシュ+ルート | O(log n) | 対象取引と経路上の兄弟だけで検証可能 |
葉が100万件(およそ2の20乗)でも、proof はわずか20個程度のハッシュで足ります。この「n が増えても証明は対数でしか伸びない」性質こそ、後述する軽量クライアントを成立させる土台です。
軽量クライアント(SPV)による効率的検証
ビットコインのフルノードは全ブロック・全取引を保持しますが、スマートフォンのような端末には重すぎます。そこで Nakamoto の原論文が提示したのが SPV(Simplified Payment Verification、簡易支払い検証)です。SPVクライアント(軽量クライアント)は取引本体を持たず、各ブロックのヘッダだけを連鎖として保持します。
ブロックヘッダは80バイト程度と小さく、その中にマークルルートが埋め込まれています。ヘッダはさらに前ブロックのハッシュとProof-of-Workの難易度目標を含むため、ヘッダ連鎖を辿るだけで「そのルートが最も work を積んだ正当なチェーン上にある」ことを確認できます。ここに包含証明を組み合わせます。
| 保持データ | フルノード | SPV(軽量クライアント) |
|---|---|---|
| ブロックヘッダ | 全部 | 全部(各80バイト程度) |
| 取引本体・マークル木全体 | 全部 | 持たない |
| ある取引の検証方法 | 自分の台帳を直接参照 | フルノードから proof を取得しルートと照合 |
| ストレージ規模 | 数百GB級 | ヘッダのみで数十MB級 |
検証の流れは次のとおりです。
1. SPVは信頼するフルノードへ「Txの包含証明が欲しい」と要求する
2. フルノードは Tx を含むブロックのマークル経路(兄弟ハッシュ列)を返す
3. SPVは手元の Tx から proof を畳み込み、ルートを再計算する
4. 再計算したルートが、自分が持つブロックヘッダ内のルートと一致するか照合
5. 一致し、かつそのヘッダが最長(最大 work)チェーン上にあれば包含を承認
SPVが確かめられるのは「その取引が、work の裏づけあるブロックに含まれている」ことです。一方でSPVは全UTXO集合を持たないため、その取引が無効ではないか(二重支払いなど)を自力で完全検証はできません。多数のマイナーが正直だという前提に依存します。包含の証明と、状態の正しさの検証は別問題だと切り分けて理解するのが要点です。
マークル木は「含まれる」ことの証明には向きますが、「含まれない」ことの証明は素朴な二分木では困難です。葉が順序付けされていないと、全体を見ない限り不在を主張できないからです。不在証明(proof of absence)が要る用途では、キーでソートしたマークル・パトリシア木(Ethereumのステート木)のような、順序を持つ構造が使われます。データベースの索引(/database/)が範囲探索のためにキー順を保つのと同じ発想です。
セキュリティ上の注意点
マークル木の安全性は下敷きのハッシュ関数の衝突困難性に全面的に依存します。関数が破られて自由に衝突を作れると、同じルートを持つ別の取引集合を捏造できてしまいます。さらに実装レベルでは、葉と内部ノードでドメイン分離(別々のプレフィックスを付けてハッシュ)を怠ると、内部ノードのハッシュを葉と誤認させる攻撃が成立し得ます。
初期ビットコインには、葉数が奇数のとき末尾を複製して詰める仕様と相まって、異なる取引集合が同一のマークルルートを生む脆弱性がありました(CVE-2012-2459)。攻撃者は取引を複製した不正ブロックで、正当なブロックと同じルートを持つ別物を作れます。受信ノードはそのブロックを(重複ゆえ)無効と判定しますが、正当ブロックと同一ハッシュのため再取得を試みず、そのチェーンで停止してしまう——実害はサービス拒否(DoS)/フォーク停止でした。マークル木を実装する際は、奇数ノードの扱い・重複葉の禁止・ドメイン分離を必ず設計に織り込む必要があります。ネットワーク層の堅牢化(/network/)だけでは防げない、データ構造固有の落とし穴です。
「マークルルート=全取引の改竄検知用の要約」「包含証明=根までの経路の兄弟ハッシュ列、サイズ O(log n)」「SPV=ヘッダのルートと proof を照合して台帳全体なしに包含を確認」の3点セットで押さえるのが定番です。落とし穴として、連結の左右順序が意味を持つこと、不在証明は別構造(ソート済み木)が要ること、安全性はハッシュの衝突困難性に依存することも問われます。
まとめ
- マークル木は葉データをハッシュ化し、隣接ペアを連結・再ハッシュして単一のルートハッシュに畳み込む二分木。ルートは全データの改竄検知用の要約になる。
- 包含証明は根までの経路上の兄弟ハッシュ列だけで構成され、サイズも検証計算もO(log n)。全走査 O(n) を避けて特定取引の包含を確かめられる。
- **SPV(軽量クライアント)**はブロックヘッダのルートのみ保持し、フルノードの proof を畳み込んでルートを照合。台帳全体を持たずに包含を検証できるが、状態の正しさは多数派の正直さに依存する。
- 安全性はハッシュの衝突困難性が土台。奇数ノードや重複葉、ドメイン分離の扱いを誤ると(CVE-2012-2459 のように)同一ルートの捏造を許すため、実装では慎重な設計が要る。
ブロックチェーン Article
マークル木と包含証明を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
ブロックチェーン
比較で見る軸
難易度: advanced / カテゴリ: ブロックチェーン / タグ数: 6
導入後に効く点
包含証明(マークルproof)は、対象の葉から根までの経路に必要な兄弟ハッシュだけを並べたもの。葉数 n に対し約 log2(n) 個で足り、O(n) の全走査なしに検証できる。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- ブロックチェーン
- タグ数
- 6
判断チェックリスト
- 自社の用途が「ブロックチェーン / 分散台帳」に近いか確認する。
- 強みである「マークル木は葉のデータをハッシュ化し、隣同士を連結して再ハッシュ、を繰り返して単一のルートハッシュに畳み込む二分木。ルートは全データの改竄検知用の要約になる。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。