Документация

Как работает ResultBond — подробно.

Для инженеров, которые будут встраивать квитанции, проверять их или проводить по ним расчёты.

Как устроена работа

  1. Манифест. Покупатель, исполнитель и ResultBond подписывают один манифест: снимок репозитория, публичные и скрытые наборы тестов, критерии приёмки, лимиты среды, цену и компенсацию. Его SHA-256 отпечаток — идентификатор работы.
  2. Скрытые тесты доказываются. До начала работы каждый скрытый тест должен падать на исходном коммите и не повторять публичный тест. Иначе работа не оценивается автоматически.
  3. Сдача. Исполнитель подписывает одну сдачу: отпечаток патча и снимок, который получается после патча. Оценивается ровно этот код.
  4. Песочница. Исходный код и кандидат запускаются в изолированной песочнице (без сети, с лимитами CPU, памяти, процессов и вывода) с публичными, скрытыми и, по желанию, собственными тестами репозитория как регрессионной проверкой. Кандидат прогоняется до трёх раз (по умолчанию три).
  5. Квитанция. Правила превращают подписанные доказательства в PASS, FAIL или INCONCLUSIVE, и проверяющий подписывает квитанцию. Каждый шаг — событие в журнале, связанном хэшами, с подписанными контрольными точками.
  6. Расчёт. В режиме с залогом квитанция закрывает эскроу-контракт. В теневом режиме деньги не двигаются — у вас просто остаются квитанции.

Квитанция

Квитанция — JSON-документ с четырьмя ключами: payload, payload_digest, signature и evaluator_public_key_b64url. Неизвестные ключи отклоняются.

Поле payloadЗначение
receipt_versionДля этого формата всегда rb.proof-receipt.v0.3.
job_id, partner_idРабота и партнёр, у которого она размещена.
manifest_digestПодписанные условия, к которым относится квитанция.
candidate_submission_digestПодписанная исполнителем сдача: какой именно код оценивался.
evidence_digestПодписанные доказательства из песочницы, на которых основано решение.
decision_digestРешение по правилам.
outcome, reason_codePASS, FAIL или INCONCLUSIVE и причина (см. ниже).
settlementcurrency (USDC), payment_action (RELEASE_PAYMENT или REFUND_PAYMENT), payment_atomic, stipend_atomic (6 знаков) и requires_manual_review.
evaluator_id, evaluator_key_idКто подписал. Id ключа есть и в подписи и должен совпадать.
event_sequence, previous_event_digestМесто квитанции в журнале работы: обрезанный или переписанный журнал будет заметен.
issued_at, policy_id, receipt_idКогда, по каким правилам и постоянный id.
previous_receipt_digestНеобязательно: квитанция, которую эта заменяет.

Отпечаток. payload_digest — это sha256: + hex SHA-256 от payload в каноническом JSON: ключи отсортированы, без лишних пробелов, UTF-8, только целые числа, время в UTC с Z.

Подпись. Ed25519 над байтами RESULTBOND-CANONICAL-SIGNATURE-V0.1\0 + proof-receipt + \0 + канонический payload. Поле purpose подписи должно быть proof-receipt.

Исходы и причины

ИсходКоды причинДеньги
PASSALL_CHECKS_PASSОплата исполнителю, его залог возвращается.
FAILHIDDEN_TEST_FAILURE · PUBLIC_TEST_FAILURE · REGRESSION_FAILURE · CANDIDATE_TEST_ERROR · BOUND_TEST_SKIPPED · CANDIDATE_RUNTIME_FAILURE · TEST_HARNESS_TAMPERINGОплата возвращается покупателю, плюс компенсация из залога исполнителя.
INCONCLUSIVEBASELINE_NOT_REPRODUCIBLE · CANDIDATE_NOT_REPRODUCIBLE · INFRASTRUCTURE_ERROR · HIDDEN_INDEPENDENCE_NOT_PROVEN · EVIDENCE_BINDING_MISMATCH · EVIDENCE_INCONSISTENT · POLICY_VIOLATIONЖдёт человека. Независимый ревьюер подписывает: заплатить, вернуть или «никто не виноват» (оба депозита возвращаются).

FAIL ставится, только если упали все прогоны кандидата. Нарушение лимитов в любом прогоне — FAIL. Хороший фикс никогда не получает FAIL из-за теста, который не удалось подтвердить: в таком случае исход INCONCLUSIVE.

Проверка квитанции

В браузере

Вставьте или перетащите квитанцию на /verify. Проверка идёт локально через WebCrypto, ничего не отправляется. Кнопка «Скопировать ссылку» кладёт саму квитанцию во фрагмент ссылки после #, который браузеры никогда не отправляют на сервер.

