Как тут уже писали ранее неоднократно, виртуальная криптовалюта Bitcoin переживаете не лучшие времена. В течение нескольких недель пользователи старейшей и некогда крупнейшей биржи MtGox испытывали трудности при попытках вывести свои биткоины с биржи. В последние несколько дней трудности, переживаемые Bitcoin, вышли на новый уровень.
Следует заметить, что проблемы у MtGox начались ещё весной прошлого года, когда её расчётный счет в США был арестован в связи с расследованием незаконной деятельности по переводу денег без соответствующей лицензии. С тех пор биржа не может найти надёжных банковских партнёров, и регулярно задерживает платежи в традиционной валюте. Это привело к заметной курсовой разнице по сравнению с другими биржами, доходившей порой до 25%.
Впрочем, что касается вывода биткоинов, то и эти проблемы биржа испытывает не в первый раз. Как сообщает один из ключевых разработчиков Bitcoin Foundation Грегори Максвелл (ссылка), аналогичные проблемы биржа уже испытывала в сентябре прошлого года:
I first heard people reporting stuck transactions back in ~September. I looked into it and determined that Mtgox was spending immature coins. Freshly generated Bitcoins (from mining) can not be spend until they are at least 100 blocks deep in the blockchain. This prevents the funds from vanishing forever if the chain reorgs. I pinged magicaltux [прим.: Mark Karpelles] and after a couple tries got ahold of him. I think they also wasted some time on dead ends trying to resolve this before the actual nature of the problem was brought to their attention, e.g. raising their transaction fees with a mistaken belief that their fees weren't high enough.
Mtgox wasn't tracking if the coins were freshly generated or what their height was in their software. Including this data would apparently be a non-trivial change, and for high risk finance software even a trivial change takes a lot of work. I suggested a workaround (basically, just try to spend the oldest coins), and as far as I know they implemented it and it was effective.
MtGox не использует эталонное ПО, предоставляемое Bitcoin Foundation, для совершения операций с биткоином. Как они утверждают, эталонное ПО не подходит для их объёмов. Вместо этого они используют свой собсвтенный кошелёк, который, по слухам, был написан на PHP лично Марком Карпеллесом (aka MagicalTux) — директором биржи. При выводе криптовалюты они пытались использовать недавно сгенерированные биткоины (менее 100 подтверждений), что запрещено правилами протокола. В результате эти транзакции блокировались и не подтверждались. Чтобы радикально решить эту проблему, пришлось бы значительно переделать существующее ПО и отслеживать количество подтверждений для каждой порции монет. Вероятнее всего, MtGox не решился на радикальные изменения и вместо этого обошёл проблему, поменяв алгоритм выбора монет для исходящих транзакций — отдавая приоритет самым давним поступившим монетам.
Проблема, с которой они столкнулись на этот раз, в чём-то похожа. Начались эти проблемы, по-видимому, ещё в начале ноября, и постепенно усугублялись по мере того, как всё больше и больше биткоинов в их кошельке «застревало» в потерянных исходящих транзакциях. Более-менее нормальное объяснение того, что случилось, на русском языке уже было тут опубликовано ранее. Я лишь сделаю пару замечаний.
Во первых, malleable transactions — это не «тягучие», а «ковкие» (mallet = молот), или, если переводить по смылу, «деформируемые».
Во-вторых, многие исходящие транзакции MtGox изначально уже были не вполне корректные, и блокировались большинством узлов сети, поскольку содержали подпись в некорректном формате. Эта блокировка была добавлена в эталонную реализцию клиента относительно недавно, и, по-видимому, не все узлы и не все майнеры успели обновить своё ПО, что позволило MtGox до поры до времени продолжать посылать кривые транзакции. Кроме того, MtGox имеет прямой выход на некоторые майнерские пулы, что позволяло им обходить блокировку транзакций сетью.
Так или иначе, в какой-то момент кто-то таки посмотрел внимательно, почему его транзакция не проходит, исправил её (ковкость позволяет это делать не меняя подпись) и отправил. Поскольку транзакция изменилась по форме (не по содержанию), то изменился и её хэш, который mtGox использовал для отслеживания. Пользователь увидел, что монеты поступили на его адрес, но MtGox продолжала считать, что транзакция не подтверждена. Позже, автоматически или вручную (я склонен думать, что автоматически), MtGox пытается послать новую транзакцию этому же пользователю. Если эта новая транзакция использует «незастрявшие» монеты (которых изначально было не так много), то либо транзакция опять успешна (иногда, случайно, подпись была в корректном формате), либо пользователю нужно было опять «перековать» транзакцию, и он получал новую порцию монет на свой адрес.
Таким образом, эта уязвимость стала очевидной, возможной и легко эксплуатируемой. Хакеру не нужно было конкурировать с оригинальной некорректной транзакцией, которая и так блокировалась сетью, не нужно было выдумывать хитрые способы «перековывания» транзакции (многие из которых уже недоступны). Ему нужно было лишь «исправить» транзакцию.
О том, что на хэш нельзя полагаться для отслеживания транзакции, было известно ещё в апреле 2011 года. Чуть позже были внесены соответствующие изменения в эталонное ПО, чтобы оно не полагалось лишь на id транзакции, а отслеживало любые транзакции, расходующие соостветствующие выходы (забегая вперёд, изменения эти были недостаточными). Несмотря на это, по состоянию на конец января 2014 года разработчики в MtGox не имели ни малейшего понятия, что происходит. После нескольких дней расследования, 10 февраля MtGox наконец заблокировал все исходящие транзакции и опубликовал объявление на своём сайте. В нём они вкратце дают техническое описание проблемы и заявляют, что это критическая ошибка в протоколе, и что все биржи и оналйн кошельки могут быть подвержены атакам. О проблемах их собственной реализации клиента, которые сделали атаку легко реализуемой, в объявлении ни слова. MtGox так торопились обвинить всех и вся в своих проблемах, что даже забыли извиниться за свои собственные огрехи, нерасторопность и те, мягко говоря, неудобства, которые они доставили и продолжают доставлять своим пользователям.
После этого заявления MtGox последовал ответ сначала от некоторых ключевых разработчиков лично, зачем официальное ответное заявление Bitcoin Foundation. Все они признают, что это давно известный недостаток дизайна протокола, однако ни в коей мере не является критическим. Указывается, что эталонное ПО уже давно содержит код, позволяющий справляться с этими трудностями, и что MtGox следует исправлять их собственное ПО. У многих вызывает недоумение, почему это используется как предлог, чтобы блокировать вывод средств с биржи.
Очень многие биткойнеры сходятся на том, что главной целью этого заявления MtGox было дестабилизировать цену, чтобы покрыть потери биткоинов за счёт скупки их по низкой цене на собственной бирже и арбитража на других биржах.
Однако самое интересное началось вчера.
Некто запустил в сети биткоин узел/узлы, которые перехватывает все транзакции, и «перековывают» их в промышленных масштабах. По некоторым данным, только в течение 11 и 12 февраля было «мутировано» порядка 30000 транзакций. Протокол биткоин не позволяет украсть деньги таким образом, и единственной целью хакера, по-видимому, является атакая на биткоин в целом, с целью дальнейшей дестабилизации цены.
Как я заметил ранее, эталонная реализация протокола не полагается на tx id (хэш транзакции) для отслеживания расходования выходов. Однако он имеет одну особенность, которая не вполне совместима с «перековыванием». В настоящее время bitcoin-qt позволяет расходовать «сдачу» от транзакции немедленно, не дожидаясь подтверждений. Считалось, что это безопасная практика — поскольку сдача всегда поступает в наш собственный кошелёк. Если транзакция, создающая сдачу, будет подтверждена, то и последующая транзакция, расходующая сдачу, будет корректна, и общий баланс кошелька не нарушится. Если первая транзакция не подвтерждена, то и расходующая сдачу транзакция не будет иметь смысла. Перековывание транзакций вносит свои коррективы в это предположение, поскольку перекованная транакция, с изменённым tx id, может быть подтверждена, но транзакция, расходующая сдачу, становится некорректной из-за того, что tx id транзакции, от которой она зависит, изменился.
Таким образом, если кто-то активно расходует средства со своего кошелька, они могу столкнуться с тем, что баланс отражается некорректно, и некоторые транзакции никогда не завершаются. Биткоины при этом не теряются! Однако это вносит хаос в учёт израсходованных биткоинов, и создаёт определённые трудности, поскольку «застрявшие» транзакции непросто удалить вручную.
В настоящее время уже готовится патч, чтобы срочно решить эту проблему. Решение простое: не расходовать сдачу, пока не получено по крайней мере одно подтверждение. Также будет добавлена команда для ручной «очистки» застрявших транзакций. В долгосрочной перспективе предложено минимизировать возможности для «перековывания» транзакций, хотя пока не вполне понятно, возможно ли это полностью исключить.
Я рекомендую пока не пересылать биткоины, используя эталонный bitcoin-qt, пока новый релиз не будет выпущен. Если же всё же есть крайняя необходимость это сделать, то дожидайтесь хотя бы одного подтверждения, прежде чем делать новые транзакции.
Автор: il--ya