
Полная история сбоев Solana: причины, исправления и извлеченные уроки
Содержание
- Введение
- Живучесть и безопасность
- Перезапуски сети
- Сообщения об ошибках
- Случаи сбоев
- Ошибка Turbine: декабрь 2020 года
- IDO Grape Protocol: сентябрь 2021 года
- Вторая ошибка: целочисленное переполнение
- Высокая перегрузка: январь 2022 года
- Спам Candy Machine: апрель / май 2022 года
- Налог Candy Machine на ботов
- Ошибка долговечного nonce: июнь 2022 года
- Ошибка дублирующихся блоков: сентябрь 2022 года
- Крупный блок перегружает Turbine: февраль 2023 года
- Бесконечный цикл повторной компиляции: февраль 2024 года
- Скоординированное исправление уязвимости: август 2024 года
- Процесс выпуска обновления с патчем
- Заключение
- Дополнительные материалы
Бип, бип, бип. Бип, бип, бип.
Резкие сигналы телефона прерывают сон Стивена и внезапно вырывают его из мира грез. В темноте ярко светится экран, а телефон неистово вибрирует на прикроватной тумбочке. Бип, бип, бип. Он стонет, сонно трет глаза и тянется за устройством. Вчитываясь в сообщение, он чувствует, как сердце уходит в пятки: нода отключена. Не раздумывая, он вскакивает с кровати полуодетым и пытается разблокировать телефон, пока продолжают поступать сообщения. И тут он понимает: отключился весь кластер.
В этот самый момент по всему миру, в разных городах и часовых поясах, сотни операторов нод смотрят на свои телефоны с тем же осознанием: наступил момент, которого они боялись, — сбой.
Введение
Как и все распределенные системы, Solana работает в условиях, где одна ошибка реализации или редкий пограничный случай могут привести к отказу всей сети. Сбои нарушают работу, но остаются неизбежной частью поддержки сложной распределенной инфраструктуры — будь то децентрализованные блокчейны, централизованные биржи или даже крупные поставщики облачных сервисов, такие как Amazon и Microsoft.
Вопрос не в том, произойдет ли отказ, а в том, когда это случится и как сеть будет развиваться, чтобы адаптироваться и лучше противостоять будущим инцидентам. Даже тщательное имитационное тестирование, тестовая сеть с вознаграждениями и активная программа поиска ошибок не позволяют ни одной, даже превосходно спроектированной системе предусмотреть все возможные сценарии отказа. Самые ценные уроки дает эксплуатация в реальных условиях.
За последние пять лет Solana пережила семь отдельных сбоев: пять из них вызвали ошибки клиентов, а два — неспособность сети справиться с потоками спам-транзакций. В ранних версиях Solana не было ключевых механизмов управления перегрузкой, таких как приоритетные комиссии и локальные рынки комиссий. Позже они оказались необходимы для снижения нагрузки на сеть. Отсутствие таких механизмов приводило к длительным периодам снижения производительности и перегрузки в течение 2022 года, поскольку сеть фактически поощряла спам.
В этой статье мы подробно разберем каждый сбой Solana, его первопричины, инициирующие события и меры по устранению. Кроме того, мы рассмотрим ключевые аспекты перезапуска сети, сообщения об ошибках и фундаментальные понятия отказов живучести и безопасности. Разделы лучше читать по порядку, но каждый из них самодостаточен, поэтому читатели могут сразу перейти к наиболее интересным темам или сбоям.
Живучесть и безопасность
Согласно теореме CAP, также известной как теорема Брюера, распределенная система может обладать только двумя из трех свойств:
- Согласованность — при каждом чтении видны все предыдущие операции записи.
- Доступность — каждый запрос получает ответ.
- Устойчивость к разделению — система продолжает работать при разделении сети.
Для блокчейнов устойчивость к разделению необходима: нарушения сетевого взаимодействия неизбежны. Поэтому приходится выбирать между AP (доступность + устойчивость к разделению) и CP (согласованность + устойчивость к разделению). Как и большинство PoS-сетей с быстрой финализацией, Solana ставит согласованность выше доступности и поэтому относится к системам CP. При критических сбоях она останавливается, а не выдает устаревшие данные и не допускает небезопасную запись. Это означает, что программное обеспечение ноды может перейти в невосстановимое состояние, требующее ручного вмешательства, но средства пользователей остаются в безопасности.
Отказ живучести: блокчейн перестает продвигаться вперед, из-за чего транзакции не подтверждаются, а блоки не создаются. Причиной может быть недоступность валидаторов, разделение сети или остановка консенсуса. В контексте теоремы CAP это соответствует потере доступности.
Отказ безопасности: финализированное состояние блокчейна некорректно изменяется или разделяется на форки. Это может привести к конфликтующим историям или двойному расходованию, часто из-за ошибок консенсуса или вредоносных атак. В контексте теоремы CAP это соответствует потере согласованности.
Solana ставит безопасность выше живучести. Поэтому при экстремальной нагрузке на сеть или отказе консенсуса сеть останавливается, а не рискует повреждением состояния. Сбои нарушают работу и могут повлиять на приложения, пользователей и валидаторов, но они предпочтительнее катастрофических последствий несогласованного или поврежденного реестра.
Перезапуски сети
Для перезапуска сети Solana необходимо определить слот последнего оптимистично подтвержденного блока и перезапустить ноды из доверенного локального снимка состояния этого слота. Поскольку слот перезапуска не определяется ончейн, операторы валидаторов должны достичь офчейн-консенсуса по безопасной точке отката. Координация проходит публично в канале #mb-validators в Solana Tech Discord, где профессиональные операторы валидаторов общаются в реальном времени. У большинства операторов есть автоматические системы оповещения, которые уведомляют их сразу после остановки производства блоков и обеспечивают быструю реакцию.
После достижения консенсуса по правильному слоту перезапуска операторы используют инструмент для работы с реестром, чтобы создать новый локальный снимок состояния, перезапустить валидаторы и дождаться возвращения в сеть не менее 80% общего стейка. Только после этого сеть возобновляет производство и валидацию блоков. Проверка того, что при перезапуске кластера офлайн остается не более 20% стейка, обеспечивает достаточный запас безопасности на случай, если ноды создадут форк или снова отключатся сразу после перезапуска.
Сообщения об ошибках
Программы вознаграждения за обнаружение ошибок платят исследователям безопасности за выявление уязвимостей программного обеспечения и сообщения о них. Это критически важная линия защиты, поскольку она заранее стимулирует обнаруживать ошибки до того, как ими смогут воспользоваться. Исследователям безопасности и разработчикам, обнаружившим потенциальные уязвимости в клиенте Agave, рекомендуется сообщать о них через соответствующие защищенные каналы. Подробные правила раскрытия информации доступны в репозитории Agave на GitHub.
За достоверные сообщения о критических уязвимостях предусмотрены вознаграждения, размер которых зависит от серьезности:
- Потеря средств: до 25 000 SOL
- Нарушения консенсуса или безопасности: до 12 500 SOL
- Потеря живучести или доступности: до 5 000 SOL
Кроме того, у клиента FireDancer есть отдельная программа вознаграждения за обнаружение ошибок на платформе Immunefi. Максимальное вознаграждение за критические находки составляет 500 000 USDC.
Случаи сбоев
В следующих разделах представлен подробный хронологический анализ сбоев и периодов сниженной производительности Solana, начиная с запуска Mainnet Beta 16 марта 2020 года. Мы рассмотрим ключевые инциденты, их первопричины и последующие улучшения сети, чтобы показать, как Solana со временем повышала стабильность и отказоустойчивость.
Ошибка Turbine: декабрь 2020 года
Время простоя: около шести часов
Основная проблема: ошибка распространения блоков
Исправления:
- Отслеживание блоков по хешу вместо номера слота
- Исправление участков Turbine, где сбои можно обнаруживать раньше
- Распространение первого обнаруженного сбоя среди всех валидаторов через gossip
Этот сбой был вызван ранее известной проблемой восстановления блоков и обработки кода, которую спровоцировала неопознанная ошибка в Turbine — механизме распространения блоков Solana. Сбой произошел, когда валидатор передал два разных блока для одного слота и распространил их в два отдельных раздела сети (A и B), а третий раздел независимо обнаружил несоответствие.
Поскольку каждый раздел контролировал лишь меньшую долю стейка, ни один из них не мог достичь консенсуса сверхбольшинства и продолжить цепочку. Основная проблема заключалась в том, как внутренние структуры данных Solana отслеживали блоки и их вычисленное состояние. Для ссылки на состояние и блок в соответствующем слоте система использовала номер слота Proof of History (PoH), то есть идентификатор u64. После разделения сети ноды ошибочно воспринимали блоки A и B как одинаковые, что мешало корректному восстановлению и синхронизации блоков.
Каждый раздел предполагал, что у другого находится тот же блок, что привело к фундаментальному конфликту:
- Ноды с блоком A отклоняли форки, созданные на основе блока B
- Ноды с блоком B отклоняли форки, созданные на основе блока A
Поскольку переходы состояния различались между разделами, валидаторы не могли восстановить или согласовать форки, и финализация стала невозможной.
Для устранения проблемы сервисам разрешили отслеживать блоки по хешу вместо номера слота. Если любое количество блоков одного слота создает разделы, система обрабатывает их так же, как разделы с блоками в разных слотах. Ноды могут восстановить все возможные форки, а консенсус — устранить разделение.
Хотя первоначальной причиной сбоя стала ошибка, большая часть простоя была связана с ожиданием возвращения в сеть достаточной доли стейка: для возобновления производства блоков Solana требуется участие не менее 80% стейка.
IDO Grape Protocol: сентябрь 2021 года
Время простоя: семнадцать часов
Основная проблема: переполнение памяти из-за транзакций ботов
Исправления:
- Игнорирование блокировок записи для программ
- Ограничение частоты пересылки транзакций
- Настраиваемое поведение повторных попыток RPC
- Приоритизация транзакций голосования TPU
14 сентября 2021 года сеть Solana серьезно остановилась после запуска ончейн-первичного предложения на DEX (IDO) от Grape Protocol на краудфандинговой платформе Raydium AcceleRaytor. Через 12 минут после начала IDO сеть оказалась перегружена беспрецедентным потоком транзакций от ботов и перестала создавать корневые слоты. По сути, эти боты провели распределенную атаку типа «отказ в обслуживании» (DDoS), создав транзакционную нагрузку выше пропускной способности сети.
На пике перегрузки:
- Некоторые валидаторы получали более 300 000 транзакций в секунду.
- Объем необработанных данных транзакций превышал 1 Гбит/с при 120 000 пакетов в секунду.
- Иногда трафик превышал физические ограничения сетевых интерфейсов, из-за чего пакеты терялись на порте коммутатора, даже не достигнув валидаторов.
Один из ботов сформировал транзакции так, чтобы заблокировать для записи 18 ключевых аккаунтов, включая глобальную программу токенов SPL и ныне закрытую программу Serum DEX. Это заблокировало все транзакции, взаимодействовавшие с этими аккаунтами, и значительно снизило возможности параллельной обработки Solana. Вместо независимого выполнения транзакций сеть столкнулась с узким местом и стала обрабатывать их последовательно, что еще сильнее усугубило перегрузку.
Исправление, игнорирующее блокировки записи для программ, уже было разработано и запланировано к выпуску. Последующий перезапуск сети позволил активировать обновление и навсегда устранить этот вектор атаки.
Во время IDO валидаторы получили поток транзакций от ботов и начали пересылать избыточные транзакции следующему лидеру, усиливая перегрузку. При перезапуске сети ввели ограничения частоты пересылки транзакций, чтобы будущие транзакционные штормы не перегружали лидеров.
RPC-ноды Solana автоматически повторяют неудачные транзакции, чтобы повысить надежность. Однако при экстремальной перегрузке этот механизм усугубил поток транзакций: старые транзакции продолжали циркулировать и не давали сети восстановиться. В Solana 1.8 появилось настраиваемое поведение повторных попыток RPC, позволяющее приложениям оптимизировать их с помощью более коротких сроков действия и стратегий экспоненциальной задержки.
При высокой перегрузке лидеры Solana не включали транзакции голосования, критически важные для поддержания консенсуса. Из-за отсутствия подтвержденных голосов консенсус остановился, прекратив производство новых корневых блоков. В более поздних версиях клиента Solana появился механизм приоритизации транзакций голосования, который не дает обычным транзакциям вытеснять их при будущих инцидентах.
Вторая ошибка: целочисленное переполнение
Во время перезапуска сети возникла вторая проблема. Валидаторы сообщили о резких колебаниях объема активного стейка. Причиной стала ошибка, из-за которой процент стейка неправильно умножался на 100 и превышал максимально допустимое значение. Механизм инфляции создал столько новых токенов SOL, что произошло переполнение 64-битного беззнакового целого числа. Ошибку быстро обнаружили и исправили до второго перезапуска.
Высокая перегрузка: январь 2022 года
Время простоя: отсутствовало
Основная причина: избыточное количество дублирующихся транзакций Частичное исправление:
- Выпуски Solana 1.8.12 и 1.8.14
- Оптимизация дедупликации SigVerify
- Повышение производительности кеша исполнителей
С 6 по 12 января 2022 года основная сеть Solana испытывала серьезную перегрузку, которая привела к снижению производительности и частичным сбоям. Причиной стали боты, рассылавшие чрезмерное количество дублирующихся транзакций и значительно снижая пропускную способность сети. Обработка блоков занимала больше времени, чем ожидалось, из-за чего следующий лидер создавал форк и еще сильнее снижал пропускную способность. На пике доля успешных транзакций упала на 70%. Клиент с трудом справлялся со все более сложными и ресурсоемкими транзакциями, что выявило ограничения его способности удовлетворять спрос.
Дополнительная нестабильность наблюдалась с 21 по 23 января, когда перегрузка сохранялась. 22 января публичная конечная точка RPC (https://api.mainnet-beta.solana.com) отключилась из-за злоупотреблений: спам из пакетных вызовов RPC перегрузил систему.
Для решения этих проблем выпуск Solana 1.8.12 был специально направлен на устранение исчерпания кеша программ, а в версии 1.8.14 улучшили кеш Sysvar, отбрасывание SigVerify и дедупликацию SigVerify.
Спам Candy Machine: апрель / май 2022 года
Время простоя: восемь часов
Основная проблема: спам-транзакции от аккаунтов ботов
Исправления:
- Налог на ботов в программе Candy Machine
- Улучшение работы с памятью в Solana v1.10
30 апреля 2022 года Solana столкнулась с беспрецедентным всплеском числа запросов на транзакции. Некоторые ноды сообщали о шести миллионах запросов в секунду, которые создавали более 100 Гбит/с трафика на ноду. Причиной стали боты, пытавшиеся получить новые NFT через программу Metaplex Candy Machine. Минтинг работал по принципу «первым пришел — первым обслужен», что создавало сильный экономический стимул наводнять сеть транзакциями ради победы в минтинге.
Когда объем транзакций резко вырос, у валидаторов закончилась память и они аварийно завершили работу, что в итоге остановило консенсус. Недостаточная пропускная способность голосования не позволяла финализировать предыдущие блоки, поэтому заброшенные форки не удалялись. В результате валидаторы оказались перегружены огромным количеством форков, которые требовалось оценить. Их мощности не хватало даже после перезапусков, поэтому для восстановления сети потребовалось ручное вмешательство.
Хотя этот сбой был похож на инцидент сентября 2021 года, Solana продемонстрировала более высокую отказоустойчивость. Несмотря на рост числа запросов на транзакции на 10 000% по сравнению с предыдущим сбоем, сеть оставалась работоспособной гораздо дольше. Это отражало улучшения, внесенные сообществом валидаторов после предыдущих проблем с масштабированием.
После согласования канонического снимка состояния перезапуск сети занял менее 1,5 часа. В Solana v1.10 улучшили использование памяти, чтобы ноды могли дольше выдерживать замедленный или остановившийся консенсус.
Однако фундаментальные проблемы оставались нерешенными. Лидер по-прежнему обрабатывал транзакции, конкурировавшие за одни и те же данные аккаунта, по принципу «первым пришел — первым обслужен» и без эффективной защиты от спама. Пользователи не могли обозначить срочность своих транзакций. Для решения проблемы предложили три практических долгосрочных механизма.
Внедрение QUIC: ранее Solana использовала сетевой протокол UDP (User Datagram Protocol) для отправки транзакций через Gulf Stream от RPC-нод текущему лидеру. UDP быстр и эффективен, но не устанавливает соединение и не поддерживает управление потоком или подтверждение получения. Поэтому он не позволяет эффективно сдерживать или пресекать злоупотребления. Чтобы контролировать сетевой трафик, протокол приема транзакций валидатором (то есть этап Fetch в TPU) заново реализовали на QUIC.
QUIC стремится объединить преимущества TCP и UDP. Он обеспечивает быструю асинхронную связь, как UDP, но при этом поддерживает защищенные сеансы и расширенные стратегии управления потоком, как TCP. Это позволяет ограничивать отдельные источники трафика, чтобы сеть могла сосредоточиться на обработке настоящих транзакций. В QUIC также есть отдельные потоки, поэтому отбрасывание одной транзакции не блокирует остальные. В конечном итоге QUIC интегрировали в клиент Solana Labs в выпуске 1.13.4.
Взвешенное по стейку качество обслуживания (SWQoS): была внедрена новая система, которая отдает приоритет сетевому трафику в зависимости от стейка валидаторов. Валидаторы с более высоким стейком могут эффективнее отправлять транзакции. В рамках этого механизма валидатор с 3% общего стейка может отправлять лидеру до 3% от общего количества пакетов. SWQoS обеспечивает устойчивость к атакам Сивиллы и затрудняет злоумышленникам переполнение сети низкокачественными транзакциями. Этот подход заменил прежнюю модель «первым пришел — первым обслужен», которая принимала транзакции без разбора и учета их источника.
Введение приоритетных комиссий: после приема транзакции по-прежнему конкурируют за доступ к общим данным аккаунтов. Ранее эта конкуренция разрешалась по простому принципу «первым пришел — первым обслужен», и пользователи не могли обозначить срочность транзакций. Поскольку транзакцию может отправить кто угодно, на этом этапе для приоритизации нельзя использовать взвешивание по стейку. Для решения проблемы в программу Compute Budget добавили новую инструкцию, которая позволяет пользователям указывать дополнительную комиссию, взимаемую при выполнении и включении в блок. Приоритет выполнения транзакции определяется отношением комиссии к числу вычислительных единиц, что обеспечивает более динамичный и рыночный подход к упорядочиванию транзакций.
Налог Candy Machine на ботов
Для борьбы со спамом ботов Metaplex быстро ввела жестко заданный налог в размере 0,01 SOL на транзакции минтинга, взаимодействующие с программой Candy Machine. Этот антиспам-механизм взимал минимальную комиссию, чтобы сдерживать вредоносную активность, не наказывая добросовестных пользователей за случайные ошибки. Налог применялся в определенных случаях, включая:
- Попытку минтинга до запуска Candy Machine
- Попытку минтинга после исчерпания всех объектов
- Транзакции, в которых mint или set collection не были последней инструкцией
- Использование неверного ID коллекции
- Несоответствие инструкций Set Collection
- Несоответствие подписанта-плательщика между инструкциями установки коллекции и минтинга
- Подозрительные транзакции с участием запрещенных программ
- Попытку минтинга из защищенной AllowList Candy Machine без необходимого токена списка разрешений
Эта экономическая мера оказалась очень эффективной. Средства снайперов минтинга быстро иссякли, и спам прекратился. За первые несколько дней боты в совокупности потеряли более 426 SOL.
Ошибка долговечного nonce: июнь 2022 года
Время простоя: четыре с половиной часа
Основная проблема: ошибка долговечного nonce, приведшая к отказу консенсуса
Исправления:
- Временное отключение транзакций с долговечным nonce
- Обновление Solana 1.10.23
Ошибка среды выполнения позволяла дважды обрабатывать некоторые транзакции с долговечным nonce: сначала как обычную транзакцию, а затем как транзакцию с nonce, если в поле recent_blockhash использовался недавний хеш блока вместо долговечного nonce. Это привело к недетерминированному поведению валидаторов: одни ноды отклоняли второе выполнение, а другие принимали его. Критически важно, что блок приняли более трети валидаторов, из-за чего необходимые две трети не смогли достичь консенсуса.
В отличие от стандартных транзакций, транзакции с долговечным nonce не истекают и требуют отдельного механизма предотвращения двойного выполнения. Они обрабатываются последовательно с помощью ончейн-значения nonce, привязанного к каждому аккаунту и обновляемого при каждой обработке транзакции с долговечным nonce. После обновления та же транзакция с nonce больше не должна считаться действительной.
Чтобы устранить проблему, транзакции с долговечным nonce временно отключили. Позже исправление реализовали в Solana 1.10.23: оно предотвращало повторное выполнение за счет разделения доменов nonce и хеша блока. Обновление обеспечило хеширование хеша блока с фиксированной строкой при продвижении аккаунтов nonce, поэтому хеш блока больше нельзя было использовать как значение nonce. В результате транзакцию, однажды выполненную как обычная, нельзя повторно выполнить как транзакцию с долговечным nonce, и наоборот. Кроме того, новый тип DurableNonce заменил прежние значения хеша блока в состоянии аккаунта nonce, повысив типобезопасность и предотвращая подобные проблемы в будущем.
Прочитайте предыдущую статью в блоге Helius, чтобы подробнее узнать о долговечных nonce и их применении.
Ошибка дублирующихся блоков: сентябрь 2022 года
Время простоя: восемь с половиной часов
Основная проблема: ошибка в правилах выбора форка привела к отказу консенсуса
Исправление:
- Патч клиента
Сбой начался после того, как валидатор по ошибке создал дублирующиеся блоки на одной высоте. Это произошло потому, что основная и резервная ноды валидатора одновременно стали активными, используя один идентификатор ноды, но предлагая разные блоки. Такая ситуация сохранялась не менее 24 часов до сбоя, и в течение этого времени сеть правильно обрабатывала дублирующиеся лидерские слоты валидатора.
В конце концов кластер остановился, когда сеть столкнулась с невосстановимым форком из-за ошибки в логике выбора форка. Она не позволяла производителям блоков продолжать предыдущий блок, что привело к отказу консенсуса.
Форки регулярно возникают в Solana, и валидаторы обычно разрешают их, выбирая форк с большинством голосов — самый тяжелый форк. Если валидатор выбирает неверный форк, он должен переключиться на самый тяжелый, чтобы сохранить синхронизацию с сетью. Однако в этом случае валидаторы не могли вернуться к самому тяжелому банку, если его слот совпадал с последним слотом, за который они голосовали. Из-за этой ошибки валидаторы застряли, консенсус перестал продвигаться, и сеть в итоге остановилась.
В приведенном выше примере неисправный валидатор C создает дублирующиеся блоки в своих лидерских слотах с 5-го по 8-й. Когда следующим лидером становится валидатор G, он видит только один из дубликатов и соответствующим образом продолжает свой форк. Однако следующий лидер, валидатор D, обнаруживает оба дублирующихся блока валидатора C и решает отбросить их, продолжив свой форк поверх слота 4.
По мере продвижения сети форк валидатора G получает голоса большинства стейка и становится канонической цепочкой. Понимая, что его форк проигрывает, валидатор D пытается переключиться на форк валидатора G. Однако переход завершается неудачей из-за ошибки в логике выбора форка. Проблема возникает потому, что общий предок двух форков — дублирующийся блок в слоте 5 — был обработан неправильно, и валидатор D не смог распознать форк большинства. В результате валидатор D остается на своем форке и не может вернуться в основную цепочку.
Проблему устранили после проверки основной командой. Патч объединили с веткой master и перенесли во все ветки выпусков.
Крупный блок перегружает Turbine: февраль 2023 года
Время простоя: почти 19 часов
Основная проблема: отказ логики дедупликации в сервисах пересылки шредов
Исправления:
- Несколько улучшений логики дедупликации и фильтрации Turbine
- Добавление патча клиента, который заставляет производителей блоков прерывать работу при создании крупных блоков
Специализированный сервис пересылки шредов одного из валидаторов дал сбой и во время его лидерского слота передал исключительно большой блок — почти 150 000 шредов, на несколько порядков больше стандартного блока. Это перегрузило фильтры дедупликации валидаторов, из-за чего данные непрерывно пересылались повторно. По мере создания новых блоков проблема усугублялась и в итоге полностью перегрузила протокол.
Всплеск аномального сетевого трафика перегрузил Turbine, поэтому данные блоков пришлось передавать через значительно более медленный резервный протокол Block Repair. Turbine умеет отфильтровывать крупные блоки, но сервисы пересылки шредов работают перед этой логикой фильтрации, снижая ее эффективность. В период сниженной производительности лидеры блоков автоматически переходили в режим только для голосования — защитный механизм, при котором лидеры исключают экономические транзакции, не связанные с голосованием.
Основной причиной проблемы стал отказ логики дедупликации в сервисах пересылки шредов, из-за которого не удавалось предотвратить избыточную повторную передачу шредов. Кроме того, фильтр дедупликации в конвейере ретрансляции изначально не был предназначен для предотвращения циклов внутри дерева Turbine, что усугубило проблему.
Сеть перезапустили вручную, понизив версию до последней известной стабильной версии программного обеспечения валидаторов. Для устранения этих проблем в Solana v1.13.7 и v1.14.17 улучшили логику дедупликации, повысив ее способность предотвращать насыщение фильтров и обеспечив более надежную работу сети.
Бесконечный цикл повторной компиляции: февраль 2024 года
Время простоя: почти пять часов
Основная проблема: ошибка, вызывающая бесконечный цикл повторной компиляции в кеше JIT
Исправления:
- Отключение устаревшего загрузчика в v1.17.20
Валидатор Agave выполняет оперативную JIT-компиляцию всех программ перед выполнением транзакций, которые на них ссылаются. Для оптимизации производительности результаты JIT часто используемых программ кешируются, что сокращает число ненужных повторных компиляций. В Agave v1.16 существующий механизм кеширования LoadedPrograms заменили новой реализацией ExecutorsCache, которая повысила эффективность в нескольких аспектах.
LoadedPrograms предоставлял глобальное представление кешированных программ с учетом форков, сокращал дублирование учетных данных и позволял потокам выполнения транзакций совместно загружать новые программы, предотвращая конфликты компиляции. Важной функцией системы было отслеживание слота, в котором программа становится активной — так называемой эффективной высоты слота. Это позволяло выявлять аннулирование кеша при обновлении ончейн-данных программы.
Эффективная высота слота большинства программ определялась по слоту развертывания, сохраненному в их ончейн-аккаунте. Однако программы, развернутые с помощью устаревших загрузчиков, не сохраняли этот слот развертывания в аккаунтах. В качестве обходного решения LoadedPrograms назначал таким программам эффективную высоту слота, равную нулю.
Исключение возникало при обнаружении инструкции deploy, указывавшей на замену байт-кода программы. В этом случае LoadedPrograms временно добавлял запись с правильной эффективной высотой слота. Однако поскольку ни одна транзакция не ссылалась на эту запись, вероятность ее вытеснения была очень высокой. При вытеснении результат JIT удалялся, а программа помечалась как незагруженная, но эффективная высота слота сохранялась.
Если транзакция позже ссылалась на эту незагруженную программу, LoadedPrograms повторно компилировал ее и добавлял запись с ее эффективной высотой слота. Обычно после этого программа становилась доступна для выполнения на следующей итерации. Однако для программ устаревшего загрузчика новому результату JIT назначалась сигнальная высота слота, равная нулю, поэтому он оказывался позади предыдущей записи о незагруженной программе. В результате LoadedPrograms никогда не распознавал программу как загруженную, что запускало непрерывный цикл повторной компиляции на каждой итерации.
В Agave v1.16 LoadedPrograms не поддерживал совместную загрузку, поэтому инициирующую транзакцию можно было включить в блок. Затем блок распространялся по сети, и каждый валидатор воспроизводил его и попадал в тот же бесконечный цикл повторной компиляции. Поскольку во время сбоя более 95% стейка кластера работало на Agave v1.17, большинство валидаторов остановилось на этом блоке, прекратив работу сети.
Эту ошибку обнаружили неделей ранее при расследовании сбоя кластера Devnet, и развертывание патча уже было запланировано. В качестве решения изменения перенесли в Agave v1.17, а при перезапуске сети сразу удалили переключатель функции. Это отключило устаревший загрузчик, вызывавший ошибку, и предотвратило ее повторение.
Скоординированное исправление уязвимости: август 2024 года
Время простоя: отсутствовало
Основная проблема: неверное предположение о выравнивании адресов ELF
Исправления:
- Обновление с патчем
5 августа основные инженеры Anza получили сообщение от внешнего исследователя об уязвимости в клиенте Agave. Злоумышленник мог использовать ее для аварийного завершения работы валидаторов-лидеров и остановки всей сети. Инженеры Anza оперативно разработали патч, который затем проверили несколько сторонних компаний по информационной безопасности.
Программы Solana компилируются с помощью LLVM в формат исполняемых и компонуемых файлов (ELF). Уязвимость была связана с неверным предположением о выравнивании адресов в созданных файлах ELF. Стандартная очистка ELF выполняла различные проверки целостности, но не проверяла выравнивание секции .text. Из-за этого специально созданный вредоносный файл ELF мог определить секцию .text с неправильным выравниванием, заставив виртуальную машину перейти по недействительному адресу. Это привело бы к ошибке сегментации хоста и аварийному завершению работы валидатора.
Злоумышленник мог воспользоваться этой уязвимостью следующим образом:
- Создать вредоносную программу Solana, использующую опкод CALL_REG.
- Изменить файл ELF, чтобы нарушить выравнивание секции .text.
- Развернуть и вызвать программу в сети, спровоцировав аварийное завершение работы валидаторов.
Процесс выпуска обновления с патчем
Любой публичный выпуск обновления с патчем сразу раскрыл бы суть уязвимости всем. Злоумышленник мог бы успеть проанализировать уязвимость и остановить сеть до обновления достаточной доли стейка. Чтобы избежать такого сценария, критическая масса валидаторов должна была как можно быстрее установить патч.
К 7 августа несколько участников Solana Foundation связались с валидаторами в личных сообщениях на различных коммуникационных платформах. Они сообщили о предстоящем критически важном патче и отправили хешированное сообщение, подтверждавшее дату и уникальный идентификатор инцидента. Несколько известных представителей Anza, Jito и Solana Foundation опубликовали этот хеш в X, GitHub и LinkedIn, чтобы подтвердить подлинность сообщения. Пример опубликованного хеша:
В течение следующего дня основные участники продолжали связываться с валидаторами, подчеркивая срочность и необходимость конфиденциальности. В заранее назначенное время, 8 августа в 14:00 UTC, операторы валидаторов получили дополнительное сообщение с инструкциями по загрузке, проверке и применению патча. Патч разместили не в основном репозитории Agave, а в репозитории GitHub известного инженера Anza. Инструкции включали проверку загруженных файлов патча по предоставленным контрольным суммам SHA.
К 20:00 UTC 8 августа патч установило сверхбольшинство стейка, что обеспечило безопасность сети. После этого уязвимость и соответствующий патч раскрыли публично, призвав всех оставшихся валидаторов выполнить обновление.
Непубличное распространение патча и скрытая координация валидаторов вызвали вопросы о децентрализации Solana. Вскоре после инцидента исполнительный директор Solana Foundation Дэн Альберт ответил на эту критику в интервью СМИ.
«Я считаю, что важно не путать централизацию со способностью координировать действия. По всему миру работает 1 500 нод, производящих блоки, и управляет ими почти столько же отдельных людей… Возможность добровольно общаться со всеми или некоторыми из них не следует путать с централизацией».
Я считаю, что важно не путать централизацию со способностью координировать действия. По всему миру работает 1 500 нод, производящих блоки, и управляет ими почти столько же отдельных людей… Возможность добровольно общаться со всеми или некоторыми из них не следует путать с централизацией.

Заключение
На момент написания статьи Solana работает без сбоев более года, достигнув важного рубежа для удаления пометки «beta» из mainnet-beta. По мере созревания сети частота сбоев, по-видимому, снижается. Ожидается, что внедрение Firedancer повысит разнообразие клиентов и уменьшит риск полной остановки кластера из-за невыявленных ошибок или пограничных случаев. Однако некоторые лидеры сообщества, включая основателя Helius Мерта Мумтаза, прогнозируют, что сбои продолжатся. Время покажет.
Большое спасибо Zantetsu (Shinobi Systems) и OxIchigo за рецензирование предыдущих версий этой работы.
Дополнительные материалы
Похожие статьи
Подпишитесь на Helius
Следите за новостями разработки на Solana и получайте уведомления о наших публикациях


