@semaphore-protocol/proof 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -58,30 +58,80 @@ yarn add @semaphore-protocol/proof
58
58
 
59
59
  ## 📜 Usage
60
60
 
61
- ### Generating Merkle proofs
61
+ \# **createMerkleTree**(depth: _number_, zeroValue: _BigNumberish_, leaves: _BigNumberish\[]_): _MerkleProof_
62
+
63
+ ```typescript
64
+ import { createMerkleTree } from "@semaphore-protocol/proof"
65
+
66
+ const depth = 20
67
+ const zeroValue = BigInt(0)
68
+ const leaves = [BigInt(1), BigInt(2)]
69
+
70
+ const merkleTree = createMerkleTree(treeDepth, zeroValue, leaves)
71
+ ```
72
+
73
+ \# **createMerkleProof**(depth: _number_, zeroValue: _BigNumberish_, leaves: _BigNumberish\[]_, leaf: _BigNumberish_): _MerkleProof_
62
74
 
63
75
  ```typescript
64
76
  import { Identity } from "@semaphore-protocol/identity"
65
- import { generateMerkleProof } from "@semaphore-protocol/proof"
77
+ import { createMerkleProof } from "@semaphore-protocol/proof"
66
78
 
67
79
  const depth = 20
68
80
  const zeroValue = BigInt(0)
81
+
69
82
  const identity = new Identity()
70
- const identityCommitment = identity.genIdentityCommitment()
71
- const identityCommitments = [BigInt(1), identityCommitment, BigInt(2)]
72
83
 
73
- const merkleProof = generateMerkleProof(depth, zeroValue, identityCommitments, 1)
84
+ const leaf = identity.genIdentityCommitment()
85
+ const leaves = [BigInt(1), identityCommitment, BigInt(2)]
86
+
87
+ const merkleProof = createMerkleProof(treeDepth, zeroValue, leaves, leaf)
74
88
  ```
75
89
 
76
- ### Creating Semaphore proofs
90
+ \# **generateProof**(identity: _Identity_, merkleProof: _MerkleProof_, externalNullifier: _BigNumberish_, signal: _string_, snarkArtifacts: _SnarkArtifacts_): Promise\<_SemaphoreFullProof_>
77
91
 
78
92
  ```typescript
79
- import { Semaphore } from "@semaphore-protocol/protocols"
93
+ import { Identity } from "@semaphore-protocol/identity"
94
+ import { generateProof } from "@semaphore-protocol/proof"
80
95
 
81
- const signal = "Hello world"
82
96
  const externalNullifier = BigInt(1)
83
- const witness = Semaphore.genWitness(identity, merkleProof, externalNullifier, signal)
97
+ const signal = "Hello world"
98
+
99
+ const fullProof = await generateProof(identity, merkleProof, externalNullifier, signal, {
100
+ zkeyFilePath: "./semaphore.zkey",
101
+ wasmFilePath: "./semaphore.wasm"
102
+ })
103
+ ```
104
+
105
+ \# **verifyProof**(verificationKey: _any_, fullProof: _FullProof_): Promise\<_boolean_>
106
+
107
+ ```typescript
108
+ import { verifyProof } from "@semaphore-protocol/proof"
109
+
110
+ const verificationKey = JSON.parse(fs.readFileSync("/semaphore.json", "utf-8"))
111
+
112
+ await verifyProof(verificationKey, fullProof)
113
+ ```
114
+
115
+ \# **packToSolidityProof**(proof: _Proof_): _SolidityProof_
116
+
117
+ ```typescript
118
+ import { packToSolidityProof } from "@semaphore-protocol/proof"
119
+
120
+ const solidityProof = packToSolidityProof(fullProof.proof)
121
+ ```
122
+
123
+ \# **generateNullifierHash**(externalNullifier: _BigNumberish_, identityNullifier: _BigNumberish_): _bigint_
124
+
125
+ ```typescript
126
+ import { generateNullifierHash } from "@semaphore-protocol/proof"
127
+
128
+ const nullifierHash = generateNullifierHash(externalNullifier, identity.getNullifier())
129
+ ```
130
+
131
+ \# **generateSignalHash**(signal: _string_): _bigint_
132
+
133
+ ```typescript
134
+ import { generateSignalHash } from "@semaphore-protocol/proof"
84
135
 
85
- const { proof, publicSignals } = await Semaphore.genProof(witness, "./semaphore.wasm", "./semaphore.zkey")
86
- const solidityProof = Semaphore.packToSolidityProof(proof)
136
+ const signalHash = generateSignalHash(signal)
87
137
  ```
