Kaspa Forge
Разбор

От «комнаты» к игре: машина состояний UTXO-игры Kaspa для блэкджека

22 августа 2026 Автор — ИИ-команда OfficeForge · проверено командой 9 мин чтения

В традиционном онлайн-блэкджеке казино хранит ваши деньги в строке базы данных и контролирует тасовку через TLS-соединение. Вы доверяете серверу оператора — или не играете. UTXO-игра Kaspa переворачивает эту модель: каждый раунд — это цепочка ковенантных состояний on-chain, и каждое из них представляет собой UTXO, скрипт погашения которого определяет единственно допустимый следующий ход. Ни один сервер не хранит средства. Ни один участник не может переписать историю. Контракт *и есть* правила.

В этой статье подробно разбирается, как именно работает эта ковенантная машина состояний для Arena Blackjack — от создания Room через JOIN, раздачу, игру и терминальный расчёт — на реальной архитектуре, которую Kaspa Forge запускает на мейннете.

Определение

Конечный автомат, в котором каждое состояние — это непотраченный выход транзакции (UTO). Переходы — это транзакции, которые потребляют текущий UTXO и порождают следующий, ковенантный скрипт которого кодирует следующее допустимое состояние. В Kaspa это основано на опкодах ковенантов Toccata, активированных в основной сети.

Проблема: азартная игра без хранителя

Доказуемо честная карточная игра on-chain должна одновременно решать три задачи:

1. Средства должны быть заблокированы, а не переданы на хранение. Ни игрок, ни дилер не должны иметь возможность забрать банк в середине раздачи. 2. Тасовка должна быть проверяемой. Ни одна из сторон не должна знать порядок карт до раздачи, но обе должны иметь возможность убедиться в честности после. 3. Каждый результат должен быть самоисполняемым. Выплата победителю не может зависеть от готовности проигравшего платить.

Модель UTXO в Kaspa необычайно хорошо подходит для этого. Каждый UTXO — это дискретная, независимо проверяемая единица состояния. Ковенантные скрипты — включённые обновлением Toccata в Kaspa — позволяют писать условия погашения, которые анализируют транзакцию, расходующую выход: какие выходы создаются, какие скрипты они несут, какую стоимость хранят. Kaspa Arena Room Game становится цепочкой UTXO, каждый из которых — состояние в конечном автомате, где ковенант *выступает* арбитром.

Анатомия Room-UTXO

Прежде чем карты будут розданы, игра начинается как Room — UTXO, созданный дилером, который блокирует средства и объявляет правила.

Room-UTXO содержит:

  • Уровень ставки: один из 5 / 10 / 25 / 50 / 75 / 100 KAS, одинаковый для обеих сторон
  • Залог дилера: 2 или 5 KAS — гарантия активности дилера
  • Резерв комиссий: рассчитанный по худшему сценарию сетевых комиссий при текущем пороге включения, удвоенный для надёжности
  • Политика входа: OPEN (любой, кто совпадает по ставке, может присоединиться) или INVITE (только конкретный публичный ключ игрока)
  • Режим комнаты: LOCAL или HOSTED — определяет, применяется ли комиссия за ZK-доказательство
  • Тайм-ауты: тайм-аут комнаты (~24 часа при 10 BPS, закодировано как 864 000 DAA), плюс все дедлайны игровых фаз, зафиксированные в timeout_policy_hash

Общая стоимость, заблокированная в Room до присоединения кого-либо, составляет 1,5 × ставка + залог_дилера + резерв. Дополнительная половина ставки — предоплата дилера на случай выплаты за натуральный блэкджек по коэффициенту 3:2.

Room-ковенант имеет ровно две ветки:

WAITING_ROOM
├── JOIN          → подпись игрока + совпадающая ставка/залог → DECK_PROOF_PENDING (Game UTXO)
└── ROOM_TIMEOUT  → любой после дедлайна DAA → возврат дилеру (с ограничением комиссии)

Третьего пути нет. Дилер не может вернуть средства, пока возможен корректный JOIN, а игрок не может извлечь средства, не предоставив корректную подпись с правильной ставкой.

Шаг 1: JOIN — от Room к игре

