720 / 736OVFL

Value Overflow Incident

Переполнение значения в блоке 74 638

Value Overflow Incident был критическим инцидентом консенсуса 15 августа 2010 года: транзакция в блоке 74 638 использовала переполнение 64-битной суммы, поэтому два огромных выхода прошли проверку и добавили 2^64 лишних сатоши в добываемую ветвь.

Ошибка была в реализации правила проверки, а не в криптографии или графике эмиссии. Каждый выход был положительным, но их сумма из-за переполнения становилась отрицательной. Разница между входом и этой отрицательной суммой выглядела как комиссия. Версия 0.3.10 добавила верхние границы для отдельных выходов и текущей суммы; после реорганизации на исправленную ветвь ошибочный блок исчез из активной истории.

15 августа 2010 года разработчик Jeff Garzik обратил внимание на странный блок 74 638. Транзакция 1d5e512a9723cbef373b970eb52f1e9598ad67e7408077a82fdac194b65333c9 потратила единственный вход в 0,50 BTC и создала два огромных выхода. В опубликованном тогда выводе printblock каждый из них равен 92 233 720 368,54275808 BTC. Автор транзакции, использовавшей уязвимость, достоверно не установлен: публичная запись подтверждает её данные, а не личность или мотив создателя. [1]

Bitcoin тогда представлял суммы как 64-битные целые числа со знаком в сатоши. Целочисленное значение каждого выхода, также записанное в шестнадцатеричном виде как 0x7ffffffffff85ee0, было положительным и чуть меньше максимума int64. Однако сумма 18 446 744 073 708 551 616 сатоши вышла за допустимый диапазон и превратилась в −1 000 000 сатоши. Старая проверка принимала этот отрицательный результат при сравнении со входом. Это была арифметическая ошибка, а не взлом подписей. Первый JSON-вывод в обсуждении содержит другие последние цифры после запятой; для точного расчёта здесь взято целое значение, подтверждённое и printblock, и шестнадцатеричной записью. [1]

Отрицательная сумма выходов −0,01 BTC при входе 0,50 BTC создавала видимость комиссии 0,51 BTC. Поэтому майнер получил в coinbase 50,51 BTC вместо базового вознаграждения 50 BTC. Если вычесть потраченный вход и учесть излишек в coinbase, два огромных выхода увеличили предложение в ошибочной ветви ровно на 18 446 744 073 709 551 616 сатоши: 2^64 сатоши, или 184 467 440 737,09551616 BTC. Таким образом, это число не является просто суммой двух выходов. [2]

Сообщество реагировало публично и под давлением времени. Lfm назвал ошибку серьёзной, Gavin Andresen предложил быстро сравнивать каждый выход с 21 миллионом BTC, а Satoshi Nakamoto опубликовал более широкое решение: отклонять отрицательный или слишком большой выход и после каждого сложения слишком большую текущую сумму. Satoshi также попросил майнеров временно остановиться, чтобы новая действительная ветвь могла быстрее догнать и заменить ошибочную. [2]

Satoshi объявил версию 0.3.10 15 августа 2010 года в 23:48 по времени форума, примерно через пять часов сорок минут после сообщения Garzik. Обновлённые узлы считали транзакцию и блок 74 638 недействительными и строили над последним общим действительным блоком. Позднее тогдашнее объявление сообщило, что хорошая ветвь обогнала плохую, поэтому обновлённый клиент мог автоматически реорганизоваться без ручного удаления файлов blockchain. [3]

Старый блок не редактировали в центральной базе данных. Существовали две конкурирующие истории: старые узлы принимали блок по исходным правилам, а исправленные отклоняли его и признавали только работу над действительным предком. Когда исправленная ветвь накопила больше Proof of Work, сеть последовала за ней, и инфляционный блок исчез из активной истории; решающими были установка правил пользователями и майнерами и последующая работа, а не приказ администратора. [3]

Введённая тогда защита до сих пор видна в Bitcoin Core. CheckTransaction отклоняет отрицательный выход, выход выше MAX_MONEY и текущую сумму вне MoneyRange; проверка после каждого сложения не даёт опасной сумме переполниться до сравнения. Комментарий кода прямо ссылается на CVE-2010-5139, а отдельная проверка повторяющихся входов напоминает о другом инциденте CVE-2018-17144. [4]

Инцидент показывает, что предел 21 миллион не является магической константой, защищённой одним хешированием: его обеспечивают точные правила проверки и правильная реализация. Аудит должен охватывать диапазоны значений, безопасное сложение, coinbase и комиссии, порядок проверок, граничные тестовые векторы и согласие независимых реализаций. История одновременно показывает способность раннего сообщества быстро устранять ошибки и его тогдашнюю зависимость от немногих разработчиков, майнеров и ручной координации. [5]

Для полной картины прочитайте эту статью вместе с Bitcoin Core, Правила консенсуса, Транзакция, UTXO, Reorg, Soft Fork.

01Существовали ли когда-нибудь 184 миллиарда BTC в действительном Bitcoin?

Они ненадолго существовали в добывавшейся тогда ошибочной ветви как результат блока с эксплойтом. Исправленные узлы отклонили эту ветвь, а действительная ветвь реорганизовала её, поэтому огромные выходы не входят в современный активный blockchain или набор UTXO. Сам исторический инцидент подтверждён блоком и реакцией того времени.

02Нарушил ли инцидент предел 21 миллион навсегда?

Нет в истории, принимаемой сегодня: исправленные правила консенсуса отклонили ошибочный блок, и его выходы исчезли при реорганизации. Событие показало, что предел зависит от правильной проверки и реально работающего ПО; запись в документации сама по себе не обеспечивает предложение.

DOC · 001BitcoinTalk — Strange block 74638Первичный источник DOC · 002BitcoinTalk — overflow bug SERIOUSПервичный источник DOC · 003BitcoinTalk — Version 0.3.10, block 74638 overflow patchПервичный источник DOC · 004Bitcoin Core — current CheckTransaction overflow checksДокументация DOC · 005CVE — CVE-2010-5139Документация
Обновлено: Сначала источники · Не является инвестиционной рекомендацией