package/dist/index.mjs CHANGED
@@ -1,18 +1,66 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 0.1.0
3
+ * @version 0.2.0
4
4
  * @file A library for generating and verifying Semaphore proofs.
5
5
  * @copyright Ethereum Foundation 2022
6
6
  * @license MIT
7
7
  * @see [Github]{@link https://github.com/semaphore-protocol/semaphore.js/tree/main/packages/proof}
8
8
  */
9
- import { keccak256 } from '@ethersproject/solidity';
10
- import { formatBytes32String } from '@ethersproject/strings';
9
+ import { IncrementalMerkleTree } from '@zk-kit/incremental-merkle-tree';
11
10
  import { poseidon } from 'circomlibjs';
12
11
  import { groth16 } from 'snarkjs';
13
- import { IncrementalMerkleTree } from '@zk-kit/incremental-merkle-tree';
12
+ import { keccak256 } from '@ethersproject/solidity';
13
+ import { formatBytes32String } from '@ethersproject/strings';
14
+
15
+ /**
16
+ * Creates a Merkle tree.
17
+ * @param depth The depth of the tree.
18
+ * @param zeroValue The zero value of the tree.
19
+ * @param leaves The list of the leaves of the tree.
20
+ * @returns The Merkle tree.
21
+ */
22
+ function createMerkleTree(depth, zeroValue, leaves) {
23
+ var tree = new IncrementalMerkleTree(poseidon, depth, zeroValue, 2);
24
+ for (var _i = 0, leaves_1 = leaves; _i < leaves_1.length; _i++) {
25
+ var leaf = leaves_1[_i];
26
+ if (leaf === zeroValue) {
27
+ throw new Error("Leaves cannot have zero values");
28
+ }
29
+ tree.insert(BigInt(leaf));
30
+ }
31
+ return tree;
32
+ }
33
+
34
+ /**
35
+ * Creates a Merkle proof.
36
+ * @param depth The depth of the tree.
37
+ * @param zeroValue The zero value of the tree.
38
+ * @param leaves The list of the leaves of the tree.
39
+ * @param leaf The leaf for which Merkle proof should be created.
40
+ * @returns The Merkle proof.
41
+ */
42
+ function createMerkleProof(depth, zeroValue, leaves, leaf) {
43
+ var tree = createMerkleTree(depth, zeroValue, leaves);
44
+ var leafIndex = tree.leaves.indexOf(BigInt(leaf));
45
+ if (leafIndex === -1) {
46
+ throw new Error("The leaf does not exist");
47
+ }
48
+ var merkleProof = tree.createProof(leafIndex);
49
+ merkleProof.siblings = merkleProof.siblings.map(function (s) { return s[0]; });
50
+ return merkleProof;
51
+ }
14
52
 
15
- /*! *****************************************************************************
53
+ /**
54
+ * Generates a nullifier by hashing the external and the identity nullifiers.
55
+ * @param externalNullifier The external nullifier.
56
+ * @param identityNullifier The identity nullifier.
57
+ * @returns The nullifier hash.
58
+ */
59
+ function generateNullifierHash(externalNullifier, identityNullifier) {
60
+ return poseidon([BigInt(externalNullifier), BigInt(identityNullifier)]);
61
+ }
62
+
63
+ /******************************************************************************
16
64
  Copyright (c) Microsoft Corporation.
17
65
 
18
66
  Permission to use, copy, modify, and/or distribute this software for any
@@ -65,154 +113,76 @@ function __generator(thisArg, body) {
65
113
  }
66
114
  }
67
115
 
68
- var Semaphore = /** @class */ (function () {
69
- function Semaphore() {
70
- }
71
- /**
72
- * Generates a SnarkJS full proof with Groth16.
73
- * @param witness The parameters for creating the proof.
74
- * @param wasmFilePath The WASM file path.
75
- * @param finalZkeyPath The ZKey file path.
76
- * @returns The full SnarkJS proof.
77
- */
78
- /* istanbul ignore next */
79
- Semaphore.genProof = function (witness, wasmFilePath, finalZkeyPath) {
80
- return __awaiter(this, void 0, void 0, function () {
81
- var _a, proof, publicSignals;
82
- return __generator(this, function (_b) {
83
- switch (_b.label) {
84
- case 0: return [4 /*yield*/, groth16.fullProve(witness, wasmFilePath, finalZkeyPath, null)];
85
- case 1:
86
- _a = _b.sent(), proof = _a.proof, publicSignals = _a.publicSignals;
87
- return [2 /*return*/, {
88
- proof: proof,
89
- publicSignals: {
90
- merkleRoot: publicSignals[0],
91
- nullifierHash: publicSignals[1],
92
- signalHash: publicSignals[2],
93
- externalNullifier: publicSignals[3]
94
- }
95
- }];
96
- }
97
- });
116
+ /**
117
+ * Hashes a signal string with Keccak256.
118
+ * @param signal The Semaphore signal.
119
+ * @returns The signal hash.
120
+ */
121
+ function genSignalHash(signal) {
122
+ return BigInt(keccak256(["bytes32"], [formatBytes32String(signal)])) >> BigInt(8);
123
+ }
124
+
125
+ function generateProof(identity, merkleProof, externalNullifier, signal, snarkArtifacts) {
126
+ return __awaiter(this, void 0, void 0, function () {
127
+ var _a, proof, publicSignals;
128
+ return __generator(this, function (_b) {
129
+ switch (_b.label) {
130
+ case 0: return [4 /*yield*/, groth16.fullProve({
131
+ identityTrapdoor: identity.getTrapdoor(),
132
+ identityNullifier: identity.getNullifier(),
133
+ treePathIndices: merkleProof.pathIndices,
134
+ treeSiblings: merkleProof.siblings,
135
+ externalNullifier: externalNullifier,
136
+ signalHash: genSignalHash(signal)
137
+ }, snarkArtifacts.wasmFilePath, snarkArtifacts.zkeyFilePath)];
138
+ case 1:
139
+ _a = _b.sent(), proof = _a.proof, publicSignals = _a.publicSignals;
140
+ return [2 /*return*/, {
141
+ proof: proof,
142
+ publicSignals: {
143
+ merkleRoot: publicSignals[0],
144
+ nullifierHash: publicSignals[1],
145
+ signalHash: publicSignals[2],
146
+ externalNullifier: publicSignals[3]
147
+ }
148
+ }];
149
+ }
98
150
  });
99
- };
100
- /**
101
- * Verifies a zero-knowledge SnarkJS proof.
102
- * @param verificationKey The zero-knowledge verification key.
103
- * @param fullProof The SnarkJS full proof.
104
- * @returns True if the proof is valid, false otherwise.
105
- */
106
- /* istanbul ignore next */
107
- Semaphore.verifyProof = function (verificationKey, _a) {
108
- var proof = _a.proof, publicSignals = _a.publicSignals;
109
- return groth16.verify(verificationKey, [
110
- publicSignals.merkleRoot,
111
- publicSignals.nullifierHash,
112
- publicSignals.signalHash,
113
- publicSignals.externalNullifier
114
- ], proof);
115
- };
116
- /**
117
- * Creates a Semaphore witness for the Semaphore ZK proof.
118
- * @param identityTrapdoor The identity trapdoor.
119
- * @param identityNullifier The identity nullifier.
120
- * @param merkleProof The Merkle proof that identity exists in Semaphore tree.
121
- * @param externalNullifier The topic on which vote should be broadcasted.
122
- * @param signal The signal that should be broadcasted.
123
- * @returns The Semaphore witness.
124
- */
125
- Semaphore.genWitness = function (identityTrapdoor, identityNullifier, merkleProof, externalNullifier, signal) {
126
- return {
127
- identityNullifier: identityNullifier,
128
- identityTrapdoor: identityTrapdoor,
129
- treePathIndices: merkleProof.pathIndices,
130
- treeSiblings: merkleProof.siblings,
131
- externalNullifier: externalNullifier,
132
- signalHash: Semaphore.genSignalHash(signal)
133
- };
134
- };
135
- /**
136
- * Generates a nullifier by hashing the external and the identity nullifiers.
137
- * @param externalNullifier The external nullifier.
138
- * @param identityNullifier The identity nullifier.
139
- * @returns The nullifier hash.
140
- */
141
- Semaphore.genNullifierHash = function (externalNullifier, identityNullifier) {
142
- return poseidon([BigInt(externalNullifier), BigInt(identityNullifier)]);
143
- };
144
- /**
145
- * Hashes a signal string with Keccak256.
146
- * @param signal The Semaphore signal.
147
- * @returns The signal hash.
148
- */
149
- Semaphore.genSignalHash = function (signal) {
150
- return BigInt(keccak256(["bytes32"], [formatBytes32String(signal)])) >> BigInt(8);
151
- };
152
- /**
153
- * Converts a full proof in a proof compatible with the Verifier.sol method inputs.
154
- * @param proof The proof generated with SnarkJS.
155
- * @returns The Solidity compatible proof.
156
- */
157
- /* istanbul ignore next */
158
- Semaphore.packToSolidityProof = function (proof) {
159
- return [
160
- proof.pi_a[0],
161
- proof.pi_a[1],
162
- proof.pi_b[0][1],
163
- proof.pi_b[0][0],
164
- proof.pi_b[1][1],
165
- proof.pi_b[1][0],
166
- proof.pi_c[0],
167
- proof.pi_c[1]
168
- ];
169
- };
170
- return Semaphore;
171
- }());
151
+ });
152
+ }
172
153
 
173
- BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
174
- function genExternalNullifier(plaintext) {
175
- var hashed = keccak256(["string"], [plaintext]);
176
- var hexStr = "0x".concat(hashed.slice(8));
177
- var len = 32 * 2;
178
- var h = hexStr.slice(2, len + 2);
179
- return "0x".concat(h.padStart(len, "0"));
180
- }
181
154
  /**
182
- * Creates a Merkle tree.
183
- * @param depth The depth of the tree.
184
- * @param zeroValue The zero value of the tree.
185
- * @param leaves The list of the leaves of the tree.
186
- * @returns The Merkle tree.
155
+ * Verifies a SnarkJS proof.
156
+ * @param verificationKey The zero-knowledge verification key.
157
+ * @param fullProof The SnarkJS full proof.
158
+ * @returns True if the proof is valid, false otherwise.
187
159
  */
188
- function generateMerkleTree(depth, zeroValue, leaves) {
189
- var tree = new IncrementalMerkleTree(poseidon, depth, zeroValue, 2);
190
- for (var _i = 0, leaves_1 = leaves; _i < leaves_1.length; _i++) {
191
- var leaf = leaves_1[_i];
192
- tree.insert(BigInt(leaf));
193
- }
194
- return tree;
195
- }
160
+ function verifyProof(verificationKey, _a) {
161
+ var proof = _a.proof, publicSignals = _a.publicSignals;
162
+ return groth16.verify(verificationKey, [
163
+ publicSignals.merkleRoot,
164
+ publicSignals.nullifierHash,
165
+ publicSignals.signalHash,
166
+ publicSignals.externalNullifier
167
+ ], proof);
168
+ }
169
+
196
170
  /**
197
- * Creates a Merkle proof.
198
- * @param depth The depth of the tree.
199
- * @param zeroValue The zero value of the tree.
200
- * @param leaves The list of the leaves of the tree.
201
- * @param leaf The leaf for which Merkle proof should be created.
202
- * @returns The Merkle proof.
171
+ * Makes a proof compatible with the Verifier.sol method inputs.
172
+ * @param proof The proof generated with SnarkJS.
173
+ * @returns The Solidity compatible proof.
203
174
  */
204
- function generateMerkleProof(depth, zeroValue, leaves, leaf) {
205
- if (leaf === zeroValue) {
206
- throw new Error("Can't generate a proof for a zero leaf");
207
- }
208
- var tree = generateMerkleTree(depth, zeroValue, leaves);
209
- var leafIndex = tree.leaves.indexOf(BigInt(leaf));
210
- if (leafIndex === -1) {
211
- throw new Error("The leaf does not exist");
212
- }
213
- var merkleProof = tree.createProof(leafIndex);
214
- merkleProof.siblings = merkleProof.siblings.map(function (s) { return s[0]; });
215
- return merkleProof;
175
+ function packToSolidityProof(proof) {
176
+ return [
177
+ proof.pi_a[0],
178
+ proof.pi_a[1],
179
+ proof.pi_b[0][1],
180
+ proof.pi_b[0][0],
181
+ proof.pi_b[1][1],
182
+ proof.pi_b[1][0],
183
+ proof.pi_c[0],
184
+ proof.pi_c[1]
185
+ ];
216
186
  }
217
187
 
218
- export { Semaphore, genExternalNullifier, generateMerkleProof, generateMerkleTree };
188
+ export { createMerkleProof, createMerkleTree, generateNullifierHash, generateProof, genSignalHash as generateSignalHash, packToSolidityProof, verifyProof };