Semaphore
Join the Telegram group to discuss.
Introduction
Semaphore is a zero-knowledge gadget which allows users to prove their membership of a set without revealing their original identity. At the same time, it allows users to signal their endorsement of an arbitrary string. It is designed to be a simple and generic privacy layer for Ethereum dApps. Use cases include private voting, whistleblowing, mixers, and anonymous authentication.
For more information, refer to the documentation.
Quick start
You should have Node 11.14.0 installed. Use
nvm to install it.
Clone this repository, install dependencies, and build the source code:
git clone git@github.com:kobigurk/semaphore.git && \
cd semaphore && \
npm i && \
npm run bootstrap && \
npm run build
Next, either download the compiled zk-SNARK circuit, proving key, and verification key (note that these keys are for testing purposes, and not for production, as there is no certainty that the toxic waste was securely discarded).
To download the circuit, proving key, and verification key, run:
# Start from the base directory
cd circuits && \
./circuits/scripts/download_snarks.sh
To generate the above files locally instead, run:
# Start from the base directory
cd circuits && \
./circuits/scripts/build_snarks.sh
This process should take about 45 minutes.
Build the Solidity contracts (you need solc v 0.5.12 installed in your $PATH):
# Start from the base directory
cd contracts && \
npm run compileSol
Run tests while still in the contracts/ directory:
# The first command tests the Merkle tree contract and the second
# tests the Semaphore contract
npm run test-semaphore && \
npm run test-mt
How to use Semaphore in your dApp
The Semaphore contract is the base layer of Semaphore. Other contracts can build upon this to create applications that rely on anonymous signaling.
First, you should have the proving key, verification key, and circuit file, which are static, easily available to your users.
To have full flexibility over Semaphore's mechanisms, you should write a Client contract and set the owner of the Semaphore contract as the address of the Client contract. This allows the Client contract to call certain critical Semaphore functions.
See SemaphoreClient.sol for an example.
Semaphore functions
insertIdentity(uint256 _identityCommitment)
This inserts the user's identity commitment into the Semaphore contract's Merkle tree of identities.
The client should generate it using
libsemaphore's
genIdentityCommitment() function.
broadcastSignal(...)
TODO: fix this
The full function signature is:
broadcastSignal(
bytes memory _signal,
uint256[8] memory _proof,
uint256 _root,
uint256 _nullifiersHash,
uint232 _externalNullifier
)
-
_signal: The signal to broadcast. Useethers.utils.toUtf8Bytes(SIGNAL)to generate it, whereSIGNALis a string. -
_proof: The zk-SNARK proof generated bylibsemaphore'sgenBroadcastSignalParams()function. -
_root: The root of the Merkle tree. This is part of the output oflibsemaphore'sgenWitness()function. -
_nullifiersHash: A uniquely derived hash of the external nullifier, user's identity nullifier, and the Merkle path index to their identity commitment. It ensures that a user cannot broadcast a signal with the same external nullifier more than once. -
_externalNullifier: A 29-byte value which serves as a context of sorts for the signal. Refer to the high-level explanation of Semaphore for more details.
-
(Optional) Has functions which call the Semaphore contract's:
-
addExternalNullifier() -
deactivateExternalNullifier() -
reactivateExternalNullifier()
-
These functions add, deactivate, and reactivate an external nullifier respectively. As each identity can only signal once to an external nullifier, and as a signal can only be successfully broadcasted to an active external nullifier, these functions enable use cases where it is necessary to have multiple external nullifiers or to activate and/or deactivate them.
- (Optional) There is also a function which controls broadcast permissioning:
setPermissioning(bool _newPermission). If permissioning is set totrue, then only the owner (usually the Client contract) may callbroadcastSignal(). Otherwise, anyone may do so.
Audit results
The Ethereum Foundation and POA Network commissioned ABDK Consulting to audit the source code of Semaphore as well as circomlib, which contains components which the Semaphore zk-SNARK uses.
The results of the audit can be found in the audit/ directory. The team's responses to their results can be found in audit/README.md.