バリュー・オーバーフロー事件の事後記事エントリーは資料的な骨格を記録している — いつ発見されたか、何がパッチされたか、チェーン再編成にどれだけ時間がかかったか。本エントリーは同じ事象を構造の問題として読む。救出のなかで実際に何が可能だったか、その制約がビットコイン黎明期の開発体制について何を露呈しているか、そしてフォレンジック視点で読んだとき、トランザクション自体が何を含意するか。
事象の物語は事後記事にある。読み解きはここにある。
1. ソフトフォーク救出が実際にどう機能したか
修正はソフトフォークだった。ハードフォークではない。この区別が、なぜ 53 ブロック分の正当なマイニングが、全ノード運用者を逐一調整することなく 1,840 億 BTC を正史から除去するのに足りたかを説明する。
元の合意ルールでは、ブロック 74638 は有効だった。各出力値は非負であり、出力の合計に対する整数オーバーフロー検査が欠落していた。Bitcoin v0.3.9 を実行するノードはブロックを目にし、自分が知るルールで検証し、受け入れた。
Bitcoin v0.3.10 は CheckTransaction() に 2 つの新しいチェックを追加した:
- 各出力 ≤ MAX_MONEY (21,000,000 BTC)
- 全出力の合計 ≤ MAX_MONEY
新ルール下では、ブロック 74638 は無効になった。パッチ適用ノードは検証時にブロックを拒絶し、ブロック 74638 の親 (高さ 74637) で分岐し、不正ブロックを含まずに伸びるチェーンを正典として扱った。
ソフトフォークの構造的性質は、新ルールが旧ルールの真部分集合であることだ。v0.3.10 で有効なブロックはすべて v0.3.9 でも有効だが、逆は成り立たない。パッチ適用ノードと未適用ノードは、永久に互換性のないネットワークに分裂するわけではない — ただ一時的にチェーンの先端について見解が異なるだけだ。十分なハッシュパワーが新ルールへ移行するかぎり、パッチ適用チェーンが累積仕事量を蓄積し、最終的に未適用チェーンを累積仕事量で追い越し、未適用ノードは既存のフォーク選択ルールにより長いチェーンに従う。再編成は自動的に起きる。ノードごとの介入は不要だ。
これが、ネットワーク全体を最初から再調整することなく救出が成立した理由である。ルール変更は制約方向に加算的だった — 拒絶を増やしただけで、許容を増やしてはいない。アップグレードしなかったノードも、累積仕事量が先行するチェーンを依然として追跡しており、パッチ適用チェーンの仕事量が先行するようになった時点で、未パッチノードも結果として正典チェーンに行き着いた。
その代償として支払われたもの: 約 15 時間の窓 (8 月 15 日 17:45 UTC のブロック 74638 から 8 月 16 日 09:00 UTC のブロック 74691 まで) のあいだ、正典チェーンが争われた。この窓のあいだ、どちらのチェーンで承認されたトランザクションも最終とみなすのは安全ではなかった。サトシの bitcoin-list 警告 — 「2010 年 8 月 15 日 17:05 UTC(ブロック 74638)以降に発生したトランザクションを信頼しないでほしい」 — は、ネットワーク稼働の停止ではなく、相手方信頼に対する 15 時間の停止だった。
機構は機能した。機構の代償は明確に開示された。両方が構造的な記録に属する。
2. 5 時間対応窓 — それは再現できない条件下でのみ成立した
ガージックの第一警告投稿は BitcoinTalk topic-822 で 18:08 UTC 付。サトシの bitcoin-0.3.10 リリース告知は topic-827 で 23:48 UTC 付。公開発見からビルド済み・署名済み・ダウンロード可能なソフトフォーク・リリースまで 5 時間 40 分 — Windows・Linux・macOS 各 SourceForge バイナリつきで。
この窓が 2010 年に可能だったのには特定の理由があり、その理由は今や再現不能である: プロダクションコード経路が実質的に単一の作者プラス信頼された 2 名のレビュアーだった。
公的記録における対応の主体:
- ジェフ・ガージック: 技術的観察者。生ブロックダンプから異常を特定。
- サトシ・ナカモト: コード作者。パッチを書き、テストし、署名・ビルドし、SourceForge にデプロイし、告知を投稿した。
- ギャビン・アンドレセン: 並行パッチテスター。topic-823 で knightmb の既存のブロックチェーン・スナップショットを清浄な起点として使用し、独自の緊急パッチをビルド・テストした。
これが 5 時間救出のプロダクション経路の参加者集合の全部である。3 つの名前、1 人の意思決定者、ガバナンスプロセスなし、レビュー待ち行列なし、マージゲーティングなし、開発者が自宅で走らせたもの以外のテストスイート・ゲートなし。「サトシのディスクに修正がある」 から「SourceForge でバイナリがダウンロード可能」 までのリリース経路に介在する制度は皆無だった。
2018 年、同じカテゴリのバグ (CVE-2018-17144、同一トランザクション内での二重支払いを許してしまうインフレーション・バグ) が Bitcoin Core で発見された時点で、対応インフラは様相を変えていた: 多人数の協調的な開示、通常のメンテナンス・バンプとして発表された静かな修正リリース、遅延を伴う公開、明示的なポストモーテム。2018 年の修正は時計時間ではより長く、関与人数もより多かった — そうあらねばならなかったからだ。2018 年の対応を生んだ体制は、2010 年の対応を生んだ体制よりも厳密に頑健であった — しかし 2010 年の対応窓は、2010 年がまだ持っていた制度的真空においてのみ達成可能だった。
構造的論点は「2010 年の対応のほうがましだった」 ということではない。2010 年の対応が単一作者によるリリース経路であり、その経路こそが 5 時間を可能にしたのだ、という点である。同じ脆弱性がそれ以降のどの年に発見されたとしても、5 時間の公開リリースから復旧までの窓は持てない。それ以降のどの年も、グローバル合意関連コードベースに対する単独デプロイ権限を持つ単一作者を持っていないからだ。
3. バグ・攻撃・概念実証 — どのカテゴリが当てはまり、どれが当てはまらないか
事件を「攻撃者が 1,840 億 BTC を盗んだ」「バグが悪意ある主体によってトリガーされた」 のいずれかに圧縮する物言いがよく見られる。両方の圧縮は、歴史記録が実際に何を確立しているかを問うのに必要な区別を見落としている。
バグは存在する。CheckTransaction() における出力合計に対するオーバーフロー検査の欠落は脆弱性である。CVE-2010-5139 がその名前である。これは誰がそれを悪用するかとは独立に成立する。
攻撃は起きた (セキュリティ用語の意味で)。オーバーフローを発動させるトランザクションを生成するには、意図的かつ技術的に情報を持った作業が必要だった — INT64_MAX/2 近辺の値は通常のウォレット使用では現れない。標準ウォレット UI はトランザクションを構築する前に MAX_MONEY と照合する。ブロック 74638 のトランザクションを生成するには、出力値が int64 算術で合計したときオーバーフローするように特別に選ばれた raw トランザクション・バイト列を手で組む必要があった。作者は標準ウォレット検証をバイパスし、手動で署名し、ブロードキャストする必要があった。セキュリティ用語では、脆弱性を意図的に発動させる行為は意図にかかわらず「攻撃」 と呼ばれる — この語自体は悪意を含意しない。
悪意は未証明であり、おそらく証明不能である。実行者が窃盗、デモンストレーション、ストレステストのどれを意図したかは、チェーンからもトランザクション形状からも確立できない。3 つの可能性が公的記録に等しく整合する:
-
窃盗の試み。1,840 億 BTC は不正チェーンが正典になっていれば、壊滅的な富の移転を引き起こしていた。2 つの出力アドレスの秘密鍵を保持していた者が、想定総供給量の 9,000 倍を支配していたことになる。鍵を主張する者が現れていない事実が含意するのは、(a) 行為者は使う意図がなく、デモンストレーションだった、(b) 使う意図はあったがソフトフォークが不可避と認識して沈黙した、(c) 鍵を紛失または破棄した、のいずれかである。
-
公的概念実証。本番ネットワーク上で最大インパクトの実証可能な exploit を生成する — 1 日以内に検出され再編成で除去されると分かっていながら — 行為は、バグ修正を強制し、バグの存在を文書化することになる。実行者にとっての費用 (若干のマイニング費用、特定リスクの若干) は、実証されたインパクトに対して小さい。
-
ストレステスト、または敵対的設定での事故。非標準条件下でコード経路を探っている開発者が、既存の検査が何を許容するかの限界を探りながらバグをトリガーした可能性はある。トリガーは依然として手動で構成されたトランザクション出力値を必要とする。タイプミスでは生成できない。
構造的な事実は、バグ・攻撃・悪意の問いは 3 つの独立した水準 — ソースコード、行為、意図 — に存在し、利用可能な証拠が各水準に異なる仕方で答える、ということである。チェーンはバグの存在と攻撃された事実を示す。チェーンは攻撃者が何を意図したかを示さない。
4. トランザクション構造のフォレンジック分析
ブロック 74638 の支出トランザクションの 2 つの出力値はいずれも 92,233,720,368.54277039 BTC である。これはウォレット由来の数値ではない。INT64_MAX を 10⁸ (satoshi-to-BTC 変換係数) で割った値から、合計が INT64_MAX を僅かに超えつつ、各出力単独では int64 表現可能範囲内に収まるよう、僅かなオフセットを引いた値である。この選択は意図的であり、検証コードの内部表現に対する知識を露呈する。
実行者が満たした制約:
- 個々の出力 ≤ INT64_MAX satoshi (そうでなければ出力ごと検証が、合計を取る前に拒絶する)
- 全出力の合計 > INT64_MAX satoshi (二の補数で負へオーバーフロー)
- オーバーフロー後の合計が、入力検査 (
output ≤ input、ただし両者は signed int64 として比較) を通過するに十分小さい — 0.5 BTC の入力で十分だった。負のオーバーフロー値は正の入力値より小さいと比較されるからである。
2 つの出力が同一 (両方 922 億 BTC) であることは構造的選択であり、偶然ではない。INT64_MAX を僅かに超えるよう合計される 2 つの等しい大きな値は、制約を満たす最も単純な構成である。異なる出力値も機能するが、実行者側でより多くの算術か、必要以上に広い値域を要する。同一値は最少情報の選択である。
ブロック 74638 のマイナーは別問題である。ブロックは不正トランザクションを含むに至った通常のプルーフ・オブ・ワーク・ブロックである。未パッチの検証ルール下では、v0.3.9 を走らせている誠実なマイナーであれば誰でも、当該トランザクションが mempool に現れていれば包含していたであろう — マイナーの検証コードが「有効」 と返すという意味で、ブロックは「誠実」 である。チェーンには、ブロック 74638 のマイナーがトランザクション作者と共謀した証拠は存在しない。マイナーのソフトウェアが走らせていたルールに従う包含は、共謀を含意しない。
5. 中央集権パラドックス
ビットコインの設計命題 — 信頼できる第三者を持たないピア・ツー・ピア電子キャッシュ — はそもそもシステムが存在する理由だった。5 時間救出が機能したのは、設計命題が含まない 3 つの条件によってだ:
- 他のいかなる主体もコード権威において匹敵し得ない単一作者。
- その作者が署名したバイナリを運用者が走らせるノード網。
- 「サトシがパッチを公開した、いま即アップグレード」 が、bitcoin-list と BitcoinTalk を通じて伝播し、数時間でネットワークを動員する十分な指示として機能する信頼勾配。
設計命題の厳密な読みでは、これらは何一つ必要であってはならない。プロトコルは自己修正的であるべきで、ノードは独立に検証すべきで、特権的なリリース権限を持つ主体はあってはならない。実際の救出では、3 つすべてが存在し、しかも構造的負荷を担っていた。
これがパラドックスである: システムは、システムが必要としないように設計された中央集権によって救われた。そして利用可能な時間内に他の手段で救出が成立する経路はなかった。同じ速度を持つ代替経路は存在しなかった。
このパラドックスはビットコインの設計命題を無効化しない。命題のランタイム保証とインシデントレスポンス保証が分岐する場所を画定するだけだ。プロトコルは定常状態では分散的でありながら、緊急ルール変更については中央集権的権威に依存しうる — なぜなら緊急ルール変更は、分散検証が内側から組織化できない調整事象だからだ。
事件が確立するのは非対称性である: 分散ネットワークは協調的なパッチを通じてルールへの攻撃を吸収できるが、パッチを生む調整層自体は分散的でない。後年のビットコインがその後数年かけて直面した引き継ぎの問い (サトシ → ギャビン → 複数メンテナ → 現在の分散メンテナンス体制) は、この非対称性への直接的応答として読める。2018 年のインフレーション・バグ対応 (多人数開示、単一デプロイ権限なし) は、ポスト・サトシ版の本救出があるべき姿である。
本エントリーはパラドックスが解消されたと論じない。2010 年 8 月の事件がパラドックスがライブネットワーク水準で初めて可視化された場であり、後続のビットコイン・ガバナンスがそれへの長期応答として読むのが最良である、と論じるのみである。
6. ビットコイン史における位置
最初の 10 年に、ビットコインに「これが迅速に検出されていなかったらシステムが存在を停止しえた」 水準のものとなる CVE は 2 件ある:
| 年 | CVE | クラス | 修正公開時間 | 正典復旧時間 |
|---|---|---|---|---|
| 2010 | CVE-2010-5139 | 出力合計に対する整数オーバーフロー、1,840 億 BTC を生成可能 | 5 時間 40 分 | 約 15 時間 |
| 2018 | CVE-2018-17144 | 入力重複検査の欠落、同一トランザクション内の二重支払いによるインフレーションを許容 | 協調的リリースで開示と修正、メインネットでは未悪用 | 該当なし (攻撃には使用されず) |
このペアが構造的に有用なのは、2018 年のバグが悪用されなかったからだ。重大度は責任ある開示窓で内部評価され、悪用前に修正がリリースされた。公的記録がバグの存在を認めた時点では、復旧すべきものは何もなかった。
2010 年の事件は最初の 10 年において「悪用かつ復旧」 のセルに該当する唯一のビットコイン事象である。ビットコインがライブチェーン上で兵器化された致命的バグから生き残れるかの、唯一の公開試験である。答えは: 是。数時間以内にパッチされたソフトフォーク経由で、単一作者によりデプロイされ、約 15 時間の再編成窓内にネットワークに受容された。答えは記録されている。しかしその答えを可能にした条件 — 単一作者デプロイ経路 — はもはや存在しない。
これが 2010 年事件の歴史記録上の特異な位置である。それは、既知の攻撃クラスでネットワークが自身の復旧能力を持つことの唯一の概念実証であり、その実証を生んだ条件は再現可能ではない。続く十年境界の事象 — ブロックサイズ戦争、2014 年の Bitcoin Core リブランド、Mt. Gox の経営破綻 — はガバナンス・エコシステム上のストレスであり、合意バグ・ストレスではない。それらはシステムの異なる側面を試した。2010 年の事象は、復旧が完了したチェーン水準の致命バグ・ストレスとしての公的記録における唯一の事例として残る。
7. 本エントリーが確立しないこと
- 攻撃者の身元。ブロック 74638 の 2 つの出力アドレスはチェーンに記録されているが、対応する秘密鍵はそれ以来使用されていない。著者性に関する公的主張は行われていない。身元の帰属は公的記録には存在しない。
- 攻撃者の意図。攻撃が窃盗、デモンストレーション、テストのいずれだったかは、トランザクションからもチェーンからも判定できない。上記 §3 は、どのカテゴリの意図が証拠と整合するかを記述する。証拠が確立するものは存在しない。
- マイナーの協力。ブロック 74638 はチェーンに身元が記録されていない主体によりマイニングされた。マイナーがトランザクション作者と共謀したか否かはチェーンから判定できない — 未パッチ検証ルールはトランザクションを受容したため、誠実な包含と協調的包含は区別不能である。
- knightmb の具体的役割。ブロックチェーン・スナップショットの貢献は knightmb のスナップショットと伝説エントリーで構造的に記録されている。本エントリーがスナップショットに言及するのは救出インフラの一部として識別するためのみであり、knightmb のより広い役割の編集的読み解きは当該エントリーに属する。
事後記事が事象を記録する。本構造分析が読み解きを記録する。身元・意図・個別貢献は、それぞれの問いを主題とするエントリーに属する。それらのエントリーは証拠が強い主張を支持しない箇所で控えめな表現を置いており、本エントリーも同様である。