`devshard improvements` Validation protocol: eligibility, in-place checks и transparent randomness

Протокол проверки: соответствие требованиям, проверки на месте и прозрачная случайность.
Резюме
Нам следует заменить текущий шаблон начальных значений для каждого хоста + фазу MsgRevealSeed времени завершения на дизайн, в котором:
- каждое MsgValidation (или его эквивалент) можно проверить во время прибытия — получатели знают, имеет ли отправитель право проверить этот вывод;
- проверка выполняется на месте (вскоре после завершения), а не только после завершения расчетов;
- один путь протокола охватывает как автоматическую/выборочную проверку, так и проверку, оплачиваемую пользователем (например, «проверять каждый вывод» для критических рабочих нагрузок);
- случайность для того, «кто должен подтвердить», прозрачна (каждый может пересчитать право на участие) и ее трудно обмануть (пользователь + исполнитель + хосты с несколькими идентификаторами не могут выбрать благоприятные результаты);
- Очень важно: дизайн должен соответствовать частному выводу — избегайте хранения открытых текстовых подсказок/ответов для проверяющих на уровне исполнителя; предпочитают данные, хранящиеся пользователем, и зашифрованный текст, ориентированный на TEE, для узлов ML исполнителя и валидатора (см. §6 «Мотивация»).
- Транспорт (ограничение): сводит к минимуму дополнительные взаимодействия и лавину сообщений; разветвление в стиле сплетен только на этапе завершения — см. Ограничения и FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) .
Самая сложная часть — определить R — публичное начальное число или маяк — так, чтобы он был обязательным после фиксации работы, не подвергался измельчению секвенсором и был достаточно эффективным для проверки с малой задержкой.
Связано: FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md), HEIGHT_SYNC_PROTOCOL_PROPOSAL.md (./HEIGHT_SYNC_PROTOCOL_PROPOSAL.md) (высота основной сети и эскиз rand_seed), ../issues/validation-protocol-remove-seed-reveal.md , ../attacks.md .
Анализ: сегодняшняя подсеть (коротко)
Сегодня каждый хост получает ownSeed от подписи escrow_id и использует MustValidate(ownSeed, inference_id, …) во время PhaseActive, чтобы решить, следует ли ему проверять завершенный вывод ( subnet/state/validation.go , subnet/host/host.go ). При завершении MsgRevealSeed публикует эти начальные значения, чтобы recomputeCompliance мог сравнивать ожидаемые и фактические проверки для каждого адреса ( subnet/state/machine.go ). Документированные меры по смягчению последствий включают в себя «горячие ключи» против измельчения начальных сигнатур ( Attacks.md (../attacks.md) ).
Мотивация
1. Раскрытие семян усложняет доработку
Привязка честного учета к специальному раунду раскрытия информации приводит к росту логики фаз, сплетен и крайних случаев (кто раскрыл, дублирует, наказывает за нераскрытие). Завершение должно быть сосредоточено на расчете ( FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) ), а не на воспроизведении кубиков проверки подсети постфактум.
2. Нет хорошей предварительной проверки на предмет «должен был подтвердить, но не сделал».
Поскольку начальные значения раскрываются только в конце, подсеть не может дешево ответить во время сеанса: «этот вывод должен был получить подтверждение от набора S, и у нас есть доказательства от S». Жизнеспособность и обнаружение мошенничества требуют немедленного, поддающегося проверке права на участие, а не процедуры сверки, которая выполняется только тогда, когда все раскрыли информацию.
3. Открытая проверка + несколько адресов → гонка самопроверки
Если какой-либо хост может отправить подтверждение/недействительность без криптографического правила приемлемости, участник с несколькими слотами или связанными идентификаторами может проверить работу своего собственного исполнителя (или координировать свои действия с вступающим в сговор валидатором) до того, как честные узлы отреагируют. Это подрывает смысл выборки: первое сообщение побеждает, если только каждый получатель не применит одно и то же общедоступное правило перед принятием передачи.
4. Быстрая проверка на месте — не только постфактум
Операторам и пользователям нужны проверки сразу после фиксации MsgFinishInference с предсказуемой нагрузкой. Протокол должен поддерживать низкую задержку, сохраняя при этом случайность, чтобы исполнитель не мог знать, кто должен проверять, пока это не указано в правилах (см. Модель угроз).
5. Один путь для «системной» и «оплачиваемой пользователем» проверки
Два случая должны использовать одну форму сообщения и конвейер проверки:
- Выборочная проверка — протокол выбирает, кто должен проверять (из R, ставки, набора слотов и т. д.).
- Необязательная дополнительная проверка — пользователь платит (условия условного депонирования, флаг каждого вывода или премиум-уровень) за использование дополнительных валидаторов или 100% проверку критически важных операций.
Единственная разница заключается в том, сколько слотов/какая политика применяется; право на каждое сообщение проверки по-прежнему рассчитывается на основе общедоступных данных + R + политики оплаты, а не от случая к случаю.
6. Локальность и конфиденциальность данных (полезные данные, хранящиеся у исполнителя, а не у пользователя, с привязкой к TEE) — очень важно
Приоритет: это ограничение является первоклассным: любая схема проверки и приемлемости, которая требует использования долгоживущего открытого текста, размещенного у исполнителя (или общедоступных путей выборки), для проверки между хостами, несовместима с приведенным ниже направлением продукта.
Текущий поток проверки предполагает, что исполнитель хранит материалы подсказок и ответов в базе данных (или иным образом делает их доступными для выборки), чтобы другие хосты могли повторно запустить или сравнить работу. Это централизует конфиденциальный контент у исполнителя и противоречит частному направлению вывода: мы хотим, чтобы обработка вывода оставалась конфиденциальной (минимальное сохранение, минимальное раскрытие).
Совместимое направление:
- Только пользователь хранит подсказки и ответы (или зашифрованный текст, который пользователь никогда не расшифровывает в цепочке); пользователь предоставляет зашифрованный текст, зашифрованный для доверенной среды выполнения (TEE) конкретного хоста-исполнителя, так что только эта аттестованная среда может выполнить задание.
- Проверка может следовать той же схеме: пользователь (или инструмент политики на стороне пользователя) создает зашифрованный текст для каждого требуемого аттестованного валидатором узла ML / TEE, поэтому повторное выполнение происходит внутри границы валидатора, без того, чтобы БД исполнителя становилась системой записи для открытого текста.
Это означает, что протокол проверки должен четко сочетаться с известными подходящими валидаторами (чтобы пользователь или инструмент знал, какие открытые ключи/аттестаты использовать) и с одним логическим путем для выборочных и платных дополнительных проверок — без необходимости использования общедоступных URL-адресов полезной нагрузки на исполнителе.
Ограничения
Это требования к любому приемлемому проекту, а не причины, по которым мы меняем протокол (см. «Мотивация»).
Бюджет взаимодействия и сплетни
Протокол должен ограничивать межхостовый трафик и разветвление: отдавайте предпочтение прямым раундам пользователь-хост, целевым уведомлениям выбранного валидатора и детерминированному перерасчету вместо широковещательных штормов.
Сплетни могли бы решить многие проблемы синхронизации состояний и разветвлений в абстрактном плане, но мы не полагаемся на сплетни как на основной механизм синхронизации во время активного вывода и проверки — они плохо масштабируются, усложняют предположения о конфиденциальности и упорядочении, а также перекрываются с поверхностями злоупотреблений (см. ../issues/secure-gossip-propagation.md). Разветвление в стиле сплетен по всей подсети зарезервировано для фазы завершения (расчет, голосование/фиксация, широковещательная рассылка коллектора) согласно FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) ; обычная проверка использует прямые сообщения и детерминированные правила. Трафик проверки остается ограниченным и предназначен только для подходящих отправителей, где это возможно.
Цели
- Право на участие во время получения: при MsgValidation каждый хост отклоняет сообщение, если только отправитель не принадлежит EligibleValidators(inference_id, context) в рамках чистой указанной функции.
- Нет начального значения времени завершения для назначения проверки; Случайность расчетов по возможности остается отдельно от этой проблемы.
- Прозрачная случайность: R (или приемлемость на основе VRF) воспроизводится на основе согласованных входных данных, поэтому для аудита не требуется секретный раунд.
- Необманываемая привязка: R не должен контролироваться пользователем + исполнителем (или перемалываться через diff-макет); смотрите варианты дизайна ниже.
- Единый путь для выборки по умолчанию и дополнительной проверки, запускаемой пользователем/платной.
- Очень важно — частный вывод: правила проверки и случайности не должны требовать, чтобы исполнитель был надежным хранилищем открытого текста для подсказок/ответов, потребляемых другими хостами; поддерживать пользовательские полезные данные и шифрование, ориентированное на TEE, для узлов ML исполнителя и валидатора (см. §6 мотивации).
- Низкое разветвление: удовлетворение ограничений — Бюджет взаимодействия и сплетни.
Модель угроз
Два основных сценария:
- Нечестный исполнитель (без подельника по секвенированию). Исполнитель хотел бы заранее знать, будут ли его выводы подлежать проверке (например, пропустить реальную работу, если он считает, что ее не проверят). Это в значительной степени смягчается, если определить, кто должен проверять, только из входных данных, доступных после фиксации MsgFinishInference в каноническом сеансе — в частности, чтобы назначение было привязано к порядку, контролируемому пользователем / секвенсором (и любой согласованной примесью, такой как энтропия основной сети), а не к секретам, которые хранит только исполнитель. До этой фиксации исполнитель не должен иметь возможности вычислить R или подходящий набор валидаторов для этого вывода.
Нечестный исполнитель (без подельника по секвенированию). Исполнитель хотел бы заранее знать, будут ли его выводы подлежать проверке (например, пропустить реальную работу, если он считает, что ее не проверят). Это в значительной степени смягчается, если определить, кто должен проверять, только из входных данных, доступных после фиксации MsgFinishInference в каноническом сеансе — в частности, чтобы назначение было привязано к порядку, контролируемому пользователем / секвенсором (и любой согласованной примесью, такой как энтропия основной сети), а не к секретам, которые хранит только исполнитель. До этой фиксации исполнитель не должен иметь возможности вычислить R или подходящий набор валидаторов для этого вывода.
- Пользователь и исполнитель в одной атакующей группе. Здесь пользователь может формировать или задерживать различия вокруг MsgFinishInference. Основным остаточным риском является репутация/экономика: группа может попытаться управлять результатами, чтобы исполнитель получил признание за выводы, которые никогда не получают честного подтверждения. Это не рассматривается как критическое нарушение безопасности или работоспособности того же класса, что и ошибки консенсуса; все же стоит ограничиться выборкой, необязательной полной проверкой, оплачиваемой пользователем, и четкими правилами расчета, но идеальная защита от злонамеренного секвенсора, вступающего в сговор с исполнителем, может выходить за рамки самых строгих гарантий.
Пользователь и исполнитель в одной атакующей группе. Здесь пользователь может формировать или задерживать различия вокруг MsgFinishInference. Основным остаточным риском является репутация/экономика: группа может попытаться управлять результатами, чтобы исполнитель получил признание за выводы, которые никогда не получают честного подтверждения. Это не рассматривается как критическое нарушение безопасности или работоспособности того же класса, что и ошибки консенсуса; все же стоит ограничиться выборкой, необязательной полной проверкой, оплачиваемой пользователем, и четкими правилами расчета, но идеальная защита от злонамеренного секвенсора, вступающего в сговор с исполнителем, может выходить за рамки самых строгих гарантий.
Дополнительные риски (ортогональные приведенному выше разделению):
- Если R зависит от измельчаемых полей, вступивший в сговор пользователь может попытаться настроить содержимое различий, чтобы изменить сортировку; R в стиле маяка (вариант A) уменьшает это.
- Операторы с несколькими слотами или в стиле Сивиллы могут попытаться занять подходящий набор или участвовать в гонке для самопроверки, если только право на участие не является узким и публично проверяется при получении сообщения.
- Честные валидаторы не должны разглашать или делать выводы о знаниях, полезных для исполнителя, до того, как протокол исправит R для этого вывода (точный предикат подлежит уточнению для каждого варианта A/B/C).
Основная проблема: посев R
Нам нужно значение R_inf (или входные данные VRF для каждого валидатора), такое, что:
- Прозрачность: любая сторона пересчитывает один и тот же подходящий набор/вероятностную массу на основе опубликованных данных.
- Необманчивый: маяк фиксируется из основной сети (или состояния проверяемой цепочки), поэтому участники сговора не могут подделать хэш блока на согласованной высоте.
- Совместимость со скоростью: validationSeedHeight находится всего в нескольких блоках после FinishInferenceHeight пакета фиксации, за счет ожидания этого блока, прежде чем идентификатор валидатора станет окончательным.
Конкретный экземпляр приведен в разделе «Инструкции по проектированию» ниже (трехсторонние высоты + block_hash(validationSeedHeight) ).
Разработка протокола
Этот раздел представляет собой конкретный эскиз протокола. Он реализует вышеуказанные цели: прозрачная случайность из основной сети, отсутствие раунда раскрытия начальных чисел и участие третьих лиц, чтобы пользователь в одиночку не мог исправить маяк. Старые абстрактные параметры (только для VRF, только для корневого состояния) здесь не повторяются; они останутся альтернативами, если этот эскиз будет уточнен.
Согласование с текущей подсетью (сегодняшний код и поведение)
Первый сегмент потока соответствует subnet/user/user.go и subnet/host/host.go сегодня:
- Пользователь создает разницу, первая передача которой — MsgStartInference (код устанавливает InferenceId в новое значение nonce diff; исполнителем для этого вывода является group[inference_id % len(group)]).
- Маршрутизация: каждый diff имеет монотонный nonce; HTTP-запрос для этого различия отправляется на хостIdx = nonce % len(group) (циклический перебор по списку участников условного депонирования).
- Исполнителем вывода является хост inference_id % len(group) (тот же модуль); этот хост запускает RunExecution , затем ставит в очередь MsgFinishInference (подписанный исполнителем) в своем мемпуле для последующего включения в пользовательский diff.
Итак: начало → выполнение → завершение в очереди соответствует текущей реализации. Новый материал ниже начинается после того, как MsgFinishInference принимается в состояние сеанса (включено в разницу).
Именование: в текущей базе кода нет MsgStartValidation; началом работы с пользователем является MsgStartInference . Ниже «FinishInference commit» — это предлагаемый шаг (MsgFinishInferenceCommit или эквивалент), а не существующий тип передачи.
Предлагаемый протокол (после текущего запуска/выполнения/окончания)
Шаг 1. То же, что и сегодня, через MsgFinishInference.
Без изменений: различия, управляемые пользователем, выполнение исполнителя, MsgFinishInference с ResponseHash, количество токенов, ProposerSig и т. д.
Шаг 2 — MsgFinishInferenceCommit на следующем хосте (пользователь → хост B)
- Пользователь формирует новый diff (следующий nonce). Маршрутизация использует hostIdx := int(nonce % uint64(len(group))) ( subnet/user/user.go ) — обычно хост, отличный от получателя предыдущего diff, когда len(group) > 1 . Этот получатель — хост B. len(group)==1 : нет отдельного B ; определить запасной вариант (например, маяк только для основной сети без B/C или отсутствие выборочной проверки для этого размера условного депонирования).
- Разница включает в себя предложенное сообщение MsgFinishInferenceCommit (кодировка TBD), которое связывает готовый вывод (например, inference_id, response_hash, escrow_id) и содержит раздел синхронизации высоты, как в HEIGHT_SYNC_PROTOCOL_PROPOSAL.md (./HEIGHT_SYNC_PROTOCOL_PROPOSAL.md): последняя подтвержденная высота основной сети, LightBlock, sender_signature и т. д.
- Цель: представить вторую честную сторону (B), помимо пользователя, с проверяемым представлением цепочки, прежде чем фиксировать случайность.
Шаг 3. Хост B включает хост C (высота пинга, детерминированная третья сторона)
- B по протоколу выбирает хост C детерминированно случайным образом из набора: { хосты, которые не выполнили этот вывод и не являются B } (т.е. не исполнитель для этого inference_id, а не B). При отборе используется общедоступное правило (например, H(escrow_id || inference_id || …) % |eligible| ), поэтому все разработчики согласны.
- B отправляет C минимальный двусторонний запрос («фиктивный» запрос или запрос только для синхронизации высоты), который также передает последнюю высоту согласно HEIGHT_SYNC_PROTOCOL_PROPOSAL.md ; C отвечает подписанным подтверждением их последней выровненной высоты (те же правила конверта).
- B возвращает пользователю (в пути HTTP-ответа на запрос пользователя к B) доказательства, необходимые для того, чтобы пользователь мог прикрепить подписанные высоты B и C к каноническому пакету фиксации (точный формат проводов будет объявлен позже).
После этого шага каждая из трех сторон хранит проверяемое представление «последней высоты» на момент фиксации: пользователь (A), B, C.
Шаг 4 — Детерминированное FinishInferenceHeight
Все участники подсчитывают:
FinishInferenceHeight = max (высота_A, высота_B, высота_C)
используя только подписанные, проверяемые поля высоты из пакета фиксации (доказательства стиля раздела 1 каждой стороны, как в HEIGHT_SYNC_PROTOCOL_PROPOSAL.md (./HEIGHT_SYNC_PROTOCOL_PROPOSAL.md)). Это значение является детерминированным для одного и того же пакета.
Шаг 5 — валидацияSeedHeight и неизвестный хеш блока
Даже при наличии трех сторон уже могут существовать более свежие блоки основной сети, чем FinishInferenceHeight . Чтобы уменьшить вероятность того, что какая-либо сторона заранее выбрала маяк, определите:
validationSeedHeight = FinishInferenceHeight + VALIDATION_TRIGGER_OFFSET
где VALIDATION_TRIGGER_OFFSET — небольшая константа политики (например, 2 или 3 блока основной сети). Семантика: проверочная выборка для этого вывода привязана к высоте основной сети validationSeedHeight — то есть блоку на этой высоте, чей хэш никому не известен до тех пор, пока этот блок не будет завершен (согласно предположениям цепочки).
Пусть block_hash(H) будет хешем канонического идентификатора блока на высоте H. Определите, например:
R_inf = H(escrow_id || inference_id || block_hash(validationSeedHeight) || …)
и получить подходящих валидаторов из R_inf с помощью общедоступной формулы (например, взвешенной по репутации/долям, как того требует политика). Все согласны с тем, кто должен проверять, как только становится доступен блок_hash(validationSeedHeight).
Шаг 6 — Уведомление выбранного валидатора; проверка цепочки nonce пользователя
- Любой из A, B, C может отправить валидатору пакет доказательства: ссылки на вывод + пакет MsgFinishInferenceCommit + высоты + validationSeedHeight + block_hash, как только он станет известен.
- Валидатор проверяет EligibleValidators, используя то же правило R_inf.
- Пользователь продолжает передавать одноразовые номера другим хостам по порядку; когда валидатор выбирается в ходе циклического перебора, валидатор может прикрепить результаты проверки (или «еще не готов») к ответу, чтобы результаты могли попасть в тот же путь различий/сплетен, что и сегодня.
- Если результат недействителен, сплетни (или эквивалентные) должны появиться как можно раньше, чтобы могли начаться потоки проверочного голосования/опроса.
Шаг 7 — Финализация без ожидания пользователя
Если пользователь перестает отправлять сообщения, но начинается финализация, валидаторы (и другие хосты) публикуют все имеющиеся у них доказательства и частичные результаты, чтобы остальная часть группы могла проверить запланированные проверки. Проверки завершения должны включать в себя: все проверки, запланированные в соответствии с этим протоколом для готовых выводов, имеют соответствующие результаты (или явный тайм-аут / косую черту для каждой политики). Это соответствует TODO в FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) для незавершенных выводов и проверок.
Расширения (тот же путь) — «проверка каждого вывода»/дополнительная циклическая проверка.
Для рабочих нагрузок, требующих проверки каждого вывода (оплаченного пользователем или политики), не добавляйте второй случайный путь. Используйте то же правило сеанса, что и при обычной маршрутизации: заранее укажите nonce и отправьте следующий diff следующему хосту в циклическом переборе (hostIdx = nonce % len(group)).
Ограничение: валидатор этого дополнительного шага не должен быть исполнителем этого вывода. Исполнитель фиксируется inference_id % len(group) (индекс слота/хоста). При увеличении nonce, если индекс следующего хоста будет равен индексу исполнителя, пропустите его один раз (снова увеличьте), чтобы проверка всегда выполнялась на другом хосте.
Несколько слотов под одним адресом: если один оператор владеет несколькими слотами, правило по-прежнему основано на индексе хоста (или индексе первичного слота): ни один раунд проверки не может быть нацелен на тот же индекс исполнителя, что и вывод, даже если другой слот с тем же адресом получит сообщение - реализация последовательно отображает слот → индекс циклического перебора хоста, поэтому исполнитель не может проверить свое собственное выполнение через одноуровневый слот.
Угрозы и векторы атак (обзор этого эскиза)
Связь с протоколом сборщика финализации
FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) адресует расчет (голосование/фиксация, сборщики). Право на валидацию и R_inf из направлений проектирования ортогональны: завершение не должно зависеть от воспроизведения семантики MsgRevealSeed. Завершение по-прежнему должно согласовывать запланированные проверки (см. «Инструкции по проектированию — шаг 7» и TODO в этом документе по незавершенной работе).
Рекомендуемые следующие шаги
- Укажите MsgFinishInferenceCommit (поля, подписи, включение относительно MsgFinishInference).
- Pin VALIDATION_TRIGGER_OFFSET , EligibleValidators(R_inf, …) (веса репутации) и обязательный или необязательный шаг фиксации для выплаты.
- Замените RevealedSeeds/recomputeCompliance/penalizeUnrevealedSeeds правилами, которые соответствуют этому пакету маяка + фиксации (или временному мосту для устаревших условного депонирования).
- Обновите ../issues/validation-protocol-remove-seed-reveal.md и расширите PROTOCOL_TESTING_PROPOSAL.md (./PROTOCOL_TESTING_PROPOSAL.md) с помощью трехсторонней фиксации, синхронизации времени, пропуска фиксации и финализации перед маяком.
Открытые вопросы
- Минимальная допустимая задержка между завершением фиксации и первой разрешенной проверкой.
- Как оплачиваемая пользователем функция «проверить все» взаимодействует с ценами, ограничениями DoS и shard-state-trim-inferences-by-height.md (../issues/shard-state-trim-inferences-by-height.md).
- Требуют ли сообщения о недействительности того же набора прав, что и для проверки, или более строгого кворума.
Статус
Проект предложения — на рассмотрение перед реализацией.

