132010年8月15日

1840億ビットコインが生まれた日

ある取引が金額の検証をすり抜け、予定された供給量をはるかに超えるビットコインを生み出した。修正は数時間で届いたが、通貨のルールを守れるかどうかは、それを実行するコードの確かさにかかっていることが明らかになった。

2010年8月15日、日曜日。Jeff Garzik は、採掘されたばかりのブロック74 638と、そこに記された本来あり得ない金額を報告した。一つのトランザクションが二つの出力を作り、それぞれが920億 BTCを超えていた。合計すると、Bitcoin が予定していた供給量のほぼ九千倍になる。Garzik は18:08:49 UTCに、フォーラムで「Strange block 74638」というスレッドを立て、ブロックのデータを掲載した。数分もしないうちに、ブロックエクスプローラーの不具合でも、小数点の位置を間違えた表示でもないと分かった。ネットワークは、自らの通貨ルールに反するブロックを受け入れていたのだ。コインを好き勝手に作ることはできないという信頼を保つには、まず原因を突き止め、ソフトウェアを直し、十分な数の参加者に別の履歴の分岐へ進んでもらう必要があった。

01

不思議なブロック 74 638

Garzik の投稿は短く、事実を端的に示していた。そこにはトランザクションのハッシュと、桁外れの二つの出力があった。同じスレッドに後から掲載された printblock の記録には、正確な値が記されている。それぞれ92 233 720 368.54275808 BTCだった。ブロックには別の coinbase トランザクションもあり、マイナーに50.51 BTCを支払っていた。通常の基本報酬である50ビットコインと比べれば、あの二つの出力は途方もない。誰かが、たった今1840億を超える単位を作り出したのだ。

そのトランザクションには、名乗り出た人物も、公の説明もなかった。残された記録から分かるのは何が起きたかであり、誰がどんな目的で不具合を利用したかではない。作成者を特定のハッカーだと断定すれば、史料にない情報を物語に付け足すことになる。確かなのは、検証処理の弱点を突くようにトランザクションが組み立てられていたことだけだ。

ネットワークが受け入れてしまったのは、旧コードが各出力を確認した後、その合計を検査していたためだ。巨大な出力も、一つずつなら使用していた数値型の範囲に収まっていた。ところが二つを足すと上限を超え、値が負の領域へあふれた。その後の検査は、許されない正の値が作られてはいないと誤って判断した。

署名の偽造でも、過去のトランザクションの改変でも、ハッシュレートの過半数を握る攻撃でもなかった。攻撃者が利用したのは、ある実装が整数を処理する方法だった。「入力を超える額を出力しない」という数学上のルールは正しかった。しかしオーバーフローのために、プログラムは人々が意図したとおりにそのルールを実行できなかった。

問題のブロックは、すでに最も有力なチェーンの一部になっていた。不具合のある版を使うノードはそれを有効と判定し、ほかのマイナーもその上にブロックを積み重ねられた。したがって、発見を公表するだけでは足りなかった。誤った履歴が伸び、巨額の出力がさらに使われ始める前に、コミュニティーは動く必要があった。

02

ルールと機械の間に生じた不具合

2100万枚という上限は、Bitcoin の不変の法則として語られることが多い。この事件が示したのは、もう少し正確な姿だった。上限は一連のコンセンサスルールであり、各プログラムとすべてのFull Nodeが誤りなく実行しなければならない。広く使われているノードがすべて同じ不具合のある実装を共有していれば、本来の意図に反する状態を一時的に受け入れてしまうことがある。

整数オーバーフローは、プログラミングでは古くから知られた問題だ。コンピューターのレジスタが扱える範囲は無限ではない。限界を超えて計算すると、結果が数直線のまったく別の側に現れることがある。金額を扱うシステムでは、この小さな違いが決定的になる。合計は計算し終えてからだけでなく、計算の途中でも確認し、個々の金額も許された範囲に保たなければならない。

現在の Bitcoin Core では、そのために複数の独立した検査を行う。出力は負の値であってはならず、最大供給量を超えてもならない。そして加算するたびに、累計額をもう一度確かめる。これらの処理は、漠然とした用心から生まれたわけではない。一つの保護処理が欠けたために、経済的にあり得ないトランザクションをネットワークが記録してしまった。その出来事の記憶が、このコードには残っている。

この不具合は、仕様と人々の期待の違いも浮き彫りにした。旧ソフトウェアが受け入れたのだから巨額のコインも正当だ、とフォーラムで本気で主張する人はいなかった。参加者は、意図していたルールへの違反だという点で一致していた。ただし、その合意を実現するには技術的な手段が必要だった。問題のブロックを拒否する新しい版である。

ここでコードと人間の役割が重なる。ノードがどのブロックを受け入れるかは、コードによって決定的に定まる。一方、意図したルールとの食い違いが見つかったとき、どのコードを入れるかを選ぶのは人間だ。この事件は、新たな発行量を決める投票ではなかった。コミュニティーがすでにシステムの土台と考えていたルールを取り戻すための、時間との競争だった。

整数オーバーフローが厄介なのは、人間ならすぐに気づく不合理さを機械は見抜けないからだ。プロセッサは限られた領域に保存された数値を扱う。計算がその境界を超えると、結果が範囲の別の部分へ回り込むことがある。旧コードは各出力を確認していたが、加算中の累計額を安全な範囲に保っていなかった。そのため、トランザクションは一つずつ見れば妥当な条件をいくつも通過しながら、全体としての目的に反していた。修正には具体的な処理が必要だった。コメントに「ビットコインは2100万枚を超えない」と書くだけでは足りない。すべてのノードに、その一文を毎回の計算で実際に守らせるルールが必要だった。

