Как можно потерять свои биткоины из-за неиспользуемых адресов

Перевод статьи разработчика и технического директора биткоин-стартапа Casa Джеймсона Лоппа.

Пользователи биткоина, которые самостоятельно хранят свои монеты, должны знать о различных вариантах кражи или потери своих ключей. Но что менее известно, так это то, что можно потерять свои биткоины, даже если у вас есть ключи!

Историческая справка

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

Иерархические детерминированные (Hierarchical Deterministic, HD) кошельки сделали резервное копирование простым одноразовым процессом. Однако вместе с HD-кошельками появилась новая проблема.

Если вы импортируете/восстанавливаете кошелек на основе пула ключей, то тут все довольно просто: все, что у вас есть ― это ключи, которые вы импортируете. С HD-кошельками ваш сид (seed) ― это портал к практически неограниченному количеству ключей. Поскольку мы не хотим тратить неограниченное количество времени на генерацию ключей из своего сида, импорт кошелька должен следовать определенному процессу обнаружения ключей, который включает в себя разумные ограничения на то, когда прекращать поиск средств.

Эти органичения в пути деривации включают достижение определенного количества неиспользуемых адресов, которые никогда не получали биткоины. Это число называется «ограничением по гэпу адресов» (address gap limit).

Как отмечено в BIP 44 и BIP 45, рекомендуемый предел гэпа адресов составляет 20 (и только на пути адресов приема, а не на пути адресов сдачи). Обратите внимание на этот раздел BIP 44:

Ограничение по гэпу адресов в настоящее время установлено на 20. Если программное обеспечение обнаруживает 20 неиспользуемых адресов подряд, то ожидается, что за пределами этой точки нет используемых адресов, и поиск прекращается. Мы сканируем только внешние цепочки адресов, потому что внутренние цепочки получают только те монеты, которые поступают из связанных внешних цепочек.

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

К сожалению, немногие кошельки следуют BIP 44, чтобы предупреждать пользователей о гэпе адресов.

Предположения…

Все вопросы, поднятые в этой статье, связаны с предположениями, которые не всегда верны. Какие это предположения?

  • Ни один пользователь не будет создавать 20 адресов подряд без получения депозита;
  • В пути деривации адресов сдачи никогда не будет гэпов.

Однако вы могли сгенерировать 20+ адресов приема во время тестирования кошелька, на которые вы не получали средства. Затем вы могли получить средства на адреса, которые были созданы после этого. Или:

  • Вы создали множество адресов для внесения в белый список на различных сторонних сервисах с целью вывода средств, но так и не перевели средства на них.
  • На вашем интернет-магазине/сервере BTCPay было создано более 20 счетов, которые не были оплачены. Это своего рода вектор DoS-атаки, потому что, как правило, не требуется больших затрат для того, чтобы заставить продавца выставить счет.
  • Вы запускаете сервис, которая принимает депозиты (например, биржу) и назначаете уникальные депозитные адреса для каждого пользователя. Если 20 пользователей зарегистрируют аккаунт, но никогда не вносят депозит, вы превысите гэп-лимит.

Возможные решения

Превентивные:

  • Ограничение по генерации адреса получения: в Casa мы не разрешаем приложению создавать новый адрес, пока на текущий адрес не поступят средства. Это может негативно повлиять на опыт пользователей, которые хотят сгенерировать много депозитных адресов, но мы считаем это функцией безопасности.
  • Добавьте в свой биткоин-кошелек логику, которая возвращает и перераспределяет неиспользуемые адреса. Это может вызвать путаницу у продавцов, если кто-то оплачивает счет, срок действия которого истек, а адрес повторно используется. Вы могли бы возразить, что такие сервисы должны увеличивать лимит для своих целей, но и с другим путем деривации вы неизбежно столкнетесь с проблемой прогнозирования.
  • Добавьте пользователю стоимость генерации адреса. Это не должны быть финансовые затраты, но они должны иметь какую-то уловку, чтобы отпугнуть спамеров. Если кто-то может просто написать скрипт или обновить страницу несколько раз, чтобы сгенерировать тысячу адресов в вашем кошельке, то у вас могут возникнуть серьезные проблемы.

Исправления:

  • Вручную заполнять гэпы, отправляя на них небольшие суммы BTC. Это дорого и представляет собой пустую трату ограниченного пространства блока.
  • Увеличить лимит гэпа в параметрах кошелька. Не все кошельки поддерживают это, но у некоторых (Electrum и Ledger Live) есть такая функция. Изменить конфигурацию лимита гэпа в Electrum можно в консоли:

wallet.change_gap_limit (100)

wallet.storage.write ()

Возврат пропавших средств

Мне уже неоднократно приходилось помогать людям восстанавливать средства, которые «таинственным образом исчезали», когда они пытались восстановить кошелек. Мое решение ― восстановить кошелек в Electrum (желательно загрузить сид на аппаратное устройство), а затем использовать консоль для быстрого создания адресов:

for x in range(1000): wallet.create_new_address(False)

for x in range(1000): wallet.create_new_address(True)

В левом нижнем углу окна Electrum вы должны увидеть сообщение «synchronizing…» в течение нескольких секунд, а затем, я надеюсь, ваши «пропавшие» биткоины появятся! Теперь вы сможете их нормально тратить.

У пользователей сервера BTCPay есть встроенный инструмент повторного сканирования, который устанавливает лимит гэпа по умолчанию на 10 000 ― насколько я знаю, это единственное ПО кошелька, которое упрощает этот процесс до нажатия кнопки.

Практический пример

Если вы хотите знать, каково это ― искать потерянные деньги, то установите Electrum и настройте следующий watch-only кошелек.

  • Запускаем: electrum –testnet
  • Создать новый кошелек.
  • Выберите «Стандартный кошелек».
  • Выберите «Использовать master key».
  • Вставьте следующий открытый ключ:

vpub5VbqiMAitbLcBPBLVaHWTudEfwaBwcAR4naUaM54kGTDq

FFB9bTU5sAwD3SoM7pD2JVVqTuojBRcQcauBeiswgm8QL1xwsLjrpx

  • Попытайтесь найти весь баланс кошелька (20 TBTC).

Гэпы адресов ― это проблема низкого уровня, которая не должна особенно беспокоить пользователей биткоина. Однако до тех пор, пока все популярные биткоин-кошельки не найдут более изящные решения для этих «крайних случаев», они будут превращать в кошмар пользовательский опыт людей, которые могут с ними столкнуться.

Интересное по теме