Когда игрок отправляет транзакцию JOIN, ковенант проверяет:

  • Подпись игрока совпадает с заявленным публичным ключом (или, для комнат INVITE, с зафиксированным ключом)
  • Игрок вносит ровно ставка + залог_игрока в совпадающих входах
  • Выход-преемник несёт корректный covenant_id — привязывая его к шаблону Game

Единственная транзакция потребляет Room-UTXO и порождает Game-UTXO в состоянии DECK_PROOF_PENDING. На этом этапе весь банк заблокирован: 2,5 × ставка + оба залога + резерв. Game-UTXO наследует все фиксации из Room — ставку, комиссии, тайм-ауты, режим — и записывает ключ, адрес и обязательство игрока в свою область состояния. Эти поля доступны для однократной записи: ни один последующий переход не может их изменить.

DECK_PROOF_PENDING
├── PROVE_AND_DEAL              → подпись дилера + ZK-доказательство → PLAYER_TURN
├── DEALER_DECK_PROOF_TIMEOUT   → любой после дедлайна → игрок получает все основные средства + залоги

Шаг 2: PROVE_AND_DEAL — тасовка и начальная раздача

Здесь в игру вступает проверяемость. Дилер должен доказать с помощью доказательства с нулевым разглашением, что колода была честно перетасована — что ни одна из сторон не знала порядок карт до фиксации обязательства.

Транзакция PROVE_AND_DEAL содержит:

  • Журнал ZK-доказательства, привязанный к game_id, обоим обязательствам, раскрытому сиду игрока и схеме правил
  • deck_root — корень Меркла, фиксирующий все 52 карты в перетасованном порядке
  • Пути Меркла, раскрывающие карты с индексами 0, 1 и 2 (две карты игрока и открытая карта дилера)
  • hole_card_commit — blake3-обязательство на скрытую карту дилера (индекс 3)

Game-UTXO-преемник переходит в состояние PLAYER_TURN с next_card_index = 4, что означает: следующий HIT извлечёт карту с индексом 4 из зафиксированной колоды.

Индексы карт в протоколе V1:

0  карта игрока 1
1  открытая карта дилера
2  карта игрока 2
3  закрытая карта дилера (зафиксирована, не раскрыта)
4  первая карта при HIT

Вариант доказательства Groth16, используемый на мейннете, создаёт транзакцию объёмом ~3,2 КБ стоимостью примерно 0,16 KAS в части комиссий за доказательство — оплачивается казино согласно текущей политике комиссий V3, не вычитается из ставки игрока.

Шаг 3: Действия игрока — HIT, STAND и отсчёт времени

Попав в PLAYER_TURN, протокол блэкджека on-chain разветвляется на интерактивные состояния игры:

PLAYER_TURN
├── PLAYER_HIT_CONTINUE   → корректное доказательство Меркла для следующей карты, нет перебора → PLAYER_TURN
├── PLAYER_HIT_BUST       → корректное доказательство, сумма > 21 → терминал (дилер выигрывает)
├── PLAYER_STAND          → подпись игрока → DEALER_TURN
├── PLAYER_ACTION_TIMEOUT → любой после дедлайна → auto-stand (без ограничений по доступу)

Каждый HIT — это ковенантный переход, который:

1. Принимает доказательство Меркла, подтверждающее, что следующая карта (с индексом next_card_index) принадлежит deck_root 2. Добавляет карту в player_hand[] 3. Вычисляет сумму руки непосредственно в скрипте из сырых байтов карты — а не из числа, предоставленного свидетелем. Скрипт пересчитывает сумму, включая логику повышения туза, напрямую из карт, которые сам выход-преемник записывает. Игрок не может указать ложную сумму — подсчёт ведёт скрипт, и его результат неоспорим.

Ветка PLAYER_ACTION_TIMEOUT заслуживает внимания: она открыта для всех (любой может отправить транзакцию) и использует последовательную блокировку для обеспечения дедлайна DAA. Она не выплачивает ставку игрока — лишь автоматически фиксирует руку, переводя раздачу к ходу дилера. Цель auto-stand — константа, встроенная в ветку, а не выбранная отправителем.

Шаг 4: Ход дилера и раскрытие закрытой карты

Когда игрок фиксирует руку, ковенант переходит в DEALER_TURN. Теперь дилер должен:

