Дело Stone Man

Внутри проблемы резервного копирования Bitcoin-кошелька, приведшей к потере 8 999 BTC

Stone Man сделал то, что советовали осторожным пользователям: создал резервную копию wallet.dat. Затем один платёж на 1 BTC и перезагрузка выявили ошибку. Копия была, а ключ к сдаче в 8 999 BTC — нет.

Блокчейн никогда не терял монеты.

Кошелёк потерял возможность их тратить.

Это различие превращает историю о плохой флешке в историю о архитектуре кошелька. Ранний Bitcoin не получал все будущие ключи из одной seed-фразы. Резервная копия была лишь снимком существующих ключей на момент копирования.

Ночь потери

Тщательное резервное копирование, 1 BTC на себя и один перезапуск с долгосрочными последствиями

Stone Man накопил 9 000 BTC и загрузил их в Bitcoin-клиент с Debian live CD. Система работала в памяти, и выключение удаляло активный кошелёк. Он сначала скопировал wallet.dat на флешку.

  1. 01

    Защитить

    Кошелёк сохранён в резервной копии

    Файл wallet.dat с 9 000 BTC копируется из активной системы на флешку.

  2. 02

    Самоплатёж

    Stone Man отправляет себе около 1 BTC

    Проверяя, когда подтвердится другой платёж, Stone Man отправляет себе около 1 BTC. Кошелёк расходует весь выход на 9 000 BTC и тихо создаёт новый ключ сдачи для остатка.

  3. 03

    Удалить

    Активная система выключается

    Кошелёк в памяти с новым ключом сдачи исчезает до обновления резервной копии.

  4. 04

    Восстановить

    Старая резервная копия возвращается

    Блокчейн показывает транзакцию, но восстановленный кошелёк не может потратить выход сдачи на 8 999 BTC.

“Я и представить не мог, что это может поставить под угрозу весь мой баланс.”

Stone Man, BitcoinTalk, 11 августа 2010— (переведено)

Что нам известно о Stone Man

Кто такой Stone Man?

Настоящая личность Stone Man неизвестна. Его профиль на BitcoinTalk — аккаунт 288. На форуме он сообщил, что со временем приобрёл 9 000 BTC, использовал Bitcoin на Debian live CD и сохранил копию wallet.dat перед выключением компьютера.

Мы не знаем его настоящего имени, где он жил, чем занимался и что произошло после обсуждения. Поздние утверждения о его личности не подтверждены.

Поиск отсутствующего ключа

Поиск ключа начался в 2010 году

Спустя несколько минут после того, как Stone Man попросил помощи, другой пользователь предложил проверить старый кошелёк. Insti восстановил транзакцию с помощью ранних инструментов Bitcoin от Гэвина Андресена. Для успешного восстановления сохранённый wallet.dat должен был содержать приватный ключ для адреса сдачи. Анализ 2010 года показал, что, вероятно, этого ключа там не было. Без него блокчейн мог показать, где находятся монеты, но никто не мог ими распоряжаться.

Август 2010

Первая попытка восстановить ключ

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

Май 2026

Новый поиск в 2026 году

В 2026 году анонимный пользователь форума сообщил, что проверил более 6,5 миллионов возможных ключей с помощью GPU. Ни один не совпал с отсутствующим адресом. Для сокращения поиска им потребовались бы данные от Stone Man и его старого кошелька.

Анализ транзакции

Почему отправка 1 BTC переместила все 9 000 BTC

Bitcoin тратит выходы транзакций целиком. Кошелёк Stone Man использовал выход на 9 000 BTC, вернул 1 BTC на выбранный адрес и создал второй выход на 8 999 BTC. Этот второй выход — сдача, а не кража.

ID транзакции eb5b761c7380ed4c6adf688f9e5ab94953dcabeda47d9eeabd77261902fccccf
Адрес сдачи 167ZWTT8n6s4ya8cGjqNNQjDwDGY31vmHg

Скрытая ошибка

wallet.dat — это снимок, а не гарантия будущих ключей

Оригинальный Bitcoin-кошелёк хранил независимо сгенерированные приватные ключи. При необходимости нового адреса сдачи он мог создать новый ключ после создания резервной копии. Восстановление старого файла восстанавливало старые ключи, но не могло воссоздать поздний случайный ключ.

Повторное сканирование блокчейна может обнаружить транзакцию и показать, куда ушли 8 999 BTC. Но оно не создаст отсутствующий приватный ключ. Видимость — не контроль.

Резервная копия на флешке Известный ключ A Может распознать и потратить исходный выход
Создано после резервного копирования
Удалённый активный кошелёк Отсутствующий ключ сдачи B Требуется для траты выхода на 8 999 BTC

Сначала пришло предупреждение

Stone Man не был первым, кого поймала сдача

14 июля 2010, почти за месяц до поста Stone Man, другой пользователь описал похожую ошибку в меньшем масштабе. Он сделал резервную копию кошелька с 1.21 BTC, пожертвовал 0.01 BTC, восстановил старый файл и увидел, как баланс упал до нуля.

Перед оплатой 1.21 BTC в одном выводе
Пожертвование 0.01 BTC
Сдача за новым ключом 1.20 BTC

