Skip to content

Commit 8352b98

Browse files
author
tilo-14
committed
docs: improve zk-merkle-proof and zk-nullifier READMEs
1 parent 1e5f303 commit 8352b98

File tree

2 files changed

+181
-41
lines changed

2 files changed

+181
-41
lines changed

zk/zk-merkle-proof/README.md

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,57 @@ Verifies a Groth16 proof that the account exists in the state tree. Does not mod
2121
- The account address stays private
2222
- Only the data hash, discriminator, and Merkle root are public
2323

24-
## Circuit
24+
## Requirements
2525

26-
5 public inputs:
26+
### System dependencies
2727

28-
- `owner_hashed` - program ID
29-
- `merkle_tree_hashed` - state tree pubkey
30-
- `discriminator` - account type
31-
- `data_hash` - account data
32-
- `expectedRoot` - current Merkle root
28+
- **Rust** (1.90.0 or later)
29+
- **Node.js** (v22 or later) and npm
30+
- **Solana CLI** (2.3.11 or later)
31+
- **Light CLI**: Install with `npm install -g @lightprotocol/zk-compression-cli`
3332

34-
Account hash:
33+
### ZK circuit tools
3534

35+
- **Circom** (v2.2.2): Zero-knowledge circuit compiler
36+
- **SnarkJS**: JavaScript library for generating and verifying ZK proofs
37+
38+
To install circom and snarkjs:
39+
40+
```bash
41+
# Install circom (Linux/macOS)
42+
wget https://github.com/iden3/circom/releases/download/v2.2.2/circom-linux-amd64
43+
chmod +x circom-linux-amd64
44+
sudo mv circom-linux-amd64 /usr/local/bin/circom
45+
46+
# For macOS, replace with circom-macos-amd64
47+
48+
# Install snarkjs globally
49+
npm install -g snarkjs
3650
```
37-
Poseidon(owner_hashed, leaf_index, merkle_tree_hashed, address, discriminator + DOMAIN, data_hash)
38-
```
51+
52+
## Circuit
53+
54+
### Public inputs
55+
56+
- `owner_hashed` - Hash of the program ID owning the account
57+
- `merkle_tree_hashed` - Hash of the state tree pubkey
58+
- `discriminator` - Account type discriminator
59+
- `data_hash` - Hash of account data
60+
- `expectedRoot` - Current Merkle root
61+
62+
### Private inputs
63+
64+
- `leaf_index` - Position of the account in the Merkle tree
65+
- `account_leaf_index` - Leaf index field inside compressed account hash
66+
- `address` - Compressed account address
67+
- `pathElements[26]` - Merkle proof siblings
68+
69+
### Constraint
70+
71+
The circuit:
72+
73+
1. Computes the account hash: `Poseidon(owner_hashed, leaf_index, merkle_tree_hashed, address, discriminator + DOMAIN, data_hash)`
74+
2. Verifies the Merkle proof against `expectedRoot`
3975

4076
## Setup
4177

@@ -45,11 +81,13 @@ Poseidon(owner_hashed, leaf_index, merkle_tree_hashed, address, discriminator +
4581

4682
This script will:
4783

48-
1. Install npm dependencies
49-
2. Download the Powers of Tau ceremony file
50-
3. Compile the circom circuit
51-
4. Generate the proving key (zkey)
52-
5. Export the verification key
84+
1. Check dependencies (Node.js, circom)
85+
2. Install npm dependencies
86+
3. Create build directories
87+
4. Download the Powers of Tau ceremony file (16 powers)
88+
5. Compile the circuit
89+
6. Generate the proving key (zkey) with contribution
90+
7. Export the verification key
5391

5492
## Build and Test
5593

@@ -80,3 +118,11 @@ zk-merkle-proof/
80118
└── scripts/
81119
└── setup.sh # Circuit compilation and setup
82120
```
121+
122+
## Cleaning build artifacts
123+
124+
To clean generated circuit files:
125+
126+
```bash
127+
./scripts/clean.sh
128+
```

zk/zk-nullifier/README.md

Lines changed: 120 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
Example to create one or four nullifiers. Uses Groth16 proofs and compressed accounts.
44

5-
The required property for nullifiers is that they can not be created twice.
5+
The required property for nullifiers is that they can not be created twice.
66
Light uses rent-free PDAs to track nullifiers in an address Merkle tree.
7-
The address tree is the nullifier set and indexed by Helius.
7+
The address tree is the nullifier set and indexed by Helius.
88
You don't need to index your own Merkle tree.
99

1010
On Solana, you typically would create a PDA account.
@@ -15,21 +15,64 @@ Nullifier accounts must remain active, hence lock ~0.001 SOL in rent per nullifi
1515
| PDA | ~0.001 SOL |
1616
| Compressed PDA | ~0.000005 SOL |
1717