03

圧力の下での修正

報告の後、フォーラムではトランザクションの受け取りをやめ、一時的に採掘を止めるよう呼びかけられた。問題のトランザクションを含むブロックの上に新しいブロックが積まれるたびに、後で捨てることになる作業は増えていく。中央の停止スイッチを持たないネットワークで、Satoshi が採掘を強制的に止めることはできなかった。修正を公開し、運用者に使ってもらうよう説得するしかなかった。

バージョン0.3.10は金額の検査を修正し、ブロック74 638を拒否した。修正済みのノードは、双方に共通する最後の有効な地点に戻り、マイナーは過剰発行のトランザクションを含まない別の分岐を作り始めた。二つの履歴はしばらくの間、積み重ねた作業量によって競い合った。

その後、Satoshi は正しいチェーンが問題のチェーンを追い越したと発表した。更新されたソフトウェアはチェーンの再編成を行い、問題のブロックは採用中の履歴から消えた。捨てられた分岐のトランザクションでも、それ自体が無効でなければ待機列に戻り、後のブロックに再び取り込まれ得た。しかし、あの巨額の出力は新しい検査では存在を認められなかった。

修復には代償もあった。捨てられた分岐で採掘したマイナーは報酬を失い、利用者は数時間分の履歴がそのまま続かないことを受け入れなければならなかった。2010年のネットワークは小さく、調整も速かった。同じ措置をはるかに大きな経済圏で行えば、関係する経済主体やソフトウェアの種類は増え、どこまでを修正と認めるかについての議論も増えるだろう。

対応の速さは、Satoshi の奇跡的な介入として語られがちだ。しかし実際には、記録で追える一連の行動があった。Garzik が問題を公表し、ほかの人々がオーバーフローを分析し、開発者が修正を用意し、運用者が新しいバージョンのBitcoin クライアントを導入した。そしてマイナーが正しい分岐に作業を積み重ねた。作者は修正を提案できても、実際に採用するのはネットワークだった。

04

最も厳格な規則は、最も謙虚な開発を必要とする

修正後、有効なビットコインの数は予定された枠内に戻り、不正に生まれた膨大な額は、その後のチェーンでは使えなくなった。したがって、事件は恒久的なインフレにはつながらなかった。それでも、ベータ版時代の珍事件にすぎないわけではない。通貨への信頼を支えるのは標語ではなく、繰り返し検証されるプログラムなのだと教えてくれる。

Bitcoin は、中央の権威が決定一つで供給量を変える仕組みと対比されることが多い。しかし、ここでも人間の役割がなくなったわけではない。開発者が実装を書き、レビュアーが不具合を探し、運用者がバージョンを選び、マイナーがブロックの順序を作る。違いは、その変更が公開され、各ノードが同意できないルールを自ら拒否できることにある。

この出来事は、現在のコンセンサスコードが慎重に変更される理由も説明している。計算処理の小さな最適化でも、通貨の供給に影響し得る。テスト、複数の実装上の確認、時間をかけたレビューは、余計な手続きではない。わずか数ビットの違いで、許されない巨額が一見有効な値に変わってしまった瞬間を、二度と繰り返さないための備えだ。

Jeff Garzik のフォーラム投稿一つで、ネットワークの安全が完成したわけではない。それでも彼は、公開台帳の強みを示した。誰もが問題のブロックを見て、出力を計算し直し、修復を確認できた。不具合は事業者の内部データベースに隠されていなかった。旧ノードがそれを受け入れた証拠とともに、コミュニティー全体の前に置かれていた。

供給上限はこの事件を生き延びた。ただし、「不変」という言葉から想像されるような形ではなかった。ソフトウェアが絶対に失敗しないからではなく、失敗が目に見え、立ち戻れる共通のルールがあり、十分な数の参加者が修正を実行したからだ。1840億ビットコインの物語は、供給量の上限を否定するものではない。それを守るために、本当は何が必要なのかを伝える歴史である。

この出来事はまた、コードの公開性だけではバグを除去できないことを思い起こさせる。オープンソースは、人々が単一のベンダーを待たずに問題を発見し、比較し、修正することを可能にしたが、決定的だったのは特定の参加者の注意深さだった。誰かが不可能な数値に気づき、誰かが欠陥のある条件を見つけ、運用者が更新を適用しなければならなかった。透明性は検証の可能性を生み出した。それをネットワークの防衛に変えたのは、行動だった。だからこそ、この物語は年月を経てもなお重要だ。ビットコインの安全性は、完璧な初期プログラムという幻想にあるのではなく、厳密なルール、独立した検証、そして誤りを隠さずにそれに対応する能力の組み合わせにある。

Atlas

Atlasの人物と用語

OVFLValue Overflow IncidentGARZIKJeff GarzikTXトランザクションRULESコンセンサスルールCOREBitcoin CoreNODEFull NodeREORGReorg
  1. 01
    BitcoinTalk — Strange block 74638

    ジェフ・ガルジックの最初の警告、正確な出力、オーバーフロー解析、対応のタイムライン。

  2. 02
    BitcoinTalk — overflow bug SERIOUS

    当時の開発者による調整、検証エラーの修正、および修正されたブロックチェーンへの移行。

  3. 03
    Bitcoin Core — transaction consensus checks

    現在の実装では、個々の出力の範囲とその合計に対するチェックを行っている。

次の物語 · 14Slush Pool:採掘を宝くじ任せにしない、プラハ発のアイデア