Battleships (also known as Sea Battle) is a strategy-type guessing game for two players.
It is played on ruled grids (paper or board) on which each player's fleet of warships is marked.
The locations of the fleets are concealed from the other player.
Players alternate turns calling "shots" at the other player's ships, and the objective of the game is to destroy the opposing player's fleet.
The paper/board game is played on four grids, two for each player.
The grids are typically square – usually 10×10 – and the individual squares in the grid are identified by letter and number.
On one grid the player arranges ships and records the shots by the opponent. On the other grid, the player records their own shots.
Doing everything on-chain is too transparent, therefore there should be a way to persist ship deployment locally with the player’s machine, whilst being able to prove to the opponent whether his/her shots successfully hit the ships or not.
⇒ With the ability to generate zero-knowledge proof locally and verify the results on a blockchain network (e.g. Ethereum, Solana), players do not have to trust each other and expose their ship deployment data (secret) online at all. The on-chain verifier can do the job fairly for them.
⇒ The ZK Battleship game is based on zero-knowledge proofs and poseidon encryption to keep the game state completely trustless and private to the players.
→ Regarding that every move made in the game i.e. transaction is public, the game progression stats is masked applying poseidon encryption to the game results.
→ The boards and shots of the players are kept private utilizing the DSL circom2 to develop the circuits required to integerate the ZKP logic to the solana program.
→ The ZK impelemenation of the game is based on two main circuits.
→ The first circuit is the board circuit, it takes the board of the player as a private input and its poseidon hash as a public input that serves as integrity attestation that the player's board is not tampered with.
When a player hosts or joins a game, the initial board hash of the player is saved in the game account so that the program conducts the groth16 verification of the proof + the stored hash as public input. Hence, any interference with the board even as a private input is reverted by the program due to non compliant board hash.
This is where the magic of zero knowledge and privacy prevails handy. It shows that it is possible to trustlessly enable provable integration of hidden information into the game by using these inputs initially saved in the game account. The board hashes saved from the initilization of the game will still be used to prove the integrity of the players' boards whenever an attack(shot) is made.
→ The second circuit is the shot circuit.
→ To keep the game account data storage as efficient as possible, the account stores only one encrypted shot and one encrypted hit result at a time, this way, when a player makes a move, the program verifies the shot circuit according to the encrypted shot from the previous turn (opponent's shot) and if successful, it updates the shot as the current player's encrypted shot in order to be verified in the next turn.
→ It is unavoidable that each player knows his/her shot result only when the opponent's finishes playing his/her turn because private inputs of the shot circuit can only be entered by the player himself/herself.
→ It is notable that the game stat progression for each player is synchronously retrieved, decrypted, and saved by the client and hence the whole game data of the player and his opponents is displayed clear and complete without any issue and with a minimum data exchange through the game account.
⇒ The ZK Battleship game cli is still under development, however it shows a cool interface for a user to host or join a game with everything clearly displayed without any worries of the technical or cryptographic operations.
Since compatibility is a common question, M1 chips will outperform the expected wait times on ptau and setup Node v16.17.1 was last used to compile this project, and failure to use it will break ipfs in deploy script (either use node 16 or comment out IPFS)
curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
git clone https://github.com/iden3/circom.git
cd circom
cargo build --release
cargo install --path circom
cd ..
yarn install
yarn ptau
yarn setup
anchor build
to build the solana program.
anchor deploy
to deploy the game to localnet.
anchor test --skip-deploy --skip-local-validator
to test the game.
yarn clean-artifacts
to clean all circuit artifacts.
yarn clean-setup
to clean circuit setup excluding ptau files.
Shoutout to BattleZips folks for their meticulous work in integrating the ZK logic to smart contracts and their detailed documentation for their code.
Great appreciation to weijiekoh for the poseidon encryption circuits and his contribution to many useful cryptography libraries.
Also great appreciation to no-stack-dub-sack for the inspiring and cool cli that helped developing the cli of this project despite being still under development.
All gratitude especially to ananas-block for the groth16 solana verifier that without it, this project wouldn't be implementing ZK logic to the program. In addition to his support and guidance during the six months of my short career.