Отчёт по поводу инцидента
В этом отчете используются технические термины, специфичные для блокчейна Everscale, которые могут быть не знакомы читателям. Для удобства, мы включили ниже небольшой глоссарий данных терминов.
Глоссарий
Опкод — инструкция на языке ассемблера, которая определяет определенную атомарную логику, которая должна выполняться виртуальной машиной.
Мастерчейн — главная часть сети Everscale. Консенсус, конфигурация блокчейна и логика размещения стейков происходят именно в мастерчейне.
Главный Воркчейн — часть блокчейна Everscale где развертываются смарт-контракты, размещаются децентрализованные приложения и происходят основные действия связанные с пользователями.
Коллатор — узел сети который создает (выпускает) блоки. Выпуск блоков включает в себя несколько этапов, на которых узлы манипулируют внутренней очередью сообщений для их проверки и включения новых транзакций в блок.
Очередь внутренних сообщений — структура данных, в которой хранятся сообщения, подлежащие обработке нодой-коллатором. Неэффективность в некоторых частях кода, отвечающих за манипулирование этой структурой в течение периода коллации, привела к возникновению инцидента.
Разделение цепочки — функция, которая назначает различные подмножества аккаунтов для обработки отдельными группами валидаторов в зависимости от текущей нагрузки. Разделение цепочки позволяет сети выполнять смарт-контракты параллельно, чтобы выдерживать растущую нагрузку.
Слияние цепочек — противоположное понятие к разделению цепочки. Когда нагрузка уменьшается, разделенные цепочки объединяются обратно, поскольку больше не требуется работа нескольких групп валидаторов.
Время простоя — полная или частичная остановка сети на определенный период времени.
Ключевые моменты:
-Смарт-контракт, состоящий из двух опкодовых операций и специально подготовленного начального состояния был развернут и выполнен в основной сети.
-Эта комбинация двух опкодов эксплуатировала уязвимость в логике ноды Everscale.
-Эксплуатация уязвимости позволила разработчикам исполнить большой объем кода на ноде, заплатив за это небольшую цену.
-На первый взгляд техническая уязвимость на самом деле является проблемой экономической конфигурации системы.
-Команда ноды рассмотрела несколько вариантов устранения уязвимости, но после прохождения внутренних тестов в различных конфигурациях остановилась на одном.
-В первый день простоя стало ясно, что внедрение правильного решения займет более двух недель, включая разработку, тесты и первичный аудит.
-Комитет пришел к выводу, что такое длительное время простоя неприемлемо, и решил временно остановить исполнение смарт-контракта и внедрить первичные оптимизации ноды
-Очевидно, что эти изменения — не окончательны, и дальнейшие обновления в разработке
-Обновление сети проводилось в два этапа:
1. Обновление нод сообществом независимых валидаторов мастерчейна.
2. Обновление нод валидаторов главной цепочки
-Обновление не потребовало форка сети, но в конфигурацию блокчейна были внесены изменения. Важную роль в разрешении инцидента сыграла координация сообщества валидаторов сети.
-Сеть успешно обработала все пользовательские транзакции, которые были инициированы во время простоя.
-Средства пользователей не пострадали.
Подробности инцидента
25 апреля, примерно в 9:00 UTC начала происходить аномальная активность в сети Everscale. Это было вызвано несколькими попытками эксплуатации неэффективной логики ноды.
Первая попытка не увенчалась успехом и сеть продолжала работать в обычном режиме. Обработка сообщений, создание блоков и механизм разделения цепочек работали штатно.
Однако во время второй попытки пользователи начали замечать последствия работы эксплуатирующего смарт-контракта. Сеть не смогла обработать транзакции пользоватаелей а также транзакции, создаваемые данным контрактом из-за роста внутренней очереди сообщений. На этом этапе неэффективность кода, который обрабатывает вышеупомянутую очередь, начала влиять на скорость работы нод-коллаторов.
Создание блока стало слишком дорогостоящим с точки зрения временных ресурсов, что привело к включению в блок меньшего количества транзакций. Это привело к слиянию шардчейнов, которые ранее были разделены. Проще говоря, сеть начала “думать”, что нагрузка уменьшилась, в то время как на самом деле она увеличивалась все больше и больше. Когда очередь внутренних сообщений достигла порогового размера, ноды-коллаторы больше не могли создавать новые блоки, поскольку были заняты выполнением манипуляций со структурой данных очереди сообщений.
Несколько дней спустя, 30 апреля в 15:30 UTC произошла третья атака на сеть, эксплуатирующая ту же уязвимость гораздо более агрессивным способом. К счастью, разработчики смогли оперативно исправить ситуацию.
Технически говоря, блокчейн не был остановлен в ходе инцидентов. Был затронут только главный воркчейн в то время как мастерчейн работал в штатном режиме. Это позволило команде разработки и сообществу валидаторов скоординировать усилия и успешно обновить сеть, чтобы смягчить последствия инцидента.
Экономические аспекты атаки
Стоимость создания внутреннего сообщения для контракта состоит из:
- фиксированного значения для каждого сообщения
- платы за размер сообщения
- платы за создание сообщения
Для атакующего контракта все три значения были одинаковыми для каждого вызова и не менялись.
Для ноды-валидатора же ресурсы для обработки запроса росли логарифмически с увеличением количества необработанных сообщений.
Хронология инцидента
Первая попытка
Было обработано около 67 000 транзакций. Баланс смарт-контракта составлял 100 EVER, и был быстро опустошен платежами за газ для выполнения транзакций, прежде чем контракт смог нанести какой-либо ущерб сети. Никаких изменений в работе сети замечено не было.
Начиная с блока 34599096, блоки были полностью заполнены вызовами контракта, с 457 по 395 в блоке 34599144. В следующем блоке произошел сплит.
Позже, начиная с блока 34599181, контракт прекращает увеличивать очередь. Это связано с опустошением баланса контракта. После блока 34599191 происходит следующее разделение, и еще одно после блока 34599243. Обработка заканчивается на блоке 34599249.
Вторая попытка
Было обработано более 150 000 транзакций и еще 135 000 находились в очереди, прежде чем пользователи начали замечать проблему. Смарт-контракт на этот раз содержал больший баланс (1000 эверов) и смог частично остановить работу сети.
Сплит произошел после блока 34603059. Следующий блок 34603060 после сплита, содержал только одну транзакцию. После этого произошли сплиты после блоков 34603106, 34603160 и 34603237. Аналогично, в следующем блоке 34603238 была только одна транзакция.
Анализ причин
Архитектура Everscale гарантирует, что каждый смарт-контракт, создающий чрезмерную активность шардируется. По сути, это означает, что такой контракт, изолируется в своем шарде, и для его обработки выделяются вычислительные ресурсы. В то же время это не влияет на выполнение других смарт-контрактов в сети. В случае контракта эксплуататора, механизм шардирования, из-за очень большого количества сообщений отправляемых смарт-контрактом, был активирован и работал в обычном режиме, то есть контракт был изолирован в своем шарде и обработан. Несмотря на это, работа сети была нарушена изза растущего размера очереди внутренний сообщений.
Разработчики, расследовавшие инцидент, выявили причину замедления работы ноды, которая заключалась в том что при небольшом размере очереди ее обработка является условно бесплатной и, соответственно, не требует взятия комиссии. При больших значениях же данная операция становится дорогостоящей для узла. Однако в данном случае это все-равно не требовало списания комиссий. Это привело к ситуации, в которой смарт-контракт эксплуататора стал слишком дорогим для обработки. Стоимость обработки при этом не была списана с баланса смарт-контракта.
Решение
Инцидент требовал быстрой реакции. Чтобы исправить ситуацию, команда разработчиков внесла некоторые оптимизации в узел валидатора (где это было возможно, учитывая сжатые сроки) и приостановила выполнение смарт-контракта эксплуататора. Принятые меры являются временным решением для обеспечения скорейшего восстановления работы сети.
В долгосрочной перспективе Everscale работает над глобальным устранением выявленной уязвимости. Решение проблемы будет включать следующее:
-комплексная оптимизация экономики и алгоритмов ноды
-реорганизация рабочих процессов команды разработчиков для своевременного реагирования на инциденты и оптимизации алгоритмов в кратчайшие сроки.