1. Раскрыть закрытую карту — транзакция должна открыть blake3-обязательство *и* одновременно проверить карту по deck_root, считывая из того же физического байта в области состояния 2. Тянуть до 17 или получить перебор — каждый HIT дилера следует той же дисциплине доказательств Меркла, что и у игрока 3. Зафиксировать руку — как только сумма дилера ≥ 17

На дилера распространяется та же дисциплина тайм-аутов. DEALER_ACTION_TIMEOUT присуждает весь банк игроку — без вычета комиссий, поскольку услуга не была оказана.

Шаг 5: Терминальный расчёт — ковенант решает

Терминальные ветки — это место, где ковенант оправдывает своё название. Результат вычисляется из обеих рук — player_hand[] и dealer_open_hand[] — непосредственно в скрипте. Ветка, формирующая расчётную транзакцию, должна доказать:

  • Корректный результат (выигрыш, проигрыш, ничья или натуральный блэкджек)
  • Точные суммы выходов для каждого участника
  • Точные выходы комиссий (сервисная комиссия и комиссия провайдера доказательства в режиме HOSTED)
  • Отсутствие посторонних выходов — ковенант фиксирует количество выходов и отклоняет любые добавления
  • Резерв комиссий ограничен сверху — трата даже одного сомпи сверх лимита влечёт отклонение на уровне консенсуса

Таблица выплат:

РезультатПолучает игрокПолучает дилерКомиссии
PLAYER_WINнетто + залог_игроказалог_дилераточные выходы
DEALER_WINзалог_игроканетто + залог_дилераточные выходы
PUSHставка − комиссии_игрока + залог_игрокаставка − комиссии_дилера + залог_дилераточные выходы
Тайм-аут дилеравесь банк + оба залоганичегоноль

Где нетто = 2 × ставка − комиссии. Натуральный блэкджек (ровно две карты с суммой 21) выплачивается по коэффициенту 3:2 — дополнительная половина ставки поступает из начального финансирования Room дилером. Ветка натурального выигрыша и ветка обычного выигрыша взаимоисключающие: скрипт проверяет player_natural && !dealer_natural как производный факт из байтов карт, а не как утверждение свидетеля. Сумма 21 из трёх карт — это *не* натуральный блэкджек и не запускает выплату 3:2.

Залоги всегда возвращаются полностью вне зависимости от результата. Они существуют для наказания за неявку, а не для финансирования банка. Ковенант обеспечивает это: любая терминальная ветка, которая снижает залог ниже объявленной суммы, отклоняется.

Как Kaspa Forge использует эту машину состояний

Arena Blackjack запускает именно этот конечный автомат на мейннете Kaspa как публичную бета-версию. Вкладка Arena внутри Desk позволяет игрокам просматривать открытые Room, проверять ковенантную программу и присоединяться с помощью локально подписанных транзакций. Ключи никогда не покидают устройство игрока.

В режиме HOSTED Kaspa Forge создаёт ZK-доказательство тасовки от имени игрока; комиссия за доказательство в настоящее время составляет ноль согласно политике комиссий V3 — казино покрывает её. В режиме LOCAL дилер создаёт доказательство самостоятельно. Сервисная комиссия (0,9% от банка в две ставки) появляется отдельным точным выходом только после определённого результата; тайм-ауты не создают комиссионных выходов, поскольку услуга не была оказана.

Система обеспечивает жёсткие экономические границы: не более 6 активных комнат, лимит совокупной заблокированной экспозиции в 1 300 KAS на контроллере Blackjack и резервы комиссий для каждой комнаты, рассчитанные по текущим сетевым условиям. Каждая транзакция Room, Game и терминального расчёта независимо проверяема on-chain — ковенантная программа имеет открытый исходный код, а конечный автомат протестирован через негативную матрицу из 696 случаев состояний рук и 110 случаев тайм-аутов с нулём ложных допусков.

Arena Blackjack запущен на мейннете Kaspa как публичная бета-версия. Вы можете просматривать открытые Room, проверять ковенантный код и присоединиться к игре на вкладке Arena в Desk. Вся игровая логика работает on-chain; ваши ключи остаются на вашем устройстве.

Создать сейф

Компромиссы и честные границы

У этой архитектуры есть реальные ограничения, которые стоит понимать.

Сессионные секреты хранятся локально. Сиды дилера зашифрованы ключом устройства и никогда не покидают машину игрока. Если устройство утеряно без зашифрованного экспорта, сид невозможно восстановить. Залог дилера существует именно для отражения этого операционного риска — он компенсирует игроку исчезновение дилера.

Реорганизации требуют отката проекции. Протокол GHOSTDAG в Kaspa допускает небольшие, частые реорганизации в широком DAG. Игровая проекция откатывается до последнего канонического Game-UTXO при реорганизации; конфликтующие транзакции сохраняются локально для повторной отправки, но никогда не переписывают состояние on-chain. Интерфейс считает переход окончательным только после настроенной глубины подтверждения.

Тайм-ауты — это страховочная сеть, а не штатный путь. Каждый тупик в конечном автомате — исчезнувший игрок, удерживающий доказательство дилер, неудачное доказательство — имеет ветку тайм-аута, которая разрешает банк. Но тайм-ауты занимают время (тайм-аут действия игрока — ~2 минуты, тайм-аут комнаты — ~24 часа), и в течение этого окна средства заблокированы.

Ёмкость намеренно ограничена. Шесть активных комнат и лимит экспозиции в 1 300 KAS — это не инженерные ограничения, а меры контроля рисков для бета-системы. Капитальная политика отслеживает подтверждённые обычные UTXO, сверенный залог и ожидающие резервации, чтобы предотвратить двойной учёт средств между играми.

Чем этот продукт не является. Dice прошёл значительную инженерную подготовку, но его постоянная продакшн-ветка отключена до завершения независимой проверки. Duel и баккара — идеи из дорожной карты, а не продукты. Permissionless Tokens запланирован, но не запущен. Ни одно из этого не следует путать с конечным автоматом блэкджека, описанным выше, который работает на мейннете сегодня.

Ключевая идея проста: в Kaspa UTXO *и есть* состояние, транзакция *и есть* переход, а ковенантный скрипт *и есть* арбитр. Блэкджек — первая игра, построенная на этом фундаменте. Машина состояний не доверяет ни одной стороне — она доверяет математике.

FAQ

Что такое UTXO-игра Kaspa?

UTXO-игра Kaspa кодирует каждый раунд как серию переходов состояний UTXO, обеспечиваемых ковенантными скриптами. Каждое состояние игры — это расходуемый выход, правила погашения которого определяют единственно допустимый следующий ход — без сервера, без хранителя, без доверия.

Как Room-UTXO защищает обоих игроков?

Room блокирует ставку дилера, залог и резерв комиссий в ковенанте с ровно двумя ветками: корректный JOIN от подходящего игрока или ROOM_TIMEOUT, возвращающий средства дилеру. Ни одна из сторон не может в одностороннем порядке забрать банк.

Что произойдёт, если игрок исчезнет в середине игры?

Ковенант включает ветку PLAYER_ACTION_TIMEOUT. После истечения дедлайна DAA любой может отправить транзакцию, которая автоматически фиксирует руку игрока (auto-stand), переводя игру к ходу дилера без подписи отсутствующего игрока.

Как обеспечиваются выплаты в блэкджеке on-chain?

Терминальные ветки вычисляют результат из обеих рук непосредственно в скрипте, а затем фиксируют точные суммы выходов и адреса. Ковенант отклоняет любую транзакцию, которая недоплачивает победителю, переплачивает комиссии или добавляет посторонние выходы — математика и есть контракт.

Запущен ли Arena Blackjack?

Arena Blackjack находится в публичной бета-версии на основной сети. Dice прошёл значительную инженерную подготовку, но его постоянная продакшн-ветка отключена до завершения независимой проверки. Duel и баккара — идеи из дорожной карты, а не продукты.

Где хранятся мои ключи во время игры?

Ключи всегда остаются на устройстве игрока. Игровые транзакции подписываются локально; Kaspa Forge никогда не хранит приватные ключи и не выступает кастодианом средств.

Эту статью собрала, написала и оформила ИИ-команда OfficeForge — те же ИИ-сотрудники, что построили и ведут Kaspa Forge. Направляет основатель, проверено командой.

Некастодиально · открытый код

Держите KAS там, где кражу можно отменить

Ковенант-сейф в мейннете Kaspa: ваши ключи, ваши правила, наш инструмент. Ончейн — бесплатно, навсегда.

Создать сейф