A survey of zero-knowledge proof implementations for tic-tac-toe games.
| Implementation | Framework | Year | Language | Live Demo |
|---|---|---|---|---|
| andreysobol/tic-tac-toe-snark | ZoKrates | 2019 | JavaScript/Java | No |
| Aleo Leo Examples | Leo/Aleo | 2022+ | Leo | Playground |
| pflow-xyz/petri-pilot | gnark | 2026 | Go | Yes |
Repository: andreysobol/tic-tac-toe-snark
What it proves:
- Valid winning position (8 win patterns)
- No cheating (players don't occupy same cell)
Architecture:
- Single circuit for win verification
- Moves encoded as position numbers (0-8, 9 for empty)
- Generates Solidity verifier contract
Limitations:
- No state root tracking
- No move-by-move proof generation
- No interactive UI
Documentation: Aleo Tic-Tac-Toe
What it proves:
- Valid move transitions
- Game state integrity
Architecture:
- Struct-based board representation
make_movetransition function- Compiles to Aleo VM circuits
Features:
- Part of official Leo examples
- Playground available at play.leo-lang.org
- Privacy-preserving by default (Aleo network)
Limitations:
- Requires Aleo ecosystem
- No educational component
- No state root chain visualization
Repository: pflow-xyz/petri-pilot
Live Demo: pilot.pflow.xyz/zk-tic-tac-toe
What it proves:
Two separate circuits (Groth16 on BN254):
| Circuit | Constraints | Public Inputs | Private Inputs |
|---|---|---|---|
| Move | 6,012 | 4 | 10 |
| Win | 3,036 | 2 | 9 |
Move Circuit proves:
- Position was empty before the move
- Correct player's turn
- State transition is valid (pre_root → post_root)
- Prover knows the actual board that hashes to the roots
Win Circuit proves:
- Board has a winning pattern
- Winner is correctly identified
- State root matches the claimed board
Architecture:
- gnark (Go) for circuit compilation and proving
- MiMC hash for state root computation
- State root chain tracks entire game history
- HTTP API for proof generation/verification
Unique Features:
| Feature | Description |
|---|---|
| State Root Chain | Each move creates a new state root, forming an unbroken cryptographic chain |
| Interactive Proof Inspector | Click any step to see detailed proof information |
| Educational Explanations | Learn what each proof verifies and why it matters |
| Replay Verification | Verify entire game history with chain integrity checking |
| Proof Export | JSON, Solidity calldata, downloadable verifier contracts |
| Petri Net Integration | Game logic defined as a Petri net workflow |
| Feature | ZoKrates | Leo/Aleo | Petri-Pilot |
|---|---|---|---|
| Move proofs | ❌ | ✅ | ✅ |
| Win proofs | ✅ | ✅ | ✅ |
| State root chain | ❌ | ❌ | ✅ |
| On-chain verifier | ✅ | ✅ (Aleo) | ✅ (Solidity) |
| Live demo | ❌ | Playground | ✅ |
| Interactive UI | ❌ | ❌ | ✅ |
| Educational content | ❌ | ❌ | ✅ |
| Replay verification | ❌ | ❌ | ✅ |
| Proof export (JSON) | ❌ | ❌ | ✅ |
| Solidity calldata export | ❌ | N/A | ✅ |
| Verifier download | ❌ | N/A | ✅ |
GET /zk/health - Health check, lists circuits
POST /zk/game - Create new ZK game
GET /zk/game/{id} - Get game state with roots
POST /zk/game/{id}/move - Make move, returns proof
POST /zk/game/{id}/check-win - Check winner, returns proof
GET /zk/circuits - List available circuits
POST /zk/verify - Verify a proof
GET /zk/verifier/{circuit} - Download Solidity verifier contract
POST /zk/replay - Verify entire game history
{
"success": true,
"position": 4,
"player": 1,
"pre_state_root": "5703935289983219918...",
"post_state_root": "6237557584142392963...",
"board": [0, 0, 0, 0, 1, 0, 0, 0, 0],
"proof": {
"circuit": "move",
"proof_hex": "de20b46b5f6a7009...",
"public_inputs": [
"0x0c9c501e9b7739eb...",
"0x05661ab7282a768b...",
"0x00000000...0004",
"0x00000000...0001"
],
"verified": true,
"a": ["0x...", "0x..."],
"b": [["0x...", "0x..."], ["0x...", "0x..."]],
"c": ["0x...", "0x..."]
}
}Traditional ZK tic-tac-toe implementations prove individual facts (valid win, valid move) but don't link them together cryptographically.
The state root chain approach:
Initial Board Move 1 Move 2 Move 3
[empty] → [X at 4] → [O at 0] → [X at 2]
↓ ↓ ↓ ↓
root_0 → root_1 → root_2 → root_3
proof_1 proof_2 proof_3
Each proof includes:
pre_state_root(must match previouspost_state_root)post_state_root(becomes nextpre_state_root)
This creates an immutable, verifiable history where:
- You can't insert fake moves
- You can't reorder moves
- You can't modify past states
- Anyone can verify the entire game without replaying it
Live Demo: pilot.pflow.xyz/zk-tic-tac-toe
- Click "ZK Mode: OFF" to enable ZK mode
- Click "New Game" to create a ZK-tracked game
- Play some moves (each generates a verified proof)
- Click "🔍 Verify Game History" to see the interactive proof inspector
- Click any step to learn about zero-knowledge proofs!