
1,844億BTCが一つのブロックで生成された。いま見ても、現実離れした数字だ。だが、もっと奇妙なのは、バグが見つかったあとである。古い規則のノードはそのブロックを受け入れ、直した版を入れたノードは拒んだ。ビットコインは一時、食い違う二つの歴史を抱えた。発見から、パッチ、チェーンの組み替えまでの経過は、バリュー・オーバーフロー事件のページに記録してある。このページでは、その先の立て直しそのものを追う。どちらの歴史が正しいかでネットワークが割れているなかで、ありえないトランザクションを消すのに何が必要だったのか。
1 ソフトフォークによる立て直しは、実際にどう進んだか
修正はハードフォークではなく、ソフトフォークだった。この違いは大事である。全部のノードの運用者と足並みをそろえなくても、正しいブロックを53個掘るだけで、1,844億BTCを正式なチェーンから消せたのは、ソフトフォークだったからだ。
元の合意の規則では、ブロック74638は有効だった。出力の値は一つずつ見ればどれも負ではなかったが、出力の合計が整数の上限を超えていないかを確かめる検査がなかった。Bitcoin v0.3.9を動かしていたノードは、このブロックを受け取り、自分の知る規則で確かめて、受け入れた。ソフトウェアに合意のバグがあると、そのバグが通したチェーンは、有効なチェーンと見分けがつかない。セキュリティモデルのページの信頼モデルの表に一般論として書いたことの、これが実例である。出力の値の欄(出力一つにつき8バイト。トランザクションの設計のページに記録)には、この事件で上限が入るまで、プロトコルとしての上限がなかった。
Bitcoin v0.3.10は、CheckTransaction() に新しい検査を二つ足した:
- 出力の一つずつがMAX_MONEY (21,000,000 BTC) 以下であること
- 出力の合計がMAX_MONEY以下であること
新しい規則のもとでは、ブロック74638は無効になった。パッチを入れたノードは、このブロックを確かめた段階で拒み、ブロック74638の一つ前(高さ74637)から枝分かれして、不正なブロックを含まずに伸びていくチェーンを、正式なチェーンとして扱った。
ソフトフォークでは、新しい規則で通るブロックは、古い規則でも必ず通る。新しい規則のほうが狭いのである。v0.3.10で有効なブロックはすべてv0.3.9でも有効だが、逆は成り立たない。そのため、パッチを入れたノードと入れていないノードは、二度と互いに通じないネットワークに分かれてしまうわけではない。チェーンの先端がどこかについて、しばらく意見が食い違うだけだ。十分なハッシュパワーが新しい規則に移れば、パッチを入れた側のチェーンに仕事量が積み上がり、やがて直していない側のチェーンを追い越す。そうなれば、パッチを入れていないノードも、もともとのフォークの選び方の規則に従って、長いほうのチェーンに乗り換える。チェーンの組み替えはひとりでに起き、ノードごとに手を入れる必要はない。
だから、ネットワーク全体と一から足並みをそろえ直さなくても、立て直しができた。規則の変更は、拒むものを増やす向きだけで、受け入れるものは増やしていない。アップグレードしなかったノードも、仕事量の多いほうのチェーンを追い続けていたので、パッチを入れた側のチェーンの仕事量が上回った時点で、正式なチェーンに乗り換えることになった。
その代わり、約15時間(8月15日17:05 UTCのブロック74638から、8月16日08:20 UTCのブロック74691まで)のあいだ、どちらが正式なチェーンかが定まらなかった。この間は、どちらのチェーンで承認されたトランザクションも、確定したものとして扱うのは危なかった。サトシはbitcoin-listへの警告で*「2010年8月15日17:05 UTC(ブロック74638)より後のトランザクションは、どれも信用しないでほしい」*と念を押した。15時間止まったのは、ネットワークの動きではない。取引の相手を信じてよいかの判断が、止まったのである。
この15時間が始まって9時間ほどたったころ、サトシ自身が、乗り換えがどこまで進んだかを書いている。「74638以降、すでに14ブロックを生成した。0.3.10のビルドは約2~3時間前にアップロードされた。接続しているノードのうち、半数以上がすでに0.3.10だ。おそらく、不正なチェーンよりもすでに多くの計算力を持っていると思う。」。ブロック74691で正式に決まる数時間前に、この仕組みが頼りにしていたハッシュパワーの乗り換えが、もう優勢になっていた。そのことを、サトシ本人の言葉が示している。
仕組みは働いた。そして、その代償も、はっきり公にされた。どちらも、この事件の成り立ちを語るうえで欠かせない。
事件のタイムライン (UTC)
2 5時間の対応 — 二度と同じ条件はそろわない
ガージックの最初の警告は、BitcoinTalkのtopic-822に、18:08 UTCの時刻で投稿された。サトシのbitcoin-0.3.10のリリースの告知は、topic-827に、23:48 UTCの時刻で投稿された。異常が公になってから、ソフトフォークの修正をビルドし、Windows・Linux・macOSのバイナリをSourceForgeに置いて誰でもダウンロードできるようにするまで、5時間40分だった。この8月14〜15日のサトシのコードのチェックインとフォーラムの投稿は、フィニーがALSで体の自由がきかないなかシンギュラリティ・サミットに出ていた同じ2日間と重なる。アリバイの比べ方はハル・フィニー同一人物説で扱っている。
2010年にこの速さが出せたのには理由があり、その理由は今では二度とそろわない。修正を書いてから公開するまでの道のりに、実質的に、書いた本人と、信頼された確かめ役の2人しかいなかったのである。
公の記録に出てくる、対応にあたった人は次の3人である。
- ジェフ・ガージック: 技術の面から見ていた人。ブロックの生のデータを書き出して、異常に気づいた。
- サトシ・ナカモト: コードの作者。パッチを書き、テストし、バイナリをビルドして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,844億BTCを盗んだ」とか、「悪意のある誰かがバグを突いた」とか、一言にまとめて語られがちだ。どちらのまとめ方も、歴史の記録で実際に何が確かめられているかを考えるうえで欠かせない区別を、落としている。
バグはあった。CheckTransaction() に、出力の合計が上限を超えないかを確かめる検査がなかったのは、弱点である。CVE-2010-5139という番号が付いている。この弱点は、誰かがそれを突くかどうかとは関わりなく、そこにあった。
攻撃は起きた(セキュリティの用語の意味で)。オーバーフローを起こすトランザクションを作るには、狙いを定め、技術をよく分かったうえで手を動かす必要があった。INT64_MAXに近い値は、ウォレットをいつものように使っていて出てくるものではない。標準のウォレットの画面は、トランザクションを組み立てる前にMAX_MONEYと照らし合わせる。ブロック74638のトランザクションを作るには、int64で足し合わせるとオーバーフローするように値を選んだ出力を、生のトランザクションのバイト列として手で組まなければならなかった。作った人は、標準のウォレットの検査を回り道し、自分で署名し、ネットワークに流す必要があった。セキュリティの用語では、弱点をわざと突くことは、意図がどうであれ「攻撃」と呼ぶ。この語には、悪意があったという意味は含まれていない。
悪意は証明されておらず、おそらく証明もできない。やった人が盗むつもりだったのか、見せるつもりだったのか、負荷を試すつもりだったのかは、チェーンからもトランザクションの形からも決められない。公の記録とは、次の三つのどれも同じように食い違わない:
-
盗もうとした。不正なチェーンが正式なものになっていれば、1,844億BTCは、取り返しのつかない富の移動を引き起こしていた。二つの出力のアドレスの秘密鍵を持つ人が、予定された発行の総量の9,000倍を手にしていたことになる。鍵を持つと名乗り出た人がいないことから考えられるのは、(a) やった人に使うつもりはなく、見せるためだった、(b) 使うつもりはあったが、ソフトフォークは避けられないと分かって黙った、(c) 鍵をなくしたか捨てた、のどれかである。
-
公に見せる概念実証だった。1日もたたずに見つかり、チェーンの組み替えで消されると分かっていながら、動いているネットワークで、最も大きな被害が出る形の悪用を誰の目にも見える形でやってみせれば、バグを直させ、バグがあったことを記録に残すことになる。やった人が負ったもの(少しのマイニングの費用と、正体を突き止められる少しの危険)は、見せつけた影響の大きさに比べれば小さい。
-
負荷の試しか、思わぬ事故だった。変わった条件でコードの動きを探っていた開発者が、今ある検査がどこまで通すのかを試すうちに、バグを起こしてしまった可能性もある。それでも、出力の値は手で組まなければ作れない。打ち間違いでできる値ではない。
ここで押さえておきたいのは、バグ、攻撃、悪意という三つの論点が、ソースコード、行い、意図という別々の段にあり、手元の証拠が段ごとに違う答え方をする、ということである。チェーンからは、バグがあり、それが攻撃に使われたことが分かる。しかし、攻撃した人が何を考えていたかは分からない。
4 トランザクションの作りから読めること
ブロック74638でコインを使ったトランザクションには出力が二つあり、どちらの値も92,233,720,368.54277039 BTCだった。これは、ウォレットをいつものように使って出てくる数ではない。INT64_MAXを10⁸(satoshiをBTCに直すときに割る数)で割った値より、0.00498768 BTC(498,768 satoshi)だけ小さい。出力は一つずつならint64に収まるが、二つを足すと2⁶⁴ satoshiのすぐ手前、INT64_MAXのほぼ2倍になり、折り返して−0.00997538 BTCになる。この値は狙って選ばれたもので、選んだ人が、検証のコードの中で数がどういう形で扱われているかを知っていたことを示す。
やった人が満たした条件:
- 出力の一つずつはINT64_MAX satoshi以下(そうでなければ、合計を取る前に、出力を一つずつ確かめる段で拒まれる)
- 出力の合計はINT64_MAX satoshiを超える(2の補数の表し方で、負の値に折り返す)
- 折り返したあとの合計は、入力との比べ(
output ≤ input。ただし、どちらも符号付きのint64として比べる)を通るほど小さい。入力は0.5 BTCで足りた。折り返した負の値は、正の入力の値より小さいと判定されるからである。
二つの出力が同じ値(どちらも922億BTC)なのは、たまたまではなく、作りの上でそう選んだものである。足すと折り返してゼロのすぐ下に来る、等しい大きな値を二つ並べるのが、条件を満たす最も単純な組み方だからだ。ほかの値でもできるが、そのぶん計算が増えるか、必要より広い範囲の値を使うことになる。同じ値を二つ並べるのが、決めることの最も少ない選び方である。
ブロック74638を掘ったマイナーは、これとは別の話である。そのブロックは、たまたま不正なトランザクションが入っていただけの、いつもどおりのプルーフ・オブ・ワークのブロックである。パッチの前の検証の規則では、v0.3.9を動かしている正直なマイナーなら誰でも、そのトランザクションが手元のmempoolに来ていれば、ブロックに入れていただろう。マイナーの検証のコードが「有効」と答えたという意味で、ブロックは「まっとう」だったのである。チェーンには、ブロック74638のマイナーがトランザクションを作った人と示し合わせていたことを示すものはない。マイナーのソフトウェアが使っていた規則に従ってブロックに入れただけなら、示し合わせたことにはならない。
5 中央集権パラドックス
ビットコインの設計のおおもとにあるのは、信頼できる第三者のいらない、ピア・ツー・ピアの電子キャッシュという考えで、それがこの仕組みのそもそもの存在理由だった。ところが、5時間の立て直しがうまくいったのは、この考えには入っていない三つのものがあったからだ:
- コードについて、ほかの誰も並ぶ者のいない権威を持つ、ただ一人の作者。
- 運用者が、その作者のビルドしたバイナリを動かしているノードの網。
- 「サトシがパッチを出した、今すぐアップグレードを」という一言が、bitcoin-listとBitcoinTalkで広まり、数時間でネットワークを動かすのに足りるほど、人々がサトシを信頼していたこと。
設計の考えを文字どおりに受け取れば、どれも要らないはずのものである。プロトコルは自分で正しい状態に戻るべきで、ノードはそれぞれ自分で確かめるべきで、特別な公開の権限を持つ人はいてはならない。ところが、実際の立て直しでは、三つともがそろっていたうえに、三つのどれが欠けても立て直しは成り立たなかった。
これが逆説である。この仕組みを救ったのは、この仕組みが要らなくなるように設計されていたはずの、中央集権だった。しかも、使える時間のうちに、ほかの方法で立て直す道はなかった。同じ速さで進められる別の道は、存在しなかったのである。
この逆説は、ビットコインの設計の考えを否定するものではない。設計が約束することのうち、平時の動きについての約束と、事故への対応についての約束が、どこで分かれるかをはっきりさせるだけである。プロトコルは、平時には分散していても、緊急に規則を変えるときには、中央の権威に頼ることがある。緊急に規則を変えるには、皆の足並みをそろえる必要があり、それぞれが別々に確かめる仕組みの内側からは、その足並みをそろえられないからだ。
この事件がはっきり示すのは、片方にだけ偏った関係である。分散したネットワークは、皆で足並みをそろえて当てたパッチによって、規則への攻撃を乗り越えられる。しかし、そのパッチを生み出す足並みのそろえ方そのものは、分散していない。ビットコインがこのあと何年もかけて進めた引き継ぎ(サトシ → ギャビン → 何人ものメンテナー → 今の、多くの人で分け持つメンテナンスの体制)は、この偏りへのじかの答えである。サトシの設計思想と現在の実態のガバナンスの章も、この一人きりの立て直しから、Coreのメンテナー、マイニングプール、取引所が絡み合う今の形へ移っていった流れを、別の側からたどっている。2018年のコインを増やせるバグへの対応(何人もの手による開示、一人で公開する権限を持つ人はいない)は、サトシがいなくなったあとの立て直しが、どんな形を取らなければならないかを示している。
この逆説が解けたわけではない。2010年8月の事件は、この逆説が、動いているネットワークの上で初めて目に見える形になった出来事である。その後のビットコインのガバナンスは、この偏りに長い時間をかけて答え続けてきたものだ。
6 ビットコインの歴史の中での位置
最初の10年のビットコインには、「すぐに見つかっていなければ、仕組みそのものがなくなっていたかもしれない」ほどのCVEが2件ある:
| 年 | CVE | 種類 | 修正の公開までの時間 | 正式なチェーンが戻るまでの時間 |
|---|---|---|---|---|
| 2010 | CVE-2010-5139 | 出力の合計の整数オーバーフロー。1,844億BTCを生み出せた | 5時間40分 | 約15時間 |
| 2018 | CVE-2018-17144 | 入力の重なりを確かめる検査がなく、同じトランザクションの中で同じ入力を二度使ってコインを増やせた | 示し合わせたリリースで、開示と修正を同時に行った。メインネットでは悪用されていない | なし(攻撃に使われていない) |
この二つを並べると、違いがはっきりする。2018年のバグは悪用されなかったからである。どれほど重大かは、公表を控えて関係者にだけ知らせる期間のうちに内々で見積もられ、悪用される前に修正が出た。公の記録がバグがあったことを認めたときには、もう立て直すものは何もなかった。
最初の10年で、「悪用され、しかも立て直された」に当たるビットコインの出来事は、2010年の事件だけである。命取りになるバグが、動いているチェーンで実際に攻撃に使われたとき、ビットコインが生き延びられるかを、公の場で試した唯一の例でもある。答えは「生き延びられる」だった。数時間のうちに作られたソフトフォークの修正を、一人の作者が公開し、約15時間のチェーンの組み替えの間にネットワークがそれを受け入れた。答えは記録に残っている。しかし、その答えを可能にした条件、つまり一人の作者がそのまま公開できる道のりは、もうない。サトシの時代の合意の規則の三つ目のバグ、難易度の調整の数え違い(時間ねじれ攻撃)は、また別の欄に入る。知られていながら直されておらず、しかも一度も悪用されていない。悪用には長く続く過半数が要り、被害が出るよりずっと前に、それが誰の目にも明らかになってしまうからだ。
そのため、2010年の事件は、歴史の記録の中で変わった位置にある。知られた種類の攻撃から、ネットワークが自分で立ち直れることを示したただ一つの実例でありながら、その実例を生んだ条件は二度とそろわない。その後の節目になった出来事、つまりブロックサイズ戦争、2014年の「Bitcoin Core」への名前の変更、Mt. Goxの経営破綻は、ガバナンスやビットコインを取り巻く業界にかかった重圧で、合意のバグによる重圧ではない。どれも、仕組みの別の面を試した。チェーンそのものを揺るがす致命的なバグから立ち直るところまで終えた例として、公の記録に残るのは、今も2010年の事件だけである。
7 このページで言えないこと
- 攻撃した人の身元。ブロック74638の二つの出力のアドレスはチェーンに残っているが、その秘密鍵は以来一度も使われていない。自分がやったと公に名乗り出た人もいない。誰がやったかは、公の記録にない。
- 攻撃した人の意図。盗むつもりだったのか、見せるつもりだったのか、試しだったのかは、トランザクションからもチェーンからも決められない。§3では、どの意図なら証拠と食い違わないかを書いた。証拠によって確かめられた意図はない。
- マイナーが手を貸したか。ブロック74638を掘った人の身元は、チェーンに残っていない。そのマイナーがトランザクションを作った人と示し合わせていたかどうかは、チェーンからは決められない。パッチの前の検証の規則はこのトランザクションを受け入れていたので、何も知らずにブロックに入れたのか、示し合わせて入れたのかは、見分けがつかない。
- knightmbが果たした役割。ブロックチェーンのスナップショットを提供したことは、knightmbのスナップショットと伝説のページにまとめてある。
この事件で最も祝いやすく、最も読み違えやすいのは、立て直しの部分だ。動いているネットワークで合意が崩れても、立ち直れることは示された。同時に、その立ち直りは、この仕組みが本来要らないはずだった公開の権限に頼っていた。私はこの事件を、「ビットコインは生き延びた」か「中央集権だった」かのどちらか一つにまとめない。記録には、二つともが残っている。この事件の居心地の悪い価値は、その二つが同時にやってきたことにある。






















