Semaphore - part 1
I have been studying about zero-knowledge proof in the past eight weeks. It is hard to grasp how a software project could integrate zero-knowledge proof. Then, through some community chat groups, I came across Privacy & Scaling Explorations group and one of their projects, Semaphore. Semaphore is a very educational project. In this project, I see how ZKP is being applied (in a fashion I understand) and observe excellent software engineering inside.
Semaphore allows users belonging to a certain group to vote without revealing which member they are, aka anonymous voting. There is also a mechanism to prevent users from double-voting, which is done by posting some "residues" generated by the zero-knowledge proof protocol on-chain.
But what is great about the project is that it is very beginner-friendly, and I say this with great respect. The whole project is architected very nicely. It can even be viewed as a model project for how software and packages are structured in modern-day dApps. I have learned a lot from their software structure and encapsulation.
-
The core software project: Semaphore protocol, with a nice structure of:
-
contracts package - the smart contract that verify the proof generated offchain.
-
proof package - the off-chain logics that generate the ZKP with wasm code generated by an arithmetic circuit.
-
circuits package - contains the arithmetic circuit written in circom that generates and verifies proof.
-
hardhat package - a package that allows developers to deploy the core semaphore contract via hardhat without downloading the semaphore project.
-
-
A template to see how the protocol can be incorporated into other projects. It consists of:
- a website
- a seemingly simple smart contract Feedback. This is because most of the key logic has been implemented in the Semaphore contract.
-
The project leverages the Merkle tree structure to verify that a member belongs to a group, with all the tree leaves being the users' identity commitment. The user will generate a Merkle proof to show that he belongs to the group. The core team implements the Merkle tree structure separately as a Lean Incremental Merkle Tree (with a summary note).
-
The project has excellent documentation and website as well, including as two different packages inside the source code.
Studying the project taught me a lot of optimization tricks I can apply in the zk-battleship codebase. I also saw how they used to save on-chain gas costs, particularly using emitted events to store voting results (the user feedback messages) instead of on-chain storage to reduce gas costs further. This is something that never crossed my mind before.
There are two feature enhancements I can help implement on the current Semaphore basis to further my engineering understanding in zk-app development.
-
Users can later prove they have voted without revealing their voting option, which can become proof of participation for them.
-
The voting result is hidden during the voting phase until it ends. In this way, the choices made by late voters won't be affected by the given voting result so far.