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

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1306 послуг
Розробка гри Poker на блокчейні
Складний
від 2 тижнів до 3 місяців
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1288
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1198
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    902
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1122
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    589
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    859

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

Покер на блокчейні — задача, яка виглядає простіше, ніж вона насправді є. Смарт-контракт гарантує прозорість і справедливі виплати. Але карти не можна розкривати on-chain до showdown — це руйнує гру. Отже, потрібно приховати інформацію в публічному середовищі, де все видно всім. Це задача mental poker, формально описана в 1979 році Шаміром, Рівестом та Адльманом. Практична реалізація вимагає вибору: повна криптографія (складна та дорога) або надійний офлайн-компонент (простіший, але вимагає довіри).

Фундаментальна проблема: приховання інформації On-Chain

У традиційному покері дилер фізично роздає карти лицем вниз. На публічному блокчейні всі дані транзакцій видимі всім вузлам. Якщо записати карти у стані контракту — будь-який вузол читає їх напряму. Якщо зашифрувати — хто тримає ключ?

Підхід 1: Mental Poker з Commit-Reveal

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

  1. Кожен гравець внесає випадковий seed для перетасування (commit фаза)
  2. Колода перетасована детерміновано з комбінації всіх seeds
  3. Кожна карта зашифрована ключем кожного гравця (шарувате шифрування)
  4. Карта розкривається тільки коли всі гравці розкривають свою частину ключа

Проблема: при 6 гравцях кожна карта зашифрована 6 разів. Розкриття вимагає 6 on-chain транзакцій. При 5 вулицях покеру — десятки транзакцій на руку. Газ та затримка неприйнятні для mainnet.

Підхід 2: ZK Proof для приховання карт

ZK-SNARK дозволяє довести «гравець тримає карту потрібної цінності для виплати» без розкриття самої карти до showdown. Проекти типу ZK-Holdem (на базі Circom) пробують цей шлях.

Складність: ZK схеми для правил покеру (повна оцінка руки) — нетривіальна задача. Генерація proof на мобільному — повільна (секунди). На десктопі — прийнятна.

Підхід 3: Trusted Execution Environment (TEE)

Дилерський сервіс запускається в Intel SGX або AWS Nitro Enclave — ізольованому середовищі, де навіть оператор сервера не бачить дані. Карти роздаються усередині TEE, гравці бачать тільки свої карти через зашифрований канал. На блокчейн йдуть тільки результати раундів та зобов'язання (commitments).

Компроміс: довіра до виробника TEE (Intel). Для більшості ігрових додатків це прийнятно — не гірше ніж довіра казино дилеру.

Підхід 4: Офлайн-сервер гри + On-Chain Settlement

Найпрактичніший варіант для production: сервер гри ведеться стан гри офлайн, гравці підписують ходи (bet, fold, raise) через state channel, остаточний результат записується on-chain для виплати.

Гравці → [Game Server] → керує приховиння карт, стан гри
   ↕ підписані ходи (state channel)
   ↓ остаточний результат + підписи
[Settlement Contract] → виплачує переможців

Архітектура State Channel

State channel — ідеальна модель для покеру. Гравці відкривають channel, вносять депозит, всі ходи — це підписані офлайн-повідомлення. 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) {
        // Перевіряємо всі депозити
        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");

        // Верифікуємо підписи всіх гравців на остаточний стан
        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;
    }
}

Механізм розирішення спорів

Що якщо сервер гри зник або намагається мошенничати? State channel повинен мати розв'язання спорів:

На основі timeout: якщо гравець не отримав відповідь протягом N блоків, він може ініціювати спір, представивши останній підписаний стан. Contador-party повинен відповісти новішим станом. Якщо не відповідає — гравець з timeout виграє.

Примусове розкриття: на 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);
}

Справедливість: Верифіковане перетасування

Сервер гри перетасовує колоду. Як довести, що не жульничає, знаючи карти гравців?

Commit-Reveal Перетасування:

  1. До початку роздачі сервер публікує хеш seed: commitment = hash(seed + salt)
  2. Гравці вносять свої внески entropy
  3. Остаточна колода = shuffle(seed XOR player_entropy_1 XOR ... XOR player_entropy_N)
  4. Після гри сервер розкриває seed — всі можуть верифікувати перетасування
// Сторона сервера
const serverSeed = crypto.randomBytes(32)
const commitment = keccak256(concat([serverSeed, salt]))
await contract.publishCommitment(channelId, commitment)

// Після отримання всіх entropy гравців:
const finalSeed = xorAll([serverSeed, ...playerEntropyContributions])
const deck = shuffleDeck(standardDeck, finalSeed) // детерміністичний Fisher-Yates

// Після гри:
await contract.revealSeed(channelId, serverSeed, salt)
// Будь-хто може перевірити: hash(serverSeed + salt) == commitment
// І: shuffle(standardDeck, serverSeed XOR playerEntropy) == used deck

Логіка гри Офлайн

Логіка покеру (Texas Hold'em оцінка рук, раунди ставок, управління поттом) — повністю офлайн на сервері. Контракт займається тільки: депозит, state commitments, спір, виплата.

// Оцінювач рук
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', та ін.
        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 та ігрові активи

Аватари гравців / профіль NFT. Косметичні NFT не впливають на гейплей, але дають ідентичність та вторинний ринок. ERC-721 з динамічними метаданими (win rate, games played) через tokenURI з on-chain або офлайн-даними.

Покерний стіл NFT. Приватний стіл як NFT: власник NFT керує налаштуванням стола (rake %, структура blinds, invite-only), отримує частину rake. Пасивний дохід для власників NFT.

Набори чипів та скорички карт. Чисто косметичні, але значущі для утримання. ERC-1155 для fungible косметики.

Економіка токенів та rake

Rake — комісія з кожного pot, як казино. 2-5% від pot — стандарт. В on-chain покері rake йде в скарбницю протоколу. Розподіл:

Pot rake (3%) → 50% burn / buyback game token
              → 30% staking rewards (stakers = liquidity providers)
              → 20% development fund

Rakeback NFT. Гравці з певним NFT отримують частинку rake повернення. Стимул для утримання NFT, sink для токену (NFT купується за токени).

Стек

Компонент Технологія
Smart contracts Solidity + Foundry
State channels Nitro Protocol / custom
Game server Node.js + TypeScript
Real-time WebSocket (Socket.io)
Фронтенд React + Three.js / Pixi.js для стола
Гаманець wagmi + WalletConnect v2
ZK (якщо вибрано) Circom + snarkjs
TEE (якщо вибрано) AWS Nitro Enclaves

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

Архітектурне рішення (1 тиждень). Вибір підходу до приховання карт: офлайн надійний сервер, TEE, або ZK. Це визначає все.

Smart contracts (3-4 тижні). State channel контракт, механізм спорів, NFT контракти, логіка settlement.

Game server (3-5 тижнів). Логіка покеру, управління станом, WebSocket мультиплеєр, commit-reveal перетасування, anti-cheat.

Фронтенд (4-6 тижнів). 3D або 2D стіл, анімації роздачі, UI ставок, реалтайм ходи інших гравців, інтеграція гаманця.

Безпека та аудит. Аудит state channel контракту та механізму спорів — критично. Економічне тестування rake моделі.

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