Validation protocol: eligibility, in-place checks, and transparent randomness
Summary
We should replace the current pattern of per-host seeds + a finalization-time MsgRevealSeed phase with a design where:
- every MsgValidation (or equivalent) is checkable at arrival time — receivers know whether the sender is eligible to validate that inference;
- validation runs in place (soon after finish), not only post hoc at settlement;
- one protocol path covers both automatic / sampled validation and user-paid validation (e.g. “validate every inference” for critical workloads);
- randomness for “who must validate” is transparent (everyone can recompute eligibility) and hard to cheat (user + executor + multi-identity hosts cannot pick favorable outcomes);
- Very important: the design must align with private inference — avoid executor-wide storage of plaintext prompts/responses for verifiers; prefer user-held data and TEE-targeted ciphertext for executor and validator ML nodes (see Motivation §6 ).
- Transport (constraint): minimize extra interactions and message flooding ; gossip -style fan-out only in the finalization phase — see Constraints and FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) .
The hard part is defining R — the public seed or beacon — so that it is binding after work is committed , not grindable by the sequencer, and efficient enough for low-latency validation.
Related: FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) , HEIGHT_SYNC_PROTOCOL_PROPOSAL.md (./HEIGHT_SYNC_PROTOCOL_PROPOSAL.md) (mainnet height and rand_seed sketch), ../issues/validation-protocol-remove-seed-reveal.md , ../attacks.md .
Analysis: today’s subnet (short)
Today, each host derives ownSeed from signing escrow_id and uses ShouldValidate(ownSeed, inference_id, …) during PhaseActive to decide whether it should validate a finished inference ( subnet/state/validation.go , subnet/host/host.go ). At finalization, MsgRevealSeed publishes those seeds so recomputeCompliance can compare expected vs actual validations per address ( subnet/state/machine.go ). Documented mitigations include warm keys against seed-signature grinding ( attacks.md (../attacks.md) ).
Motivation
1. Seed reveal makes finalization heavier
Tying honest accounting to a dedicated reveal round grows phase logic , gossip , and edge cases (who revealed, duplicates, unrevealed penalties). Finalization should focus on settlement ( FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) ), not on reproducing subnet validation dice after the fact .
2. No good pre-finalization check for “should have validated but didn’t”
With seeds revealed only at the end, the subnet cannot cheaply answer during the session: “this inference was supposed to receive validation from set S , and we have evidence from S .” Liveness and fraud detection want immediate , verifiable eligibility — not a reconciliation pass that runs only when everyone has revealed.
3. Open validation + multiple addresses → self-validation race
If any host may send validate / invalidate without a cryptographic eligibility rule , a participant with several slots or linked identities can validate their own executor work (or coordinate with a colluding validator) before honest nodes react. That undermines the point of sampling: the first message wins unless every receiver applies the same public rule before accepting the tx.
4. In-place, fast validation — not only postfactum
Operators and users want validations right after MsgFinishInference is committed, with predictable load. The protocol should support low latency while still binding randomness so the executor cannot know who must check until the rules say so (see Threat model ).
5. One path for “system” and “user-paid” validation
Two cases should share one message shape and verification pipeline :
- Sampled validation — protocol chooses who must validate (from R , stake, slot set, etc.).
- Optional extra validation — user pays (escrow terms, per-inference flag, or premium tier) to require additional validators or 100% check for critical operations.
The only difference is how many slots / which policy applies; eligibility for each validation message is still computable from public inputs + R + payment policy , not ad hoc.
6. Data locality and privacy (executor-held payloads vs user-held, TEE-bound) — very important
Priority: This constraint is first-class : any validation and eligibility design that forces long-lived executor-hosted plaintext (or world-readable fetch paths) for cross-host verification is incompatible with the product direction below.
The current validation flow assumes the executor keeps prompt and response material in a database (or otherwise makes it fetchable ) so other hosts can re-run or compare work. That centralizes sensitive content on the executor and conflicts with a private inference direction: we want inference processing to stay confidential (minimal retention, minimal exposure).
A compatible direction is:
- Only the user holds prompts and responses (or ciphertext the user never decrypts on chain); the user supplies ciphertext encrypted for a specific executor host’s Trusted Execution Environment (TEE) so only that attested environment can run the job.
- Validation can follow the same pattern : the user (or a policy tool on the user’s side) produces ciphertext for each required validator’s attested ML node / TEE , so re-execution happens inside the validator’s boundary without the executor’s DB becoming the system-of-record for plaintext.
That implies the validation protocol must pair cleanly with known-eligible validators (so the user or tooling knows which public keys / attestations to target) and with one logical path for sampled vs paid extra checks — without requiring world-readable payload URLs on the executor.
Constraints
These are requirements on any acceptable design, not reasons why we change the protocol (see Motivation for that).
Interaction budget and gossip
The protocol must limit cross-host traffic and fan-out : prefer direct user–host rounds, targeted notifies to the selected validator, and deterministic recomputation over broadcast storms .
Gossip could solve many state-sync and fan-out problems cheaply in the abstract, but we do not rely on gossip as the primary synchronization mechanism during active inference and validation — it scales poorly, complicates privacy and ordering assumptions, and overlaps with abuse surfaces (see ../issues/secure-gossip-propagation.md ). Subnet-wide gossip–style fan-out is reserved for the finalization phase (settlement, vote/commit, collector broadcasts) per FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) ; ordinary validation uses direct messages and deterministic rules. Validation traffic stays bounded and eligible-sender-only where possible.
Goals
- Eligibility at receive time: On MsgValidation , every host rejects unless sender ∈ EligibleValidators(inference_id, context) under a pure, specified function .
- No finalization-time seed reveal for validation assignment; settlement randomness stays separate from this problem where possible.
- Transparent randomness: R (or VRF-based eligibility) is reproducible from agreed inputs so no secret round is needed for audit.
- Uncheatable binding: R must not be controllable by user + executor (or grindable via diff layout); see design options below.
- Unified path for default sampling and user-triggered / paid extra validation.
- Very important — private inference: validation and randomness rules must not require the executor to be the durable plaintext store for prompts/responses consumed by other hosts; support user-held payloads and TEE-targeted encryption for executor and validator ML nodes (see Motivation §6 ).
- Low fan-out: satisfy Constraints — Interaction budget and gossip .
Threat model
Two major scenarios:
- Dishonest executor (without an accomplice on sequencing). The executor would like to know in advance whether their inference will be subject to validation (e.g. to skip real work when they believe they will not be checked). That is largely mitigated if who must validate is fixed only from inputs available once MsgFinishInference is committed in the canonical session — in particular so that assignment is bound to the user/sequencer-controlled ordering (and any agreed mix-in such as mainnet entropy), not to secrets the executor holds alone. Before that commit, the executor should not be able to compute R or the eligible validator set for that inference.
Dishonest executor (without an accomplice on sequencing). The executor would like to know in advance whether their inference will be subject to validation (e.g. to skip real work when they believe they will not be checked). That is largely mitigated if who must validate is fixed only from inputs available once MsgFinishInference is committed in the canonical session — in particular so that assignment is bound to the user/sequencer-controlled ordering (and any agreed mix-in such as mainnet entropy), not to secrets the executor holds alone. Before that commit, the executor should not be able to compute R or the eligible validator set for that inference.
- User and executor in the same attacking group. Here the user can shape or delay diffs around MsgFinishInference . The main residual risk is reputation / economics : the group may try to steer outcomes so the executor gains credit for inferences that never receive honest validation. That is not treated as a critical safety or liveness break in the same class as consensus faults; it is still worth bounding with sampling, optional user-paid full validation , and clear settlement rules — but perfect prevention against a malicious sequencer colluding with the executor may be out of scope for the strongest guarantees.
User and executor in the same attacking group. Here the user can shape or delay diffs around MsgFinishInference . The main residual risk is reputation / economics : the group may try to steer outcomes so the executor gains credit for inferences that never receive honest validation. That is not treated as a critical safety or liveness break in the same class as consensus faults; it is still worth bounding with sampling, optional user-paid full validation , and clear settlement rules — but perfect prevention against a malicious sequencer colluding with the executor may be out of scope for the strongest guarantees.
Additional risks (orthogonal to the split above):
- If R depends on grindable fields, the colluding user may try to tweak diff contents to change sortition; beacon-style R (option A) reduces this.
- Multi-slot / Sybil-style operators may try to occupy the eligible set or race to self-validate unless eligibility is narrow and publicly verifiable at message receipt.
- Honest validators must not leak or infer executor-advantageous knowledge before the protocol fixes R for that inference (exact predicate TBD per option A/B/C).
The core problem: seeding R
We need a value R_inf (or per-validator VRF inputs) such that:
- Transparent: any party recomputes the same eligible set / probability mass from published data .
- Uncheatable: the beacon is fixed from mainnet (or auditable chain state) so colluders cannot forge the block hash at the agreed height.
- Compatible with speed: validationSeedHeight is only a few blocks after the commit bundle’s finishInferenceHeight , at the cost of waiting for that block before validator identity is final.
A concrete instantiation is in Design directions below (three-party heights + block_hash(validationSeedHeight) ).
Protocol design
This section is a concrete protocol sketch . It instantiates the goals above: transparent randomness from mainnet , no seed-reveal round , and third-party involvement so the user alone cannot fix the beacon. Older abstract options (VRF-only, state-root-only) are not repeated here; they remain alternatives if this sketch is refined.
Alignment with the current subnet (today’s code and behavior)
The first segment of the flow matches subnet/user/user.go and subnet/host/host.go today:
- User builds a diff whose first tx is MsgStartInference (the code sets InferenceId to the new diff nonce ; the executor for that inference is group[inference_id % len(group)] ).
- Routing: each diff has a monotonic nonce ; the HTTP request for that diff is sent to hostIdx = nonce % len(group) (round-robin over the escrow participant list).
- Executor for the inference is the host at inference_id % len(group) (same modulus); that host runs RunExecution , then queues MsgFinishInference (signed by the executor) in its mempool for later inclusion in a user diff.
So: start → execute → finish queued matches the current implementation. The new material below begins after MsgFinishInference is accepted into session state (included in a diff).
Naming: There is no MsgStartValidation in the current codebase; the user-facing start of work is MsgStartInference . Below, “FinishInference commit” is a proposed step ( MsgFinishInferenceCommit or equivalent), not an existing tx type.
Proposed protocol (after current start / execute / finish)
Step 1 — Same as today through MsgFinishInference
Unchanged: user-driven diffs, executor execution, MsgFinishInference with ResponseHash , token counts, ProposerSig , etc.
Step 2 — MsgFinishInferenceCommit on the next host (user → host B)
- User forms a new diff (next nonce ). Routing uses hostIdx := int(nonce % uint64(len(group))) ( subnet/user/user.go ) — typically a different host than the previous diff’s receiver when len(group) > 1 . That receiver is host B . len(group)==1 : there is no distinct B ; define a fallback (e.g. mainnet-only beacon without B/C, or no sampled validation for this escrow size).
- The diff includes a proposed message MsgFinishInferenceCommit (encoding TBD) that binds the finished inference (e.g. inference_id , response_hash , escrow_id ) and carries a height-sync section as in HEIGHT_SYNC_PROTOCOL_PROPOSAL.md (./HEIGHT_SYNC_PROTOCOL_PROPOSAL.md) : latest attested mainnet height , LightBlock , sender_signature , etc.
- Purpose: introduce a second honest party (B) besides the user, with verifiable chain view, before fixing randomness.
Step 3 — Host B involves host C (height ping, deterministic third party)
- B , by protocol, selects host C deterministically at random from the set: { hosts that did not execute this inference and are not B } (i.e. not the executor for this inference_id , and not B). Selection uses a public rule (e.g. H(escrow_id || inference_id || …) % |eligible| ) so all implementers agree.
- B sends C a minimal round-trip (a “dummy” or height-sync-only request) that also carries latest height per HEIGHT_SYNC_PROTOCOL_PROPOSAL.md ; C responds with a signed attestation of their latest aligned height (same envelope rules).
- B returns to the user (in the HTTP response path for the user’s request to B) the evidence needed so the user can attach B’s and C’s signed heights into the canonical commit bundle (exact wire format TBD).
After this step, three parties each hold a verifiable view of “latest height” at the time of the commit round : user (A) , B , C .
Step 4 — Deterministic finishInferenceHeight
All participants compute:
finishInferenceHeight = max(height_A, height_B, height_C)
using only signed, verifiable height fields from the commit bundle (each party’s section-1 style proofs as in HEIGHT_SYNC_PROTOCOL_PROPOSAL.md (./HEIGHT_SYNC_PROTOCOL_PROPOSAL.md) ). This value is deterministic given the same bundle.
Step 5 — validationSeedHeight and unknowable block hash
Even with three parties, fresher mainnet blocks may already exist than finishInferenceHeight . To reduce the chance that any party picked the beacon in advance, define:
validationSeedHeight = finishInferenceHeight + VALIDATION_TRIGGER_OFFSET
where VALIDATION_TRIGGER_OFFSET is a small policy constant (e.g. 2 or 3 mainnet blocks). Semantics: validation sampling for this inference is keyed to mainnet height validationSeedHeight — i.e. the block at that height whose hash is not knowable to anyone until that block is finalized (under the chain’s assumptions).
Let block_hash(H) be the canonical block ID hash at height H . Define e.g.:
R_inf = H(escrow_id || inference_id || block_hash(validationSeedHeight) || …)
and derive eligible validator(s) from R_inf with a public formula (e.g. weighted by reputation / stake as policy requires). Everyone agrees on who must validate once block_hash(validationSeedHeight) is available.
Step 6 — Notifying the selected validator; validation on the user’s nonce chain
- Any of A, B, C may send the validator a proof package : inference refs + MsgFinishInferenceCommit bundle + heights + validationSeedHeight + block_hash once known.
- The validator checks EligibleValidators using the same R_inf rule.
- User continues to advance nonces to other hosts in order; when the validator is picked by the round-robin, the validator may attach validation results (or “not yet ready”) to the response, so results can enter the same diff / gossip path as today.
- If the outcome is invalid , gossip (or equivalent) should surface that early so validation voting / challenge flows can start.
Step 7 — Finalization without waiting on the user
If the user stops sending messages but finalization starts, validators (and other hosts) publish whatever proofs and partial results they hold so the rest of the group can verify scheduled validations. Finalization checks should include: all validations scheduled under this protocol for finished inferences have corresponding results (or explicit timeout / slash per policy). This aligns with the TODO in FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) on unfinished inferences and validations.
Extensions (same path) — “validate every inference” / extra round-robin check
For workloads that require every inference to be checked (user-paid or policy), do not add a second randomness path. Use the same session rule as normal routing: advance the nonce and send the next diff to the next host in the round-robin ( hostIdx = nonce % len(group) ).
Constraint: the validator for this extra step must not be the executor for that inference. The executor is fixed by inference_id % len(group) (slot / host index). When incrementing nonce , if the next host index would equal the executor’s index , skip it once (increment again) so validation always lands on a different host.
Multiple slots under one address: if one operator owns several slots, the rule is still host-index (or primary slot index) based: no validation round may target the same executor index as the inference, even if another slot of the same address would receive the message — implementation maps slot → host round-robin index consistently so the executor cannot validate their own execution via a sibling slot.
Threats and attack vectors (review of this sketch)
Relation to finalization collector protocol
FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) addresses settlement (vote/commit, collectors). Validation eligibility and R_inf from Design directions are orthogonal : finalization should not depend on reproducing MsgRevealSeed semantics. Finalization must still reconcile scheduled validations (see Design directions — Step 7 and the TODO in that doc on unfinished work).
Recommended next steps
- Specify MsgFinishInferenceCommit (fields, signatures, inclusion relative to MsgFinishInference ).
- Pin VALIDATION_TRIGGER_OFFSET , EligibleValidators(R_inf, …) (reputation weights), and mandatory vs optional commit step for payout.
- Replace RevealedSeeds / recomputeCompliance / penalizeUnrevealedSeeds with rules that match this beacon + commit bundle (or interim bridge for legacy escrows).
- Update ../issues/validation-protocol-remove-seed-reveal.md and extend PROTOCOL_TESTING_PROPOSAL.md (./PROTOCOL_TESTING_PROPOSAL.md) with three-party commit , timing grind , omit commit , and finalization-before-beacon cases.
Open questions
- Minimum latency acceptable between finish commit and first allowed validation.
- How user-paid “validate all” interacts with pricing , DoS bounds , and shard-state-trim-inferences-by-height.md (../issues/shard-state-trim-inferences-by-height.md) .
- Whether invalidation messages require the same eligibility set as validation or a stricter quorum.
Status
Draft proposal — for review before implementation.
Протокол проверки: соответствие требованиям, проверки на месте и прозрачная случайность.
Резюме
Нам следует заменить текущий шаблон начальных значений для каждого хоста + фазу MsgRevealSeed времени завершения на дизайн, в котором:
Самая сложная часть — определить R — публичное начальное число или маяк — так, чтобы он был обязательным после фиксации работы, не подвергался измельчению секвенсором и был достаточно эффективным для проверки с малой задержкой.
Связано: FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md), HEIGHT_SYNC_PROTOCOL_PROPOSAL.md (./HEIGHT_SYNC_PROTOCOL_PROPOSAL.md) (высота основной сети и эскиз rand_seed), ../issues/validation-protocol-remove-seed-reveal.md , ../attacks.md .
Анализ: сегодняшняя подсеть (коротко)
Сегодня каждый хост получает ownSeed от подписи escrow_id и использует MustValidate(ownSeed, inference_id, …) во время PhaseActive, чтобы решить, следует ли ему проверять завершенный вывод ( subnet/state/validation.go , subnet/host/host.go ). При завершении MsgRevealSeed публикует эти начальные значения, чтобы recomputeCompliance мог сравнивать ожидаемые и фактические проверки для каждого адреса ( subnet/state/machine.go ). Документированные меры по смягчению последствий включают в себя «горячие ключи» против измельчения начальных сигнатур ( Attacks.md (../attacks.md) ).
Мотивация
1. Раскрытие семян усложняет доработку
Привязка честного учета к специальному раунду раскрытия информации приводит к росту логики фаз, сплетен и крайних случаев (кто раскрыл, дублирует, наказывает за нераскрытие). Завершение должно быть сосредоточено на расчете ( FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) ), а не на воспроизведении кубиков проверки подсети постфактум.
2. Нет хорошей предварительной проверки на предмет «должен был подтвердить, но не сделал».
Поскольку начальные значения раскрываются только в конце, подсеть не может дешево ответить во время сеанса: «этот вывод должен был получить подтверждение от набора S, и у нас есть доказательства от S». Жизнеспособность и обнаружение мошенничества требуют немедленного, поддающегося проверке права на участие, а не процедуры сверки, которая выполняется только тогда, когда все раскрыли информацию.
3. Открытая проверка + несколько адресов → гонка самопроверки
Если какой-либо хост может отправить подтверждение/недействительность без криптографического правила приемлемости, участник с несколькими слотами или связанными идентификаторами может проверить работу своего собственного исполнителя (или координировать свои действия с вступающим в сговор валидатором) до того, как честные узлы отреагируют. Это подрывает смысл выборки: первое сообщение побеждает, если только каждый получатель не применит одно и то же общедоступное правило перед принятием передачи.
4. Быстрая проверка на месте — не только постфактум
Операторам и пользователям нужны проверки сразу после фиксации MsgFinishInference с предсказуемой нагрузкой. Протокол должен поддерживать низкую задержку, сохраняя при этом случайность, чтобы исполнитель не мог знать, кто должен проверять, пока это не указано в правилах (см. Модель угроз).
5. Один путь для «системной» и «оплачиваемой пользователем» проверки
Два случая должны использовать одну форму сообщения и конвейер проверки:
Единственная разница заключается в том, сколько слотов/какая политика применяется; право на каждое сообщение проверки по-прежнему рассчитывается на основе общедоступных данных + R + политики оплаты, а не от случая к случаю.
6. Локальность и конфиденциальность данных (полезные данные, хранящиеся у исполнителя, а не у пользователя, с привязкой к TEE) — очень важно
Приоритет: это ограничение является первоклассным: любая схема проверки и приемлемости, которая требует использования долгоживущего открытого текста, размещенного у исполнителя (или общедоступных путей выборки), для проверки между хостами, несовместима с приведенным ниже направлением продукта.
Текущий поток проверки предполагает, что исполнитель хранит материалы подсказок и ответов в базе данных (или иным образом делает их доступными для выборки), чтобы другие хосты могли повторно запустить или сравнить работу. Это централизует конфиденциальный контент у исполнителя и противоречит частному направлению вывода: мы хотим, чтобы обработка вывода оставалась конфиденциальной (минимальное сохранение, минимальное раскрытие).
Совместимое направление:
Это означает, что протокол проверки должен четко сочетаться с известными подходящими валидаторами (чтобы пользователь или инструмент знал, какие открытые ключи/аттестаты использовать) и с одним логическим путем для выборочных и платных дополнительных проверок — без необходимости использования общедоступных URL-адресов полезной нагрузки на исполнителе.
Ограничения
Это требования к любому приемлемому проекту, а не причины, по которым мы меняем протокол (см. «Мотивация»).
Бюджет взаимодействия и сплетни
Протокол должен ограничивать межхостовый трафик и разветвление: отдавайте предпочтение прямым раундам пользователь-хост, целевым уведомлениям выбранного валидатора и детерминированному перерасчету вместо широковещательных штормов.
Сплетни могли бы решить многие проблемы синхронизации состояний и разветвлений в абстрактном плане, но мы не полагаемся на сплетни как на основной механизм синхронизации во время активного вывода и проверки — они плохо масштабируются, усложняют предположения о конфиденциальности и упорядочении, а также перекрываются с поверхностями злоупотреблений (см. ../issues/secure-gossip-propagation.md). Разветвление в стиле сплетен по всей подсети зарезервировано для фазы завершения (расчет, голосование/фиксация, широковещательная рассылка коллектора) согласно FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) ; обычная проверка использует прямые сообщения и детерминированные правила. Трафик проверки остается ограниченным и предназначен только для подходящих отправителей, где это возможно.
Цели
Модель угроз
Два основных сценария:
Нечестный исполнитель (без подельника по секвенированию). Исполнитель хотел бы заранее знать, будут ли его выводы подлежать проверке (например, пропустить реальную работу, если он считает, что ее не проверят). Это в значительной степени смягчается, если определить, кто должен проверять, только из входных данных, доступных после фиксации MsgFinishInference в каноническом сеансе — в частности, чтобы назначение было привязано к порядку, контролируемому пользователем / секвенсором (и любой согласованной примесью, такой как энтропия основной сети), а не к секретам, которые хранит только исполнитель. До этой фиксации исполнитель не должен иметь возможности вычислить R или подходящий набор валидаторов для этого вывода.
Пользователь и исполнитель в одной атакующей группе. Здесь пользователь может формировать или задерживать различия вокруг MsgFinishInference. Основным остаточным риском является репутация/экономика: группа может попытаться управлять результатами, чтобы исполнитель получил признание за выводы, которые никогда не получают честного подтверждения. Это не рассматривается как критическое нарушение безопасности или работоспособности того же класса, что и ошибки консенсуса; все же стоит ограничиться выборкой, необязательной полной проверкой, оплачиваемой пользователем, и четкими правилами расчета, но идеальная защита от злонамеренного секвенсора, вступающего в сговор с исполнителем, может выходить за рамки самых строгих гарантий.
Дополнительные риски (ортогональные приведенному выше разделению):
Основная проблема: посев R
Нам нужно значение R_inf (или входные данные VRF для каждого валидатора), такое, что:
Конкретный экземпляр приведен в разделе «Инструкции по проектированию» ниже (трехсторонние высоты + block_hash(validationSeedHeight) ).
Разработка протокола
Этот раздел представляет собой конкретный эскиз протокола. Он реализует вышеуказанные цели: прозрачная случайность из основной сети, отсутствие раунда раскрытия начальных чисел и участие третьих лиц, чтобы пользователь в одиночку не мог исправить маяк. Старые абстрактные параметры (только для VRF, только для корневого состояния) здесь не повторяются; они останутся альтернативами, если этот эскиз будет уточнен.
Согласование с текущей подсетью (сегодняшний код и поведение)
Первый сегмент потока соответствует subnet/user/user.go и subnet/host/host.go сегодня:
Итак: начало → выполнение → завершение в очереди соответствует текущей реализации. Новый материал ниже начинается после того, как MsgFinishInference принимается в состояние сеанса (включено в разницу).
Именование: в текущей базе кода нет MsgStartValidation; началом работы с пользователем является MsgStartInference . Ниже «FinishInference commit» — это предлагаемый шаг (MsgFinishInferenceCommit или эквивалент), а не существующий тип передачи.
Предлагаемый протокол (после текущего запуска/выполнения/окончания)
Шаг 1. То же, что и сегодня, через MsgFinishInference.
Без изменений: различия, управляемые пользователем, выполнение исполнителя, MsgFinishInference с ResponseHash, количество токенов, ProposerSig и т. д.
Шаг 2 — MsgFinishInferenceCommit на следующем хосте (пользователь → хост B)
Шаг 3. Хост B включает хост C (высота пинга, детерминированная третья сторона)
После этого шага каждая из трех сторон хранит проверяемое представление «последней высоты» на момент фиксации: пользователь (A), B, C.
Шаг 4 — Детерминированное FinishInferenceHeight
Все участники подсчитывают:
FinishInferenceHeight = max (высота_A, высота_B, высота_C)
используя только подписанные, проверяемые поля высоты из пакета фиксации (доказательства стиля раздела 1 каждой стороны, как в HEIGHT_SYNC_PROTOCOL_PROPOSAL.md (./HEIGHT_SYNC_PROTOCOL_PROPOSAL.md)). Это значение является детерминированным для одного и того же пакета.
Шаг 5 — валидацияSeedHeight и неизвестный хеш блока
Даже при наличии трех сторон уже могут существовать более свежие блоки основной сети, чем FinishInferenceHeight . Чтобы уменьшить вероятность того, что какая-либо сторона заранее выбрала маяк, определите:
validationSeedHeight = FinishInferenceHeight + VALIDATION_TRIGGER_OFFSET
где VALIDATION_TRIGGER_OFFSET — небольшая константа политики (например, 2 или 3 блока основной сети). Семантика: проверочная выборка для этого вывода привязана к высоте основной сети validationSeedHeight — то есть блоку на этой высоте, чей хэш никому не известен до тех пор, пока этот блок не будет завершен (согласно предположениям цепочки).
Пусть block_hash(H) будет хешем канонического идентификатора блока на высоте H. Определите, например:
R_inf = H(escrow_id || inference_id || block_hash(validationSeedHeight) || …)
и получить подходящих валидаторов из R_inf с помощью общедоступной формулы (например, взвешенной по репутации/долям, как того требует политика). Все согласны с тем, кто должен проверять, как только становится доступен блок_hash(validationSeedHeight).
Шаг 6 — Уведомление выбранного валидатора; проверка цепочки nonce пользователя
Шаг 7 — Финализация без ожидания пользователя
Если пользователь перестает отправлять сообщения, но начинается финализация, валидаторы (и другие хосты) публикуют все имеющиеся у них доказательства и частичные результаты, чтобы остальная часть группы могла проверить запланированные проверки. Проверки завершения должны включать в себя: все проверки, запланированные в соответствии с этим протоколом для готовых выводов, имеют соответствующие результаты (или явный тайм-аут / косую черту для каждой политики). Это соответствует TODO в FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) для незавершенных выводов и проверок.
Расширения (тот же путь) — «проверка каждого вывода»/дополнительная циклическая проверка.
Для рабочих нагрузок, требующих проверки каждого вывода (оплаченного пользователем или политики), не добавляйте второй случайный путь. Используйте то же правило сеанса, что и при обычной маршрутизации: заранее укажите nonce и отправьте следующий diff следующему хосту в циклическом переборе (hostIdx = nonce % len(group)).
Ограничение: валидатор этого дополнительного шага не должен быть исполнителем этого вывода. Исполнитель фиксируется inference_id % len(group) (индекс слота/хоста). При увеличении nonce, если индекс следующего хоста будет равен индексу исполнителя, пропустите его один раз (снова увеличьте), чтобы проверка всегда выполнялась на другом хосте.
Несколько слотов под одним адресом: если один оператор владеет несколькими слотами, правило по-прежнему основано на индексе хоста (или индексе первичного слота): ни один раунд проверки не может быть нацелен на тот же индекс исполнителя, что и вывод, даже если другой слот с тем же адресом получит сообщение - реализация последовательно отображает слот → индекс циклического перебора хоста, поэтому исполнитель не может проверить свое собственное выполнение через одноуровневый слот.
Угрозы и векторы атак (обзор этого эскиза)
Связь с протоколом сборщика финализации
FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md (./FINALIZATION_COLLECTOR_PROTOCOL_PROPOSAL.md) адресует расчет (голосование/фиксация, сборщики). Право на валидацию и R_inf из направлений проектирования ортогональны: завершение не должно зависеть от воспроизведения семантики MsgRevealSeed. Завершение по-прежнему должно согласовывать запланированные проверки (см. «Инструкции по проектированию — шаг 7» и TODO в этом документе по незавершенной работе).
Рекомендуемые следующие шаги
Открытые вопросы
Статус
Проект предложения — на рассмотрение перед реализацией.