К 21 июля пользователи явно предупреждали, что старая копия может содержать использованный ключ, но не новый ключ сдачи. Опасность была известна до потери 8 999 BTC.

Как изменился Bitcoin

От отдельных ключей к keypool, затем к детерминированным кошелькам

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

  1. Обнаружена ошибка

    Предупреждение о 1.20 BTC

    Пользователь восстанавливает старый кошелёк после пожертвования 0.01 BTC и теряет доступ к новосозданному выходу сдачи.

  2. Предложенный дизайн

    Сатоши описывает очередь будущих ключей

    Заранее сгенерированные адреса позволяли резервной копии содержать ключи, которые кошелёк ещё не использовал.

  3. Ошибка усугублена

    Stone Man теряет ключ сдачи на 8 999 BTC

    Эту архитектурную слабость сообщество уже не может игнорировать.

  4. Выпущен запас безопасности

    В Bitcoin 0.3.13.3 появился keypool

    Стандартный пул из 100 заранее сгенерированных ключей даёт резервным копиям ограниченный запас будущих адресов.

  5. Детерминированный стандарт

    BIP 32 определяет дерево ключей из одной seed-фразы

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

  6. HD по умолчанию

    Bitcoin Core внедряет детерминированное получение ключей

    Для новых HD-кошельков одна правильная резервная копия с seed-фразой может восстановить все производные ключи.

Запись реализации SVN r163 · Bitcoin 0.3.13.3
103849419a9c014a69c76b6f96e48b66cbc838ca

Коммит изменил создание транзакций, чтобы резервировать ключи сдачи из пула из 100 заранее сгенерированных ключей, а не создавать ключ только при построении транзакции.

Что это значит сегодня

Современные seed-фразы изменили восстановление, но не сделали резервное копирование необязательным

Иерархические детерминированные кошельки получают множество ключей из одной seed-фразы, поэтому ошибка Stone Man не должна повториться при правильном восстановлении. Bitcoin Core внедрил HD-кошельки в версии 0.13. Но импортированные ключи, старые не-HD кошельки, неизвестные пути генерации, потерянные пароли, повреждённые копии и непроверенные процедуры восстановления всё ещё могут привести к потере средств.

01

Знайте, какой у вас тип резервной копии

Seed-фраза, экспорт дескриптора, файл wallet.dat, резервная копия аппаратного кошелька и импортированный приватный ключ восстанавливаются по-разному.

02

Проверьте восстановление без перевода реальных средств

Проверьте, что восстановленный кошелёк генерирует ожидаемые адреса приёма и сдачи, прежде чем экстренная ситуация заставит вас гадать.

03

Рассматривайте импортированные ключи как отдельный риск

Ключи, импортированные после исходной seed-фразы или резервной копии, могут требовать отдельного экспорта и не всегда восстанавливаются из фразы восстановления.

04

Аккуратно переносите ценные старые кошельки

Создайте актуальный кошелёк из свежих данных восстановления, проверьте резервную копию, отправьте небольшой тестовый платёж и только потом переводите остаток.

Долговременный урок

Резервная копия полна лишь настолько, насколько полна модель ключей за ней

Потеря Stone Man не была взломом криптографии Bitcoin и не связана с неизвестным злоумышленником. Это была ошибка в дизайне восстановления, выявленная обычной транзакцией. Сеть сохранила учёт идеально; старая копия сохранила неправильный момент времени.

Монеты видны в блокчейне Приватный ключ восстанавливается из резервной копии

Частые вопросы

Действительно ли Stone Man потерял 8 999 BTC?

Публичная транзакция потратила один выход на 9 000 BTC и создала выходы на 1 BTC и 8 999 BTC. Stone Man сообщил, что приватного ключа для адреса сдачи на 8 999 BTC не было в восстановленной копии, и адрес не тратил выходы на момент проверки статьи.

Почему резервная копия wallet.dat Stone Man не восстановила монеты?

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

Был ли выход на 8 999 BTC взломом или платёж злоумышленнику?

Для объяснения транзакции не нужен злоумышленник. 8 999 BTC — это сдача от самоплатежа Stone Man на 1 BTC. Ошибка — потеря приватного ключа для этой сдачи.

Может ли такая же проблема с резервным копированием случиться с современной seed-фразой?

Правильно восстановленный детерминированный кошелёк может получить ожидаемые адреса для приёма и сдачи из правильной seed-фразы. Восстановление может не сработать, если seed неверен или неполон, неизвестна схема генерации, ключи импортированы отдельно, отсутствует пароль или резервная копия не проверялась.

Известно ли, что случилось со Stone Man?

Stone Man обратился за помощью на форум, сообщил, что у него всё ещё есть старый файл кошелька, и отвечал на технические вопросы. Позже он перестал публиковать сообщения. Мы не знаем, почему, и пытался ли он продолжать восстанавливать ключ в приватном порядке.

Продолжить расследование

Узнайте, где ещё может подвести безопасность кошелька

Stone Man потерял доступ из-за того, что резервная копия не включала новый ключ для сдачи. Сравните это с инцидентом COLDCARD, где ключи были, но часть из них создана на слабой случайности, и с адресным отравлением, когда владелец подписывает перевод на поддельный адрес.