Bitcoin の 1 ブロックには数千のトランザクションが入っているが、ブロックヘッダは 80 バイト。Git のリポジトリの 100 万コミットの整合性が、現在の HEAD ハッシュ 1 つで検証できる。これらすべての中核に Merkle Tree (ハッシュツリー) がある。
1. これで何が動いているか
- Bitcoin / Ethereum: ブロック内トランザクションの整合性検証
- Git: commit / tree / blob の階層 (実は Merkle DAG)
- IPFS: 分散ファイルストレージのコンテンツアドレッシング
- DynamoDB / Cassandra: 分散レプリカ間の差分同期
- ZFS / BTRFS: ファイルシステムの整合性検証
- Certificate Transparency: SSL 証明書の改ざん検出 (Google Chrome)
2. 仕組みのざっくり
- 葉: 元データの SHA-256 ハッシュ
- 内部ノード: 左右の子ハッシュを連結 (concat) したもののハッシュ
- 根 (root): ツリーの最上位、これ 1 つで全データを代表
- 葉が奇数個: 一般的に最後の葉を複製 (Bitcoin 方式)
- 改ざん検出: 1 bit でも変わると、その葉から root まで全ノードのハッシュが変わる
3. Python 実装 (動作確認済)
純粋 Python の Merkle Tree
Python
import hashlib
def sha256(s): return hashlib.sha256(s.encode() if isinstance(s, str) else s).hexdigest()
def merkle_root(leaves): '''葉のリストから Merkle root を計算''' if not leaves: return None h = [sha256(l) for l in leaves] while len(h) > 1: if len(h) % 2: h.append(h[-1]) # 奇数個なら末尾を複製 h = [sha256(h[i] + h[i+1]) for i in range(0, len(h), 2)] return h[0]
# 4 トランザクションのブロックtxs = ['Alice→Bob: 1 BTC', 'Carol→Dave: 0.5 BTC', 'Eve→Frank: 2 BTC', 'Grace→Henry: 0.1 BTC']root = merkle_root(txs)print(f'Merkle root: {root}')
# 1 文字でも変えると root が変わるtxs_tampered = ['Alice→Bob: 1 BTC', 'Carol→Dave: 0.5 BTC', 'Eve→Frank: 2 BTC', 'Grace→Henry: 0.2 BTC'] # 0.1 → 0.2root_t = merkle_root(txs_tampered)print(f'改ざん後 root: {root_t}')print(f'検出: {root != root_t}')
# 実機実行結果:# Merkle root: <ハッシュ># 改ざん後 root: <別のハッシュ># 検出: True4. Merkle Proof の実装
葉が root に含まれることを log₂ N 個のハッシュで証明
Python
def build_tree(leaves): '''全レベルのハッシュを保持''' levels = [[sha256(l) for l in leaves]] while len(levels[-1]) > 1: cur = levels[-1] if len(cur) % 2: cur = cur + [cur[-1]] levels.append([sha256(cur[i]+cur[i+1]) for i in range(0, len(cur), 2)]) return levels
def merkle_proof(levels, index): '''葉 index に対する Merkle proof を生成''' proof = [] for level in levels[:-1]: sibling = index ^ 1 # 兄弟は最下位 bit 反転 if sibling >= len(level): sibling = index proof.append((sibling > index, level[sibling])) # (right?, hash) index //= 2 return proof
def verify_proof(leaf, proof, root): '''proof を使って root に到達するか検証''' h = sha256(leaf) for is_right, sibling in proof: h = sha256(h + sibling) if is_right else sha256(sibling + h) return h == root
txs = [f'tx{i}' for i in range(8)]levels = build_tree(txs)root = levels[-1][0]
# tx3 の proof を作って検証proof = merkle_proof(levels, 3)print(f'proof 長: {len(proof)} (= log₂ 8 = 3)')print(f'検証: {verify_proof("tx3", proof, root)}')print(f'偽装検証: {verify_proof("tx3_fake", proof, root)}')5. メリットとデメリット
| 観点 | Merkle Tree | 全データハッシュ |
|---|---|---|
| 改ざん検出 | ✓ (root 1 つで全体) | ✓ |
| 部分証明 | O(log n) のハッシュで可能 | 全データ必要 |
| 差分同期 | 差分木の比較で高速 | 全件比較 |
| 追加コスト | 葉数 × 2 のハッシュ計算 | 1 ハッシュ |
6. 関連ツール
- hashlib (Python 標準): SHA-256 / SHA-3
- py-merkle-tools: Merkle Tree 実装
- ethereum/trie (Python): Ethereum の Merkle Patricia Trie
- bitcoin-cli: Bitcoin の Merkle proof コマンド
7. 次の話
EP.10 では PageRank を扱います。Google を作った 1998 年のアルゴリズム を Python で実装。Web グラフの「重要なページ」を行列計算で求める数学的な美しさ。
この記事の感想を教えてください
あなたの 1 クリックで、本当にこの記事は更新されます。「もっと詳しく」「続編希望」が一定数集まった記事は、 ふくふくが 実際に内容を拡充したり続編記事を公開 します。 送信したリアクションはお使いのブラウザに記録され、再カウントされません。