Skip to content

Instantly share code, notes, and snippets.

@stackdump
Created January 28, 2026 16:50
Show Gist options
  • Select an option

  • Save stackdump/c9a00049e7a9050e5b7d053fdb2b0117 to your computer and use it in GitHub Desktop.

Select an option

Save stackdump/c9a00049e7a9050e5b7d053fdb2b0117 to your computer and use it in GitHub Desktop.
ZK Tic-Tac-Toe Implementations Comparison - ZoKrates vs Aleo/Leo vs Petri-Pilot (gnark)

ZK Tic-Tac-Toe Implementations Comparison

A survey of zero-knowledge proof implementations for tic-tac-toe games.

Implementations Overview

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

Detailed Comparison

1. ZoKrates Implementation (2019)

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

2. Aleo/Leo Implementation (2022+)

Documentation: Aleo Tic-Tac-Toe

What it proves:

  • Valid move transitions
  • Game state integrity

Architecture:

  • Struct-based board representation
  • make_move transition 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

3. Petri-Pilot Implementation (2026)

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:

  1. Position was empty before the move
  2. Correct player's turn
  3. State transition is valid (pre_root → post_root)
  4. Prover knows the actual board that hashes to the roots

Win Circuit proves:

  1. Board has a winning pattern
  2. Winner is correctly identified
  3. 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 Matrix

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

ZK API Reference (Petri-Pilot)

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

Example Move Response (Petri-Pilot)

{
  "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..."]
  }
}

Why State Root Chains Matter

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 previous post_state_root)
  • post_state_root (becomes next pre_state_root)

This creates an immutable, verifiable history where:

  1. You can't insert fake moves
  2. You can't reorder moves
  3. You can't modify past states
  4. Anyone can verify the entire game without replaying it

Try It

Live Demo: pilot.pflow.xyz/zk-tic-tac-toe

  1. Click "ZK Mode: OFF" to enable ZK mode
  2. Click "New Game" to create a ZK-tracked game
  3. Play some moves (each generates a verified proof)
  4. Click "🔍 Verify Game History" to see the interactive proof inspector
  5. Click any step to learn about zero-knowledge proofs!

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment