After implementing the circuit, we export a zkSNARK validator with the following command:
zokrates export-verifier-scrypt
snarkjs zkey export scryptverifier
We get an sCrypt project under verifier/
. With this verifier we can implement the Battleship contract with ZKP. We can start building the actual game logic in the contract. In our case, we can pass a board state (private) and move, and emit whether it's a hit. The contract just needs the proof to ensure the absence of cheating.
The Battleship game consists of two players: you and a computer. The Battleship contract contains four properties:
player
: public key used to check the signature to confirm that you executed the contract.computer
: public key used to check the signature to confirm that the computer executed the contract.playerBoardHash
: A hash commitment of the positions and orientations of all your shipscomputerBoardHash
: A hash commitment of the positions and orientations of all computer’s shipsIn addition to the above four properties, the contract also contains three state properties:
successfulPlayerHits
: Indicates how many times you hit the battleshipsuccessfulComputerHits
: Indicates how many times the computer player has hit the shipplayerTurn
: Indicates that it's your turn or the computer’s to fireWhen the game starts, you and the computer each secretly place the ships and calculate the hash commitment. The contract is initialized with the hashed commitments and public keys of both players.
The contract contains a public method named move()
. In the move()
method, we use the zk-SNARK verifiers verifyProof()
method to check the firing submitted by the other player.
verifyProof()
contains four inputs and a proof:
x
, y
indicate where the player fires.hit
indicates the other party reports whether you hit or not.proof
is the proof that the other party generates for their own firing. With the verifier library and the proof provided by the other party, you can check whether the other party is honest.If the other party provides an honest result, it will pass the check, otherwise it will fail. Afterwards, we check whether the signature of the player calling the contract is valid and update the number of times the corresponding player hit the battleship according to whether the battleship is hit, that is, we update the state properties successfulPlayerHits
and successfulComputerHits
. Finally we update the playerTurn
flag. If someone hits the ships 17
times first, he wins the game and the game is over. If not, save the latest states and wait for the next move.
In summary, we have achieved the Battleship contract. In the contract we imported and called the sCrypt zk-SNARK verifier code that we exported in a previous step.