Статьи

📉 Крах Биткоина 15 августа 2010 года: Баг на 184 миллиарда BTC, который едва не уничтожил криптовалюту

15 августа 2010 года Биткоин пережил одну из самых опасных атак за всю свою историю. В блоке №74638 неизвестный эксплуатировал критическую уязвимость в коде Bitcoin Core и создал из воздуха… 184 миллиарда BTC — в десятки тысяч раз больше, чем предусмотрено лимитом в 21 миллион монет.

Это событие стало важнейшей вехой в понимании того, как устроен Биткоин и что именно обеспечивает его устойчивость — не столько код, сколько люди, стоящие за ним.

⚠️ Что произошло?

Блок 74638

  • Дата: 15 августа 2010 года
  • Блок: №74638
  • Суть бага: В результате переполнения целочисленной переменной (integer overflow), один из участников сети смог создать две транзакции по 92,2 миллиарда BTC каждая — в сумме 184 миллиарда BTC.

Почему баг сработал?

Bitcoin Core на тот момент не проверял сумму выходов транзакции на переполнение чисел. В C/C++ это означает, что если сумма становится больше максимально допустимого значения (например, 2^64), она обнуляется или переходит в отрицательное значение, позволяя обойти проверку валидности.

if (txout_total > MAX_MONEY) // эта проверка не сработала из-за переполнения

Таким образом, злоумышленник смог обойти лимит монет, встроенный в протокол.

🚨 Реакция сообщества и исправление

Уязвимость была замечена очень быстро. Уже в течение нескольких часов после обнаружения:

  1. Сатоши Накамото лично выпустил патч Bitcoin версии 0.3.10, устраняющий уязвимость.
  2. Была внедрена строгая проверка суммы выходов транзакции.
  3. Блок 74638 и все последующие на его основе были откатаны.
  4. Узлы сети обновились на новую версию и начали майнить блоки на «чистой» цепочке.
  5. Через 5 часов зловредная цепочка была вытеснена из консенсуса.

Это был хардфорк, но не запланированный, а экстренный — и все же он прошёл быстро и эффективно благодаря скоординированным действиям сообщества.

🧠 Что это значит для Биткоина?

📌 Миф: «Биткоин — это доверие к коду»

Многие сегодня повторяют мантру о том, что Биткоин децентрализован, устойчив, и всё решается кодом. Но в августе 2010 года именно код дал сбой — и спасла ситуацию не магия алгоритмов, а люди:

  • Кто-то заметил аномалию.
  • Кто-то понял, в чем проблема.
  • Кто-то написал и опубликовал исправление.
  • Кто-то убедил майнеров и участников сети обновиться.

Это событие показало: в основе Биткоина лежит социальный консенсус, а не только машинный.

🔐 Как изменилась архитектура после инцидента?

После инцидента:

  • Была внедрена жёсткая проверка на превышение лимита монет.
  • Введены более строгие условия валидации транзакций.
  • Усилено тестирование новых релизов.
  • Сообщество стало больше осознавать важность наблюдения и ответственности.

📚 Делаем Резюме

Баг на 184 миллиарда BTC — это не просто ошибка, это лакмусовая бумажка децентрализованных систем. Он показал, что:

  • Код может дать сбой.
  • Люди, понимающие, как работает система, — её настоящие хранители.
  • Доверие в Биткоине — это не только про математические доказательства, но и про зрелость и ответственность сообщества.

Биткоин выжил не потому, что он безупречен. А потому, что сообщество было готово защитить его.

Если хочешь, могу добавить в статью технические детали кода, ссылки на архив форума Bitcointalk по этой теме или инфографику.

Хвала Злоумышленнику

Злоумышленник мог бы создать и меньшую сумму, но, скорее всего, он намеренно выбрал огромную цифру — 184 миллиарда BTC, чтобы:

✅ 1. Проверить границы и спровоцировать переполнение

  • В языке программирования C++, на котором написан Bitcoin Core, переполнение целочисленных значений (integer overflow) происходит при превышении максимального значения типа данных.
  • Тип int64_t (signed 64-bit integer), используемый для хранения суммы сатоши (1 BTC = 100,000,000 сатоши), имеет лимит около ±9.22 × 10^18.
  • Значения, близкие к этому пределу, как раз и могут вызвать непредсказуемое поведение — вроде обнуления, отрицательных значений или «оборачивания» числа.

→ Злоумышленник, скорее всего, сознательно протестировал крайние значения, чтобы спровоцировать баг.

✅ 2. Убедиться, что атака очевидна

  • Если бы он создал, скажем, 1000 BTC, это выглядело бы нормально, и никто не заметил бы сразу.
  • 184 миллиарда BTC — это настолько аномально, что привлекло моментальное внимание сообщества.

Это был способ сигнализировать об уязвимости громко, почти как «white-hat» (этический хакер), но без объяснений.

✅ 3. Игра на эффекте: продемонстрировать уязвимость протокола

  • Возможно, целью было не обогатиться, а показать миру, что в Биткоине всё еще есть критические дыры.
  • В 2010 году Биткоин только набирал обороты, и такие атаки могли разрушить доверие к проекту.

💡 Интересный факт

Никто не потратил эти 184 миллиарда BTC. Они были быстро замечены, а цепочка с багом отклонена. Поэтому никакой реальной финансовой выгоды злоумышленник не получил.

🔎 Вывод

Злоумышленник выбрал огромную сумму не случайно. Это была демонстрация уязвимости через резонансную и очевидную аномалию. Маленькая сумма осталась бы незамеченной, а огромная — мгновенно спровоцировала реакцию.

Хочешь, могу сделать блок с техническим примером кода переполнения или диаграмму, как это выглядело в блоке.

Вот технический пример на C++, который иллюстрирует суть бага с переполнением, аналогичного тому, что произошёл 15 августа 2010 года в Биткоине.

💻 Пример: переполнение int64_t при вычислении суммы выходов

🔹 Исходные условия:

  • Сатоши в коде хранятся как 64-битное целое число int64_t.
  • Лимит: 21 млн BTC = 2.1 * 10^15 сатоши.
  • Проверка должна быть: сумма выходов ≤ 21 млн BTC (в сатоши).

🔹 Код с потенциальным багом:


#include
#include int main() {
// Каждое значение — 92.2 миллиарда BTC в сатоши
int64_t txout1 = 9223372036854775807; // Максимальное значение int64_t
int64_t txout2 = 100; // Любая малая суммаint64_t total = txout1 + txout2; // тут происходит переполнениеstd::cout << "txout1: " << txout1 << std::endl;
std::cout << "txout2: " << txout2 << std::endl;
std::cout << "total: " << total << std::endl; // даст отрицательное число!// Проверка валидности — не сработает
if (total < 21000000LL * 100000000LL) {
std::cout << "Сумма допустима" << std::endl;
} else {
std::cout << "Сумма превышает лимит!" << std::endl;
}

return 0;
}

📉 Что произойдёт?

  • txout1 — это максимальное допустимое значение для int64_t: 9223372036854775807
  • При сложении с любым числом произойдёт переполнение → значение станет отрицательным или «обнулится» в пределах диапазона.
  • Проверка if (total < MAX_MONEY) не сработает, потому что total — уже отрицательное число, и оно «проходит» под лимитом.

🛠 Как это устранили в Bitcoin Core

После инцидента был добавлен код, который явно проверяет переполнение при каждом добавлении:
if (!MoneyRange(txout.nValue))
return state.DoS(100, false, REJECT_INVALID, "txout.nValue out of range");CAmount nValueOut = 0;
for (const auto& txout : tx.vout) {
nValueOut += txout.nValue;
if (!MoneyRange(nValueOut))
return state.DoS(100, false, REJECT_INVALID, "txout total out of range");
}

Функция MoneyRange() гарантирует, что значения не выходят за допустимый диапазон.

Похожие статьи

Кнопка «Наверх»