Scaffolding a Commit-Reveal Scheme with Niftyzk
Introduction
This tutorial will contain information about the generated code. This is the continuation of the previous tutorial, Niftyzk Tutorial 1. You should read that one first.
Scaffolding a New Project
Let’s scaffold a new project using niftyzk init. We will select a commit-reveal scheme with Poseidon hash and add 2 inputs for tamper-proofing, address and amount.
niftyzk init
Setting up your current directory
? What project do you want to scaffold? Commit-Reveal Scheme
? Choose the hashing algorithm to use: Poseidon
? Do you wish to add tamperproof public inputs? (E.g: walletaddress): yes
? Enter the name of the public inputs in a comma separated list (no numbers or special characters): address,amount
Generating circuits
Generating javascript
Done
Run npm install in your project folder
The Circuits Directory
Navigate to the /circuits/ directory to see the generated code. It should contain 2 files, circuits.circom which is the entry point and commitment_hasher.circom which contains the hashing implementation.
circuits.circom
pragma circom 2.0.0;
include "./commitment_hasher.circom";
template CommitmentRevealScheme(){
// Public inputs
signal input nullifierHash;
signal input commitmentHash;
signal input address;
signal input amount;
// Private inputs
signal input nullifier;
signal input secret;
// Hidden signals to validate inputs so they can't be tampared with
signal addressSquare;
signal amountSquare;
component commitmentHasher = CommitmentHasher();
commitmentHasher.nullifier <== nullifier;
commitmentHasher.secret <== secret;
// Check if the nullifierHash and commitment are valid
commitmentHasher.nullifierHash === nullifierHash;
commitmentHasher.commitment === commitmentHash;
// An extra operation with the public signal to avoid tampering
addressSquare <== address * address;
amountSquare <== amount * amount;
}
component main {public [nullifierHash,commitmentHash,address,amount]} = CommitmentRevealScheme();
JavaScript Code
First, we look at the library that was scaffolded and then the tests.
The project depends on ffjavascript, snarkjs, circomlib, circomlibjs, and circom_tester.
lib/index.js contains the source code for the client-side code.
First, you will see the functions for generating circuit inputs:
// new public and private inputs and new templates.
// So first we have the merkle tree root as a new public input and pathElements and pathIndices,
// these contain the merkle proof. The levels variable specifies the size of the merkle tree,
// the default 20 will give a lot of branches to work with.
template MerkleTreeChecker(levels) {
signal input leaf;
signal input root;
signal input pathElements[levels];
signal input pathIndices[levels];
component selectors[levels];
component hashers[levels];
signal levelHashes[levels];
levelHashes[0] <== leaf;
for (var i = 1; i < levels; i++) {
selectors[i] = DualMux();
hashers[i] = HashLeftRight();
selectors[i].in[1] <== levelHashes[i - 1];
selectors[i].in[0] <== pathElements[i];
selectors[i].s <== pathIndices[i];
hashers[i].left <== selectors[i].out[0];
hashers[i].right <== selectors[i].out[1];
levelHashes[i] <== hashers[i].hash;
}
root === levelHashes[levels - 1];
}
Merkle Tree Commands
The project gives you a few commands to work with from the CLI to interact with merkle trees manually. There are many use-cases, for example if you want to manage a tree for withdrawing airdrops, you might just manipulate it manually.
lib/run.js contains the commands:
new: creates a new merkle tree with a similar output.proof: asks you for a root hash and a commitment to verify. It will split out a JSON which contains the merkle proof.verify: asks you for the merkle root and the proof and verifies the proof.
Conclusion
I hope this saves you a lot of time developing your circuits.
FAQs
Q: What is a commit-reveal scheme?
A: A commit-reveal scheme is a way to prove possession of a secret without revealing the secret itself.
Q: What is Poseidon hash?
A: Poseidon hash is a cryptographic hash function used in this tutorial.
Q: What are the public inputs in the circuit?
A: The public inputs in the circuit are nullifierHash, commitmentHash, address, and amount.
Q: What are the private inputs in the circuit?
A: The private inputs in the circuit are nullifier and secret.

