ZK Checkmate (R0 v1.0)

Let's experiment with a ZK chess game for verifying a winning move (a checkmate) is possible next turn without revealing what the move is to anyone. We extend the example by proving we know a set of moves that arrives at that final board state.

  1. (Optional) Watch a primer on FEN and SAN notation for chess.

  2. Watch this playlist to learn the basics of RISC Zero.

  3. Use rzup to setup your development environment based on the correct version of the RISC Zero Getting Started Docs for you.

    # Get rzup
    curl -L https://risczero.com/install | bash
    # Follow command instructions to use rzup
    # ... This will take a while first time!
    
  4. Generate a new repo from the template for this chess example:

    # Clone direct, or your new repo fom this template:
    git clone https://github.com/<YOUR_GH_USER>/risc0-v1-chess 
    # **OR** Clone the template direct:
    git clone https://github.com/nuke-web3/risc0-v1-chess 
    cd risc0-v1-chess 
    cargo r -r
    # ... This will take a while first time!
    # If you get errors, see step one to get setup!
    
  5. Take a look at the structure of the code and key files:

    risc0/examples/risc0-v1-chess 
    β”œβ”€β”€ Cargo.toml
    β”œβ”€β”€ core                 
    β”‚   β”œβ”€β”€ Cargo.toml
    β”‚   └── src
    β”‚       └── lib.rs       # 🌍 Shared = Host ↔️ Guest
    β”œβ”€β”€ methods
    β”‚   β”œβ”€β”€ build.rs
    β”‚   β”œβ”€β”€ Cargo.toml
    β”‚   β”œβ”€β”€ guest
    β”‚   β”‚   β”œβ”€β”€ Cargo.lock
    β”‚   β”‚   β”œβ”€β”€ Cargo.toml
    β”‚   β”‚   └── src
    β”‚   β”‚       └── main.rs  # 🧰 Guest = Game Logic to be proven 🌟
    β”‚   └── src
    β”‚       └── lib.rs
    β”œβ”€β”€ README.md
    └── src
        └── main.rs          # πŸƒ Host = Execution of guest & GUI & more unproven
    
  6. Add the ability to prove multiple moves arriving at a final checkmate:

    1. In core/src/lib.rs change Inputs to allow for many moves, also refactor where that struct is used as needed.
    2. In src/main.rs change the FEN initial_state and mv to moves to support multiple (legal) moves.
      1. ✨Experiment with game Inputs on chess.com/analysis by Loading a valid FEN in "setup position" any playing moves.
      2. Test if a non-mate move is detected.
    3. In methods/guest/src/main.rs change what is commited about the game.
⚠️ SPOILERS ⚠️

One possible solution with comments and tips

πŸ“ Key Takeaways

  • Use crates in the zkVM without modification - no need to rewrite in circuits or zkDSL!
  • Use standard patterns like println! & fmt! normally for basic experiments and debugging in DEV_MODE.
  • 10s on lines of code overall -> useful proof, easily extensible!
  • Incomplete information games are possible on-chain! Hidden data/moves for players are proven, never revealed to anyone!
  • There is still many risks of creating privacy and security faults via bugs and all the normal ways cryptographic systems can break down... With zkVMs you are abstracting the math/circuits of zk... NOT the robust design and audits required to harden your system!

πŸ€“ Taking it Further

Here are some ideas to keep extending this example to learn more:

  • Add something to core/src/lib.rs around player identity that could be proven, perhaps their blockchain account via ENS.
  • Make the game multiplayer with turns between untrusting parties
    • Perhaps using moves signed by players in a state channel type construction, latter proven to arrive at a final winner (only?) in the receipt.
  • Integrate with the Foundry Template
    • Game with stake or pot to play?
    • Verify a winner and dispense funds accordingly.

Original deep dive video & slides & source - a great reference to supplement, but outdated using R0 v0.12 .