18+
## Requirements
19+
20+
### System dependencies
21+
22+
- **Rust** (1.90.0 or later)
23+
- **Node.js** (v22 or later) and npm
24+
- **Solana CLI** (2.3.11 or later)
25+
- **Light CLI**: Install with `npm install -g @lightprotocol/zk-compression-cli`
26+
27+
### ZK circuit tools
28+
29+
- **Circom** (v2.2.2): Zero-knowledge circuit compiler
30+
- **SnarkJS**: JavaScript library for generating and verifying ZK proofs
31+
32+
To install circom and snarkjs:
33+
34+
```bash
35+
# Install circom (Linux/macOS)
36+
wget https://github.com/iden3/circom/releases/download/v2.2.2/circom-linux-amd64
37+
chmod +x circom-linux-amd64
38+
sudo mv circom-linux-amd64 /usr/local/bin/circom
39+
40+
# For macOS, replace with circom-macos-amd64
41+
42+
# Install snarkjs globally
43+
npm install -g snarkjs
44+
```
45+
1846
## Flow
1947

2048
1. Client computes nullifiers from secrets
2149
2. Client generates Groth16 proof
2250
3. On-chain: verify proof, derive addresses, create accounts
2351
4. If any address exists, tx fails
2452

25-
## Instructions
53+
## Program instructions
54+
55+
### 1. `create_nullifier`
56+
57+
Creates a single nullifier account using a ZK proof. The nullifier is derived from `Poseidon(verification_id, secret)` where only the prover knows the secret.
58+
59+
**Properties:**
60+
61+
- The secret stays private
62+
- The nullifier is deterministic from the secret and verification_id
63+
- If the nullifier address already exists, the transaction fails
64+
65+
### 2. `create_batch_nullifier`
66+
67+
Creates four nullifier accounts with a single ZK proof. Each nullifier is derived from the same `verification_id` but different secrets.
2668

27-
| Instruction | Nullifiers | Description |
28-
|-------------|-----------|-------------|
29-
| `create_nullifier` | 1 | Single nullifier with ZK proof |
30-
| `create_batch_nullifier` | 4 | Batch of 4 with single proof |
69+
**Properties:**
3170

32-
## Compute Units
71+
- All four secrets stay private
72+
- Single proof verification is ~2.7x more efficient per nullifier than four separate proofs
73+
- If any nullifier address already exists, the entire transaction fails
74+
75+
## Compute units
3376

3477
| Method | Nullifiers | CU | CU per nullifier |
3578
|--------|-----------|-------------|------------------|
@@ -38,39 +81,82 @@ Nullifier accounts must remain active, hence lock ~0.001 SOL in rent per nullifi
3881

3982
*Estimated. Batch is ~2.7x more efficient per nullifier.
4083

41-
## Setup
84+
## Circuits
4285

43-
```bash
44-
./scripts/setup.sh
45-
cargo build-sbf
46-
```
86+
### Single nullifier (`nullifier.circom`)
4787

48-
## Testing
88+
**Public inputs:**
4989

50-
**Rust tests**:
51-
```bash
52-
cargo test-sbf
53-
```
90+
- `verification_id` - Context identifier (vote ID, airdrop ID, etc.)
91+
- `nullifier` - The nullifier hash
5492

55-
**TypeScript tests**
56-
```bash
57-
npm install
58-
npm test
59-
```
93+
**Private inputs:**
6094

61-
## Circuits
95+
- `secret` - Only the owner knows this value
96+
97+
**Constraint:**
6298

63-
**Single** (`nullifier.circom`):
6499
```circom
65100
nullifier === Poseidon(verification_id, secret)
66101
```
67102

68-
**Batch** (`batch_nullifier.circom`):
103+
### Batch nullifier (`batchnullifier.circom`)
104+
105+
**Public inputs:**
106+
107+
- `verification_id` - Shared context for all nullifiers
108+
- `nullifier[4]` - Array of 4 nullifier hashes
109+
110+
**Private inputs:**
111+
112+
- `secret[4]` - Array of 4 secrets
113+
114+
**Constraint:**
115+
69116
```circom
70117
for i in 0..4:
71118
nullifier[i] === Poseidon(verification_id, secret[i])
72119
```
73120

121+
## Setup
122+
123+
```bash
124+
./scripts/setup.sh
125+
```
126+
127+
This script will:
128+
129+
1. Check dependencies (Node.js, circom)
130+
2. Install npm dependencies
131+
3. Create build directories
132+
4. Download the Powers of Tau ceremony file (14 powers)
133+
5. Compile single nullifier circuit
134+
6. Generate single nullifier proving key
135+
7. Compile batch nullifier circuit
136+
8. Generate batch nullifier proving key
137+
9. Clean intermediate files
138+
139+
## Build and test
140+
141+
**Build:**
142+
143+
```bash
144+
cargo build-sbf
145+
```
146+
147+
**Rust tests:**
148+
149+
```bash
150+
cargo test-sbf
151+
```
152+
153+
**TypeScript tests:**
154+
155+
```bash
156+
npm install
157+
npm test
158+
```
159+
74160
## Structure
75161

76162
```
@@ -84,3 +170,11 @@ zk-nullifier/
84170
│ └── zk-nullifier.ts # TypeScript tests
85171
└── scripts/setup.sh
86172
```
173+
174+
## Cleaning build artifacts
175+
176+
To clean generated circuit files:
177+
178+
```bash
179+
./scripts/clean.sh
180+
```

0 commit comments

Comments
 (0)