Перейти к содержанию

Web3: модель отказов L2, мостов и оракулов

Один зелёный индикатор скрывает разные результаты

В библиотеке теперь несколько независимых процессов: публикация выпуска, хранение файлов, доставка объявления между сетями, получение отчёта, случайное назначение и выдача права по доказательству. Пользователь видит одну страницу, но общий статус «всё готово» может оказаться ложным. Успех одного процесса не означает успех остальных.

В этой главе построим модель отказов для выпуска 2 курса 17. Исходный CourseCatalog публикует contentHash. В нашем формате это SHA-256 точных байтов release.json. Полный CID и сведения о копиях находятся в отдельном досье. MirrorCatalog отражает объявление в другой сети, ReleaseCheckRegistry хранит результаты наблюдения, AccessClaimRegistry выдаёт ограниченное право. Каждый модуль имеет собственное основание для изменения состояния.

Объявление есть, файлы недоступны

Пусть публикация подтверждена по выбранной политике сети, а contentHash совпадает с сохранённым манифестом. Это доказывает связь с определёнными байтами, но не гарантирует, что gateway сейчас отдаёт их. У библиотеки может остаться только недоступная копия, а цепь продолжит хранить правильное объявление.

Реакция: показываем отдельно «выпуск объявлен» и «копия недоступна». Пробуем разрешённый альтернативный источник тех же байтов, не заменяя contentHash на новый. Если вместо нужного файла пришла HTML-страница ошибки с кодом 200, проверка digest не проходит. Успешный HTTP-код не закрывает инцидент.

Если архив сохранился локально у оператора, восстановление реплики возвращает доступность без нового выпуска. Если байты потеряны, их нельзя восстановить из самого SHA-256. В журнале инцидента записывается именно потеря данных, а не «ошибка блокчейна». Возможности восстановления изучались в серии IPFS; здесь используем их как независимый слой.

Источник обновлён, зеркало отстаёт

Издатель объявил выпуск 2, а в сети B ещё виден выпуск 1. Причина может находиться до отправки, в доставке или в исполнении callback. Обозначать это одним красным статусом «мост сломан» недостаточно: повторное действие зависит от стадии.

Источник: edition 2, digest D2
Зеркало: edition 1, digest D1
Доставка: сообщение M2 отправлено; исполнение неизвестно

Разрешённая реакция:
  найти стадию M2 по исходным идентификаторам;
  согласовать повтор с правилами транспорта;
  не выдавать новое бизнес-объявление без причины.

D1, D2 и M2 — обозначения сценария, не фактические хеши и идентификаторы. При поздней доставке старого объявления MirrorCatalog проверяет номер редакции и область источника. Правильный транспортный отправитель не даёт старому сообщению права откатить текущий выпуск. Модель доставки CCIP помогает отличать стадии сервиса; правила редакции задаёт наша библиотека.

Цена не прошла проверку

Оракул вернул положительное число, но updatedAt слишком старый. Тогда предлагаемая сумма по необязательному USD-режиму не вычисляется как будто сведения свежие. Не подставляем нулевую цену и не переиспользуем незаметно последний ответ без объявленной политики.

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

На L2 дополнительно проверяется выбранный uptime-feed, если такая зависимость предусмотрена сетью и маршрутом цены. После восстановления sequencer может требоваться grace-период. Документация sequencer feeds описывает этот отдельный сигнал; он не заменяет свежесть самой цены. Статус доступности файла также не становится отрицательным от отказа ценового виджета.

Workflow доставил устаревший отчёт

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

Для диагностики нужны время наблюдения, время доставки, jobId, выпуск и revision. Если сохранять только момент принятия, пользователь может решить, что ресурс проверили прямо сейчас. Если сохранять только внешний observedAt, потеряется задержка и проверка того, разрешён ли момент наблюдения.

При повторе доставленного отчёта действуют ключи jobId и слота. Но эту политику нельзя механически перенести на VRF. Поздняя случайность относится к зафиксированному назначению; новая попытка выбора способна изменить результат. В рекомендациях VRF запрет переброса имеет другой смысл, чем повтор доставки обычного отчёта.

Proof корректен, действие отклонено

Участник доказал членство, но право уже использовано. Это не ошибка verifier. Журнал nullifier отвечает на прикладной вопрос однократности. Иной пример: proof относится к допустимой группе, но message содержит получателя B вместо A. Отказ по контексту защищает выдачу результата.

Интерфейс различает «доказательство не принято», «контекст не подходит» и «право использовано». Точные внутренние сведения об ошибках должны соответствовать политике приватности; не раскрываем скрытый witness ради удобной диагностики. Для восстановления потерянного секретного состояния нельзя запросить его у публичного verifier.

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

Отдельно фиксируем неопределённость наблюдения. Отсутствие транзакции в ответе одного RPC не доказывает отсутствие действия в цепи. До выяснения состояния сохраняем исходные идентификаторы и не объявляем операцию отменённой. Такой статус позволяет человеку продолжить диагностику, не создавая второй эффект только потому, что первый временно не виден.

Сводим отказ к разрешённому действию

Для каждого инцидента записываем четыре вещи: наблюдаемый факт, источник наблюдения, область влияния и разрешённое восстановление. Например, «gateway не ответил» — это факт доступности конкретной копии; «выпуск не опубликован» — иной факт реестра. Их нельзя взаимозаменять даже при одинаковом сообщении пользователю «попробуйте позже».

Ручная помощь также ограничена областью. Оператор хранения может восстановить копию, но не заменить получателя уже выданного права. Издатель может публиковать новый выпуск, но не объявлять повторный VRF-запрос невидимым. Администратор группы может отозвать членство, но не удалить неудобный журнал прошлых действий без отдельного договора.

Сценарии этой главы не исполнялись. Они формируют будущий план приёмки: отдельно потеря копии, задержка зеркала, устаревшая цена, старый revision, повтор nullifier и поздний VRF-ответ. Проверять их следует по конкретным состояниям и эффектам, сохраняя различие между техническим восстановлением и изменением обещанных пользователю правил.

Оглавление серии