Иммерсивный покер на блокчейне: 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 месяцев — обсудим архитектуру и сроки. Свяжитесь для консультации: мы бесплатно оценим ваш проект.







