Onchain Texas Hold'em poker on Stellar with cryptographically private cards using ZK-MPC (coSNARKs).
No single party ever sees the full deck. A 3-node MPC committee (TACEO coNoir) shuffles and deals cards using REP3 secret sharing. UltraHonk ZK proofs verify every deal, reveal, and showdown onchain via Soroban's native BN254 host functions.
Live Demo · Demo Video · Slide Deck
Stellar Poker is built directly on top of the cryptographic primitives introduced in Stellar's recent protocol upgrades:
- Protocol 25 (X-Ray) introduced native BN254 elliptic-curve operations and Poseidon2 hashing as Soroban host functions. The
zk-verifiercontract uses these to verify UltraHonk proofs onchain at a fraction of the cost of a pure-Rust implementation. - Protocol 26 (Yardstick) added multi-scalar multiplication, scalar-field arithmetic, and curve-membership checks. These are used inside the verifier's Shplemini opening scheme, which is the most compute-intensive part of UltraHonk verification.
Without these host functions, onchain UltraHonk verification would exceed Soroban's instruction budget. Protocol 25 and 26 are what make this project possible.
ZK proofs can verify that a computation was done correctly, but they cannot keep inputs secret from the prover. In a card game, the entity generating the proof would necessarily know all cards. REP3 secret sharing across multiple MPC nodes ensures no single party — including the coordinator — ever holds the full deck. The slide deck above covers this in detail.
Player A Player B
| |
+------+ +--------+
| |
[Web App] Next.js frontend
|
[Coordinator] Orchestrates MPC sessions (Axum)
/ | \
[Node0] [Node1] [Node2] TACEO coNoir MPC nodes (REP3)
|
[Soroban] Onchain settlement
/ | \
[PokerTable] [ZKVerifier] [CommitteeRegistry]
Supports up to 6 players. Includes a solo mode against a deterministic AI opponent.
- Private cards — Cards exist only as REP3 secret shares across 3 MPC nodes. Privacy holds as long as at least 2 nodes are honest.
- ZK-verified — Deal, reveal, and showdown proofs are UltraHonk proofs verified onchain via Soroban's native BN254 host functions (Protocol 25).
- Trustless settlement — All bets, pot calculation, and payouts are handled entirely in Soroban smart contracts.
- Reusable library —
stellar-zk-cardsis a standalone Rust crate for card encoding and hand evaluation that any Soroban app can use.
| Contract | Address | |---|---|---| | Poker Table | CA3RAB66WJ3OONO4OFYEATISRZA3ND65MN3DET5IE2XXSZZMPKH3CHAV | | Committee Registry | GBTYELEQ2YZH2W6SXLHT4AX6TYBHHU7LNNPKJV7J37VS3S5GPA75KRDU |
Works alongside the Stellar Game Studio deployed at CB4VZAT2U3UC6XFK3N23SKRF2NDCMP3QHJYMCHHFMZO7MRQO6DQ2EMYG.
stellar-poker/
contracts/
poker-table/ Main game contract (betting, state machine, settlement)
zk-verifier/ UltraHonk proof verification (BN254 native ops)
committee-registry/ MPC committee management and slashing
game-hub/ Mock Game Hub contract (Stellar Game Studio interface)
circuits/
lib/ Shared Noir library (cards, commitments, Merkle)
deal_valid/ Proves deck shuffle + deal consistency
reveal_board_valid/ Proves community card reveals match committed deck
showdown_valid/ Proves winner has the best hand
stellar-zk-cards/ Reusable card-game library crate (encoding, hand eval)
services/
coordinator/ Axum HTTP server orchestrating MPC sessions
node/ MPC node (TACEO coNoir participant)
app/ Next.js web frontend
tests/ Integration tests
vendor/ Vendored UltraHonk verifier
scripts/ Build, deploy, and test scripts
docker-compose.yml Full-stack local development
| Component | Technology |
|---|---|
| Smart contracts | Soroban (Rust, soroban-sdk 22.0.0) |
| ZK proofs | Noir circuits + UltraHonk (Barretenberg) |
| MPC | TACEO coNoir (REP3, 3-party) |
| Hash function | Poseidon2 |
| Frontend | Next.js 15, Freighter wallet |
- Rust (stable)
- Nargo 1.0.0-beta.17 —
noirup -v 1.0.0-beta.17 - Node.js 18+
- Docker
- Stellar CLI —
cargo install stellar-cli --features opt - co-noir (for CRS download) —
cargo install --git https://github.com/TaceoLabs/co-snarks co-noir
# Install dependencies and verify build
./scripts/setup.sh
# Download BN254 common reference string
./scripts/download-crs.sh
# Start full stack
docker-compose upThen open http://localhost:3000.
# Check all Rust crates
cargo check
# Run contract tests
cargo test -p poker-table
# Compile and test Noir circuits
./scripts/compile-circuits.sh
cd circuits/lib && nargo test
# Run the frontend
cd app && npm run dev
# Run integration tests (requires docker-compose up)
python3 scripts/test-flow.pyNETWORK=testnet ./scripts/deploy.sh- Create table — Admin creates a
PokerTablecontract with config (blinds, buy-in range, timeout). - Join — Players join with a buy-in (tokens escrowed in contract).
- Start hand — Triggers the MPC committee to shuffle and deal.
- Deal — Committee generates a
deal_validZK proof, commits deck Merkle root + hand commitments onchain, privately delivers hole cards to each player. - Betting — Players submit actions (fold / check / call / bet / raise / all-in) to the contract.
- Reveal — After each betting round, committee reveals community cards with a
reveal_board_validproof. - Showdown — Committee reveals remaining hands, generates a
showdown_validproof, contract settles the pot.
- Private:
deck[52],salts[52](secret-shared in MPC) - Public:
deck_root,hand_commitments[6],dealt_indices - Proves: Valid 52-card deck, Merkle root matches commitments, hand commitments match dealt cards.
- Private:
deck[52],salts[52] - Public:
deck_root,revealed_cards,revealed_indices,previously_used_indices - Proves: Revealed cards match committed deck, no indices reused.
- Private:
hole_cards,board_cards,salts - Public:
hand_commitments,board_commitments,declared_winner - Proves: Cards match commitments, hand evaluation is correct, winner has best hand.
The live demo at stellar-poker-six.vercel.app runs against Stellar testnet. Here is exactly what is live and what is simulated:
| Component | Status | Notes |
|---|---|---|
| Soroban contracts | ✅ Live on testnet | Poker table, ZK verifier, committee registry all deployed |
| ZK proof verification | ✅ Live onchain | zk-verifier contract verifies real UltraHonk proofs via BN254 host functions |
| Frontend | ✅ Live | Hosted on Vercel, connects to testnet via Freighter wallet |
| Solo mode (vs AI) | ✅ Fully functional | Deals, betting, showdown, and settlement all work end-to-end |
| MPC nodes (multiplayer) | 3 TACEO coNoir nodes run for demo purposes; in production these would be independently operated | |
| Multiplayer (2–6 players) | ✅ Functional | Requires all players to have Freighter and testnet XLM |
The ZK proofs in solo mode are generated and verified onchain in every hand — this is not mocked.
The technical patterns in this project are directly applicable to real-world use cases:
- MPC committee + ZK verification — the same architecture works for any multi-party secret: sealed-bid auctions, private voting, threshold key custody, blind RFQ matching in DeFi.
stellar-zk-cards— the card encoding, commitment, and hand evaluation library is a standalone Rust crate any Soroban app can use for any card or tile-based game.- Onchain UltraHonk verifier — the
zk-verifiercontract is a general-purpose Noir proof verifier. Any Noir circuit can be verified through it by swapping the verification key. - REP3 secret sharing via coNoir — the node and coordinator services are structured to be reused for any coSNARK application, not just poker.
