Creating zk dApp Sudoku Proof
Tags: zeroknowledge, zksnark, smartcontract, solidity
Published: 2023-10-09 23:47:52

---
title: Creating zk dApp Sudoku Proof
published: true
description: 
tags: zeroknowledge, zksnark, smartcontract, solidity
cover_image: https://images.unsplash.com/photo-1640537702474-3e503c21eefc?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1470&q=80
# Use a ratio of 100:42 for best results.
# published_at: 2023-03-25 09:50 +0000
---

To begin, we need to install the required dependencies. Make sure you have Node.js and npm installed before proceeding.

First, let's install Circom:

```
npm install -g circom
```

Next, we'll generate the circuit file for our Sudoku game proof:

```
circom create sudoku.circom
```

Open the `sudoku.circom` file in your preferred editor and write the following code:

```circom
template Sudoku(idx) {
    signal a[9][9];
    signal x[10];
    signal y[10];
    signal v[10];

    for i in [0..8] {
        for j in [0..8] {
            constraint a[i][j] > 0;
            constraint a[i][j] < 10;
        }
    }

    for i in [0..8] {
        for j in [0..8] {
            c = a[i][j];
            constraint x[c] == i;
            constraint y[c] == j;
        }
    }

    for i in [0..2] {
        for j in [0..2] {
            num = i * 3 + j;
            constraint v[num] == (a[x[num]][y[num]]);
        }
    }

    def commodore = multiplexer([
        private x[0],
        private x[1],
        private x[2],
        private x[3],
        private x[4],
        private x[5],
        private x[6],
        private x[7],
        private x[8]
    ]);

    def everest = multiplexer([
        private y[0],
        private y[1],
        private y[2],
        private y[3],
        private y[4],
        private y[5],
        private y[6],
        private y[7],
        private y[8]
    ]);

    def kilimanjaro = multiplexer([
        private v[0],
        private v[1],
        private v[2],
        private v[3],
        private v[4],
        private v[5],
        private v[6],
        private v[7],
        private v[8]
    ]);

    constant C = 1;

    for i in [0..2] {
        for j in [0..2] {
            constraint commodore[num] == i;
            constraint everest[num] == j;
            constraint kilimanjaro[num] == (a[commodore[num]][everest[num]]);
        }
    }
}

component main = Sudoku(0);
```

Now, let's generate the circuit:

```
circom sudoku.circom
```

This will create a `circuit.json` file that represents our Sudoku game proof circuit.

Next, we'll write the Solidity smart contract. In the `contracts` directory, create a new file called `Sudoku.sol` and add the following code:

```solidity
pragma solidity ^0.8.0;

contract Sudoku {
    struct Puzzle {
        uint8[9][9] puzzle;
    }

    struct Proof {
        uint32[9][9] proof;
    }

    function verifySolution(Puzzle memory puzzle, Proof memory proof) public pure returns (bool) {
        // TODO: Implement the verification logic
        return false;
    }
}
```

The `verifySolution` function takes in a `Puzzle` struct (represents the Sudoku puzzle) and a `Proof` struct (represents the proof provided by the user) and returns a boolean indicating whether the solution is valid or not. We'll fill in the verification logic later.

Finally, let's write the JavaScript frontend code. In the `src` directory, create a new file called `app.js` and add the following code:

```javascript
const Web3 = require('web3');
const contractData = require('../build/contracts/Sudoku.json');

const web3 = new Web3('http://localhost:8545'); // Update with your Ethereum provider's URL
const contractAddress = '<YOUR_CONTRACT_ADDRESS>'; // Update with the deployed contract address
const accountAddress = '<YOUR_ACCOUNT_ADDRESS>'; // Update with your Ethereum account address

const contract = new web3.eth.Contract(contractData.abi, contractAddress);

async function verifySolution(puzzle, proof) {
    const result = await contract.methods.verifySolution(puzzle, proof).call({ from: accountAddress });
    return result;
}

async function run() {
    const puzzle = [
        [6, 0, 2, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 7, 5, 2, 6, 0, 0],
        [0, 0, 8, 0, 6, 0, 0, 0, 0],
        [0, 0, 4, 0, 9, 8, 0, 7, 0],
        [7, 6, 0, 0, 0, 0, 0, 2, 4],
        [0, 3, 0, 5, 7, 0, 9, 0, 0],
        [0, 0, 0, 0, 1, 0, 4, 0, 0],
        [0, 0, 9, 3, 2, 7, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 6, 0, 5],
    ];

    const proof = [
        [0, 6, 7, 5, 4, 2, 3, 8, 9],
        [3, 1, 5, 0, 0, 0, 7, 6, 4],
        [2, 4, 8, 6, 9, 3, 1, 5, 0],
        [1, 7, 0, 4, 2, 6, 8, 9, 3],
        [9, 5, 6, 0, 8, 1, 2, 0, 7],
        [8, 2, 3, 7, 0, 5, 0, 4, 0],
        [5, 9, 2, 8, 0, 0, 0, 7, 6],
        [6, 8, 1, 9, 3, 0, 4, 2, 5],
        [4, 3, 0, 0, 0, 0, 0, 0, 0],
    ];

    const result = await verifySolution(puzzle, proof);
    console.log(result);
}

run();
```

This code sets up the Web3 provider, loads the Sudoku smart contract, and provides a sample Sudoku puzzle and proof to test the verification.

Before running the script, make sure to replace `<YOUR_CONTRACT_ADDRESS>` with the deployed smart contract address and `<YOUR_ACCOUNT_ADDRESS>` with your Ethereum account address.

To run the application, open a terminal window and navigate to the project directory. Then, run the following command:

```
node src/app.js
```

This will execute the script and print the result indicating whether the solution is valid or not.

That's it! You have created a zk DApp using Circom, Solidity, and JavaScript to prove someone's ability to solve a Sudoku game without revealing the answer. Feel free to enhance and customize the code as per your requirements.
---
Ps. This content is AI-generated by the prompt: 
```
We will create a zk DApp to prove that someone knows how to solve a sudoku game, without revealing the answer.

We will use Circom (for circuits), Solidity (for smart contracts) and Javascript (for the frontend).
```