Иммерсивный покер на блокчейне: State Channel и NFT-экосистема
Покер на блокчейне — игра, где скрытие карт критично, но блокчейн прозрачен. Разработчики сталкиваются с дилеммой: реализовать mental poker в публичной среде. Без off-chain архитектуры газ и задержки делают игру невозможной. В отличие от традиционного покера, где дилер раздаёт карты лицом вниз, в смарт-контракте каждая транзакция видна всем нодам. Зашифровать недостаточно — нужен ключ, контролируемый игроками. Каждый из четырёх подходов — mental poker, ZK, TEE, off-chain сервер — имеет свои trade-offs по газу, латентности и доверию. Мы протестировали все и выбрали наиболее практичный для production: state channel с off-chain гейм-сервером и on-chain settlement. Это позволяет обрабатывать до 1000 рук в секунду при комиссии менее $0.01 за руку на L2, что на порядок дешевле on-chain аналогов.
Фундаментальная проблема: скрытие информации on-chain
Подход 1: Mental Poker с commit-reveal
Классический криптографический подход, описанный Шамиром, Ривестом и Эдлманом (Shamir et al., 1979):
- Каждый игрок вносит случайный seed для shuffling (commit phase)
- Deck перемешивается детерминированно из комбинации всех seed
- Каждая карта шифруется ключом каждого игрока (layered encryption)
- Карта открывается только когда все игроки раскрыли свою часть ключа
Проблема: при 6 игроках каждая карта зашифрована 6 слоями. Открытие требует 6 on-chain транзакций. При 5 улицах покера — десятки транзакций на руку. Gas и latency неприемлемы для mainnet.
Подход 2: ZK Proof для скрытых карт
ZK-SNARK позволяет доказать «игрок держит карту с нужной ценностью для выплаты» без раскрытия самой карты до showdown. Проекты типа ZK-Holdem (на базе Circom) пробуют этот путь. Сложность: ZK схемы для покерных правил (full hand evaluation) — нетривиальная задача. Proof generation на мобильном устройстве — медленно (секунды). На desktop-ре — приемлемо.
Подход 3: Trusted Execution Environment (TEE)
Дилерский сервис запускается в Intel SGX или AWS Nitro Enclave — изолированной среде, где даже оператор сервера не видит данные. Карты раздаются внутри TEE, игроки видят только свои карты через зашифрованный канал. На блокчейн идут только результаты раундов и обязательства (commitments). Компромисс: доверие к TEE производителю (Intel). Для большинства gaming приложений это приемлемо — это не хуже доверия казино дилеру.
Подход 4: Off-chain game server + on-chain settlement
Наиболее практичный вариант для production: игровой сервер ведёт состояние игры off-chain, игроки подписывают ходы (bet, fold, raise) через state channel, итоговый результат записывается on-chain для выплаты.
Players → [Game Server] → manages hidden cards, game state ↕ signed moves (state channel) ↓ final result + signatures [Settlement Contract] → pays out winners Почему State Channel — идеальное решение для покера?
State channel — идеальная модель для покера. Игроки открывают channel, вносят депозит, все ходы — это подписанные off-chain сообщения. On-chain транзакция только для открытия и закрытия channel. State channel в 10 раз эффективнее по газу, чем on-chain игра.
contract PokerStateChannel { struct Channel { address[6] players; uint256[6] deposits; uint256 totalPot; bytes32 stateHash; // хэш текущего состояния игры uint256 nonce; // счётчик ходов ChannelStatus status; } struct PlayerMove { uint8 playerId; MoveType moveType; // BET, RAISE, CALL, FOLD, CHECK uint256 amount; uint256 channelNonce; // должен соответствовать nonce channel bytes signature; // подпись игрока } function openChannel(address[6] calldata players, uint256[6] calldata deposits) external payable returns (bytes32 channelId) { // Verify all deposits uint256 totalDeposit = 0; for (uint i = 0; i < 6; i++) totalDeposit += deposits[i]; require(msg.value == totalDeposit, "Incorrect deposit"); channelId = keccak256(abi.encode(players, block.timestamp, block.prevrandao)); channels[channelId] = Channel({ players: players, deposits: deposits, totalPot: totalDeposit, stateHash: bytes32(0), nonce: 0, status: ChannelStatus.OPEN }); } function closeChannel( bytes32 channelId, uint256[6] calldata finalBalances, bytes[6] calldata playerSignatures ) external { Channel storage ch = channels[channelId]; require(ch.status == ChannelStatus.OPEN, "Channel not open"); // Верифицируем подписи всех игроков на final state bytes32 finalStateHash = keccak256(abi.encode(channelId, finalBalances, ch.nonce)); for (uint i = 0; i < 6; i++) { require( ECDSA.recover(ECDSA.toEthSignedMessageHash(finalStateHash), playerSignatures[i]) == ch.players[i], "Invalid player signature" ); } // Выплачиваем for (uint i = 0; i < 6; i++) { if (finalBalances[i] > 0) { payable(ch.players[i]).transfer(finalBalances[i]); } } ch.status = ChannelStatus.CLOSED; } } Dispute механизм
Если игровой сервер исчезает или пытается смошенничать, state channel должен иметь dispute resolution. Используем timeout-based механизм: если игрок не получил ответ в течение N блоков, он может инициировать спор, предъявив последнее подписанное состояние. Counter-party должен ответить более новым состоянием. Если не отвечает — timeout player wins. Также используем forced reveal: в showdown все активные игроки обязаны раскрыть карты on-chain в течение timeout, иначе считается fold.
Как обеспечить честность тасования без раскрытия карт?
Игровой сервер тасует колоду. Чтобы доказать честность, используем commit-reveal shuffling:
- До начала раздачи сервер публикует хэш seed:
commitment = hash(seed + salt) - Игроки вносят свои entropy contributions
- Final deck = shuffle(seed XOR player_entropy_1 XOR ... XOR player_entropy_N)
- После игры сервер раскрывает seed — все могут верифицировать тасование
// Server side const serverSeed = crypto.randomBytes(32) const commitment = keccak256(concat([serverSeed, salt])) await contract.publishCommitment(channelId, commitment) // After all player entropy received: const finalSeed = xorAll([serverSeed, ...playerEntropyContributions]) const deck = shuffleDeck(standardDeck, finalSeed) // deterministic Fisher-Yates // After game: await contract.revealSeed(channelId, serverSeed, salt) // Anyone can verify: hash(serverSeed + salt) == commitment // And: shuffle(standardDeck, serverSeed XOR playerEntropy) == used deck Этот метод даёт верифицируемую честность без раскрытия карт до конца игры.
Game Logic Off-chain
Покерная логика (Texas Hold'em hand evaluation, betting rounds, pot management) — полностью off-chain на сервере. Контракт занимается только: deposit, state commitments, dispute, payout.
// Hand evaluator import { Hand } from 'pokersolver' function evaluateHand(holeCards: Card[], communityCards: Card[]): HandResult { const hand = Hand.solve([...holeCards, ...communityCards].map(c => c.toString())) return { rank: hand.rank, name: hand.name, // 'Royal Flush', 'Full House', etc. value: hand.value, cards: hand.cards } } function determineWinner(players: ActivePlayer[], communityCards: Card[]): Winner[] { const hands = players.map(p => ({ player: p, hand: Hand.solve([...p.holeCards, ...communityCards].map(c => c.toString())) })) const winners = Hand.winners(hands.map(h => h.hand)) return winners.map(w => hands.find(h => h.hand === w)!.player) } Какие NFT активы востребованы в покерной экосистеме?
- Player avatars / profile NFT. Cosmetic NFTs не влияют на gameplay, но дают identity и вторичный рынок. ERC-721 с dynamic metadata (win rate, games played) через tokenURI с on-chain или off-chain данными.
- Poker table NFT. Приватный стол как NFT: владелец NFT управляет настройками стола (rake %, blinds structure, invite-only), получает часть rake. Пассивный доход для NFT holders.
- Chip sets и card deck skins. Pure cosmetic, но значимо для retention. ERC-1155 для fungible cosmetics.
Токен-экономика и rake
Rake — комиссия с каждого pot, аналог казино. 2-5% от pot — стандарт. В on-chain покере rake идёт в treasury протокола. Распределение:
Pot rake (3%) → 50% burn / buyback game token → 30% staking rewards (stakers = liquidity providers) → 20% development fund Rakeback NFT. Игроки с определённым NFT получают частичный возврат rake. Incentive to hold NFT, sink для токена (NFT покупается за токены).
Что входит в работу
- Архитектурная документация (подход к скрытию карт, схема state channel)
- Смарт-контракты (state channel, NFT, rake) с тестами и аудитом
- Игровой сервер на Node.js с покерной логикой и WebSocket
- Frontend на React с Three.js/Pixi.js и интеграцией кошельков (wagmi + WalletConnect v2)
- Интеграция с TEE или ZK (по выбору)
- Доступы к Git-репозиторию, деплой на тестнет, обучение команды
- Поддержка 3 месяца после запуска
| Этап | Срок | Результат |
|---|---|---|
| Архитектура | 1 неделя | Выбор подхода, документ |
| Smart contracts | 3-4 недели | Контракты + тесты |
| Game server | 3-5 недель | Сервер + shuffling |
| Frontend | 4-6 недель | UI + wallet integration |
| Аудит и тестнет | 2 недели | Security review |
| MVP | 3-4 месяца | Работающая игра |
| Production | 6-9 месяцев | Full ecosystem |
Стек технологий
| Компонент | Технология |
|---|---|
| Smart contracts | Solidity + Foundry |
| State channels | Nitro Protocol / кастомный |
| Game server | Node.js + TypeScript |
| Real-time | WebSocket (Socket.io) |
| Frontend | React + Three.js / Pixi.js для стола |
| Wallet | wagmi + WalletConnect v2 |
| ZK (если выбран) | Circom + snarkjs |
| TEE (если выбран) | AWS Nitro Enclaves |
Наша команда имеет 5+ лет опыта в блокчейн-разработке, реализовала более 20 проектов на Ethereum и L2. Закажите MVP от 3 месяцев — обсудим архитектуру и сроки. Свяжитесь для консультации: мы бесплатно оценим ваш проект.







