Разработка игры Poker на блокчейне

Проектируем и разрабатываем блокчейн-решения полного цикла: от архитектуры смарт-контрактов до запуска DeFi-протоколов, NFT-маркетплейсов и криптобирж. Аудит безопасности, токеномика, интеграция с существующей инфраструктурой.
Показано 1 из 1 услугВсе 1306 услуг
Разработка игры Poker на блокчейне
Сложная
от 2 недель до 3 месяцев
Часто задаваемые вопросы
Направления блокчейн-разработки
Этапы блокчейн-разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1258
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1170
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    873
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1092
  • image_logo-advance_0.png
    Разработка логотипа компании B2B Advance
    563
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    830

Разработка игры Poker на блокчейне

Покер на блокчейне — задача, которая выглядит проще, чем есть на самом деле. Смарт-контракт гарантирует прозрачность и честные выплаты. Но карты нельзя показывать on-chain до вскрытия — это уничтожает игру. Значит нужно скрыть информацию в публичной среде, где всё видно всем. Это задача mental poker, формально описанная ещё в 1979 году Шамиром, Ривестом и Эдлманом. Практическая реализация требует выбора: полноценная криптография (сложно и дорого) или trusted off-chain компонент (проще, но требует доверия).

Фундаментальная проблема: скрытие информации on-chain

В традиционном покере дилер физически раздаёт карты лицом вниз. В публичном блокчейне все данные транзакций видны всем нодам. Если записать карты в state контракта — любой нод читает их напрямую. Если зашифровать — кто держит ключ?

Подход 1: Mental Poker с commit-reveal

Классический криптографический подход:

  1. Каждый игрок вносит случайный seed для shuffling (commit phase)
  2. Deck перемешивается детерминированно из комбинации всех seed
  3. Каждая карта шифруется ключом каждого игрока (layered encryption)
  4. Карта открывается только когда все игроки раскрыли свою часть ключа

Проблема: при 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.

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 блоков, он может начать dispute, предъявив последнее подписанное состояние. Counter-party должен ответить более новым состоянием. Если не отвечает — timeout player wins.

Forced reveal: в showdown все активные игроки обязаны раскрыть карты on-chain в течение timeout. Если не раскрыл — считается fold. Это защита от стратегии «отключиться при проигрышном showdown».

function initiateDispute(bytes32 channelId, GameState calldata lastKnownState, bytes calldata sig)
    external {
    Channel storage ch = channels[channelId];
    require(ch.players[_getPlayerId(channelId, msg.sender)] == msg.sender, "Not player");

    disputes[channelId] = Dispute({
        challenger: msg.sender,
        challengeState: lastKnownState,
        challengeTime: block.timestamp,
        resolved: false
    });

    ch.status = ChannelStatus.DISPUTED;
    emit DisputeInitiated(channelId, msg.sender, lastKnownState.nonce);
}

Fairness: верифицируемое тасование

Игровой сервер тасует колоду. Как доказать, что не жульничает, зная карты игроков?

Commit-Reveal shuffling:

  1. До начала раздачи сервер публикует хэш seed: commitment = hash(seed + salt)
  2. Игроки вносят свои entropy contributions
  3. Final deck = shuffle(seed XOR player_entropy_1 XOR ... XOR player_entropy_N)
  4. После игры сервер раскрывает 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 покупается за токены).

Стек

Компонент Технология
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

Процесс разработки

Архитектурное решение (1 неделя). Выбор подхода к скрытию карт: off-chain trusted server, TEE, или ZK. Это определяет всё.

Smart contracts (3-4 недели). State channel контракт, dispute mechanism, NFT контракты, settlement логика.

Game server (3-5 недель). Покерная логика, state management, WebSocket мультиплеер, commit-reveal shuffling, anti-cheat.

Frontend (4-6 недель). 3D или 2D стол, анимации раздачи, betting UI, real-time ходы других игроков, wallet интеграция.

Безопасность и аудит. Аудит state channel контракта и dispute mechanism — критично. Экономическое тестирование rake модели.

MVP с off-chain сервером и базовым state channel — 3-4 месяца. Production с ZK или TEE, полным NFT ecosystem, lobby системой — 6-9 месяцев.