JavaScript (браузер или Node 20+)

import { verifyReceiptText } from "https://resultbond.com/js/receipt.mjs";

const result = await verifyReceiptText(receiptJson, {
  trustedKeys: { "rb:evaluator:2026-10": "k3qnbpbsfVPtAtfgsbMs_H18mKRKJzRSrHUSWnBXDpQ" },
});
// { valid, trusted, outcome, payloadDigest, reasons }
if (!result.valid || !result.trusted) throw new Error(result.reasons.join("; "));

Чтобы доверять ключам, которые ResultBond публикует сейчас, загрузите их функцией trustedKeysFromKeySet из того же модуля (см. Ключи и доверие).

Python

resultbond verify-receipt receipt.json --online --text   # набор ключей с resultbond.com
resultbond verify-receipt receipt.json --keyset resultbond-keys.json   # без сети, сохранённый набор

Root-ключ встроен в CLI, поэтому набор ключей проверяется без дополнительных аргументов. Коды выхода: 0 — действительна и подписана доверенным ключом, 1 — недействительна или изменена, 3 — цела, но подписана ключом, которому вы не доверяете, 2 — ошибка настройки. Можно передать сразу несколько квитанций.

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

Ключи и доверие

Тот, кто проверяет квитанции, закрепляет один ключ — офлайн-ключ root ResultBond. Он подписывает набор рабочих ключей (проверяющего, песочницы, аудитора тестов), опубликованный на /.well-known/resultbond-keys.json.

Id ключа rootrb:root:2026-10
Публичный ключ rootk4kS-tpmIN5OQFjdt8Q8AJiaPC_iOa6jfhU5IIz3AUE
Id ключа проверяющегоrb:evaluator:2026-10
  • Срок действия. У каждого набора ключей есть срок действия (у текущего — до 5 октября 2027 года), его переподписывают заранее. Истёкший набор отклоняется.
  • Серийный номер. У каждого набора есть номер; запоминайте самый новый и отклоняйте более старые.
  • Ротация. Добавляется новый ключ, старый остаётся в списке, чтобы его квитанции можно было проверить.
  • Отзыв. У скомпрометированного ключа появляется время отзыва. С этого момента всё, что он подписал, отклоняется — какую бы дату ни указывала квитанция.

Эскроу-контракт

ResultBondEscrow (Solidity 0.8.28), по образцу ERC-8183. Один проверяющий, назначенный при создании работы, решает её один раз. Деньги только начисляются; каждая сторона выводит свои сама.

create(manifestDigest, provider, evaluator, payment, stipend, bondBy, decideBy) → jobId   // клиент
cancel(jobId)                         // клиент, до залога
bond(jobId)                           // исполнитель, до bondBy
complete(jobId, receiptDigest)        // проверяющий: PASS
reject(jobId, receiptDigest)          // проверяющий: FAIL
hold(jobId, receiptDigest)            // проверяющий: INCONCLUSIVE
voidHeld(jobId, reviewDigest)         // проверяющий, после ревью «никто не виноват»
expire(jobId)                         // кто угодно, после срока
withdraw()                            // любой, у кого есть баланс

Id работы = keccak256(manifestDigest, client, provider, evaluator, payment, stipend, bondBy, decideBy, chainid, escrow). Он фиксирует все условия, поэтому квитанция может закрыть только ту работу, для которой выдана. Те же значения записаны в привязке escrow подписанного манифеста, и адаптер расчётов сверяет их все до отправки транзакции.

Срок прошёлКто что получает
Нет залога к bondByКлиент: свою оплату.
Нет решения к decideByКлиент: оплату + компенсацию.
Работа заморожена, нет ревью 30 дней после decideByКаждая сторона: свой депозит.

Тестнет Monad (сеть 10143)

Только тестнет и тестовые токены. Перед реальными деньгами контракт пройдёт внешний аудит. Работы, закрытые на нём →

Как проходит пилот

От вас

  • Доступ на чтение к одному Python-репозиторию.
  • 30–50 реальных багов, исправленных или открытых.
  • Агент, которого вы хотите оценить.
  • Инженер примерно на два часа в неделю: просмотреть скрытые тесты и разметить часть вердиктов.

От нас

  • Скрытые тесты «чёрного ящика», доказанно падающие на старом коде.
  • Подписанная квитанция на каждую работу.
  • Отчёт о совпадении с вашими ревьюерами.
  • Итоговое решение: включать ли режим с залогом.