@semaphore-protocol/proof 4.0.0-alpha → 4.0.0-alpha.2

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
@@ -10,7 +10,7 @@
10
10
  <img src="https://img.shields.io/badge/project-Semaphore-blue.svg?style=flat-square">
11
11
  </a>
12
12
  <a href="https://github.com/semaphore-protocol/semaphore/blob/main/LICENSE">
13
- <img alt="Github license" src="https://img.shields.io/github/license/semaphore-protocol/semaphore.svg?style=flat-square">
13
+ <img alt="NPM license" src="https://img.shields.io/npm/l/%40semaphore-protocol%2Fproof?style=flat-square">
14
14
  </a>
15
15
  <a href="https://www.npmjs.com/package/@semaphore-protocol/proof">
16
16
  <img alt="NPM version" src="https://img.shields.io/npm/v/@semaphore-protocol/proof?style=flat-square" />
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-alpha
3
+ * @version 4.0.0-alpha.2
4
4
  * @file A library to generate and verify Semaphore proofs.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
7
7
  * @see [Github]{@link https://github.com/semaphore-protocol/semaphore/tree/main/packages/proof}
8
8
  */
9
9
  import { BigNumber } from '@ethersproject/bignumber';
10
- import { prove, verify } from '@zk-kit/groth16';
10
+ import { groth16 } from 'snarkjs';
11
11
  import { zeroPad } from '@ethersproject/bytes';
12
12
  import { keccak256 } from '@ethersproject/keccak256';
13
13
 
@@ -100,11 +100,11 @@ function hash(message) {
100
100
  }
101
101
 
102
102
  /**
103
- * Packs a proof into a format compatible with Semaphore.
104
- * @param proof The Groth16 proof generated with SnarkJS.
105
- * @returns The proof compatible with Semaphore.
103
+ * Packs the Groth16 proof points into a format compatible with Semaphore.
104
+ * @param proof The proof points generated with SnarkJS.
105
+ * @returns The proof points compatible with Semaphore.
106
106
  */
107
- function packProof(proof) {
107
+ function packPoints(proof) {
108
108
  return [
109
109
  proof.pi_a[0],
110
110
  proof.pi_a[1],
@@ -120,21 +120,26 @@ function packProof(proof) {
120
120
  /**
121
121
  * Generates a Semaphore proof.
122
122
  * @param identity The Semaphore identity.
123
- * @param group The Semaphore group or its Merkle proof.
123
+ * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
124
124
  * @param scope The external nullifier.
125
125
  * @param message The Semaphore signal.
126
126
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
127
127
  * @param snarkArtifacts The SNARK artifacts.
128
128
  * @returns The Semaphore proof ready to be verified.
129
129
  */
130
- function generateProof(identity, group, message, scope, merkleTreeDepth, snarkArtifacts) {
130
+ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
131
131
  return __awaiter(this, void 0, void 0, function () {
132
- var leafIndex, merkleProof, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
132
+ var merkleProof, leafIndex, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
133
133
  return __generator(this, function (_b) {
134
134
  switch (_b.label) {
135
135
  case 0:
136
- leafIndex = group.indexOf(identity.commitment);
137
- merkleProof = group.generateMerkleProof(leafIndex);
136
+ if ("siblings" in groupOrMerkleProof) {
137
+ merkleProof = groupOrMerkleProof;
138
+ }
139
+ else {
140
+ leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
141
+ merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
142
+ }
138
143
  merkleProofLength = merkleProof.siblings.length;
139
144
  if (merkleTreeDepth !== undefined) {
140
145
  if (merkleTreeDepth < 1 || merkleTreeDepth > 12) {
@@ -158,7 +163,7 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
158
163
  merkleProofSiblings[i] = "0";
159
164
  }
160
165
  }
161
- return [4 /*yield*/, prove({
166
+ return [4 /*yield*/, groth16.fullProve({
162
167
  secret: identity.secretScalar,
163
168
  merkleProofLength: merkleProofLength,
164
169
  merkleProofIndices: merkleProofIndices,
@@ -174,7 +179,7 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
174
179
  nullifier: publicSignals[1],
175
180
  message: BigNumber.from(message).toString(),
176
181
  scope: BigNumber.from(scope).toString(),
177
- proof: packProof(proof)
182
+ points: packPoints(proof)
178
183
  }];
179
184
  }
180
185
  });
@@ -182,11 +187,11 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
182
187
  }
183
188
 
184
189
  /**
185
- * Unpacks a proof into its original form.
186
- * @param proof The proof compatible with Semaphore.
187
- * @returns The proof compatible with SnarkJS.
190
+ * Unpacks the Groth16 proof points into their original form.
191
+ * @param proof The proof points compatible with Semaphore.
192
+ * @returns The proof points compatible with SnarkJS.
188
193
  */
189
- function unpackProof(proof) {
194
+ function unpackPoints(proof) {
190
195
  return {
191
196
  pi_a: [proof[0], proof[1]],
192
197
  pi_b: [
@@ -780,7 +785,7 @@ var verificationKeys = {
780
785
  * @returns True if the proof is valid, false otherwise.
781
786
  */
782
787
  function verifyProof(_a) {
783
- var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, proof = _a.proof;
788
+ var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, points = _a.points;
784
789
  return __awaiter(this, void 0, void 0, function () {
785
790
  var verificationKey;
786
791
  return __generator(this, function (_b) {
@@ -789,12 +794,9 @@ function verifyProof(_a) {
789
794
  throw new TypeError("The tree depth must be a number between 1 and 12");
790
795
  }
791
796
  verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
792
- return [2 /*return*/, verify(verificationKey, {
793
- publicSignals: [merkleTreeRoot, nullifier, hash(message), hash(scope)],
794
- proof: unpackProof(proof)
795
- })];
797
+ return [2 /*return*/, groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackPoints(points))];
796
798
  });
797
799
  });
798
800
  }
799
801
 
800
- export { generateProof, getSnarkArtifacts, packProof, unpackProof, verifyProof };
802
+ export { generateProof, getSnarkArtifacts, packPoints, unpackPoints, verifyProof };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-alpha
3
+ * @version 4.0.0-alpha.2
4
4
  * @file A library to generate and verify Semaphore proofs.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
@@ -9,7 +9,7 @@
9
9
  'use strict';
10
10
 
11
11
  var bignumber = require('@ethersproject/bignumber');
12
- var groth16 = require('@zk-kit/groth16');
12
+ var snarkjs = require('snarkjs');
13
13
  var download = require('download');
14
14
  var fs = require('fs');
15
15
  var tmp = require('tmp');
@@ -90,10 +90,7 @@ function getSnarkArtifacts(treeDepth) {
90
90
  case 0:
91
91
  tmpDir = "semaphore-proof";
92
92
  tmpPath = "".concat(tmp.tmpdir, "/").concat(tmpDir, "-").concat(treeDepth);
93
- if (!fs.existsSync(tmpPath)) {
94
- tmp.dirSync({ name: "".concat(tmpDir, "-").concat(treeDepth) });
95
- }
96
- if (!(fs.readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
93
+ if (!(!fs.existsSync(tmpPath) || fs.readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
97
94
  return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"), tmpPath)];
98
95
  case 1:
99
96
  _a.sent();
@@ -122,11 +119,11 @@ function hash(message) {
122
119
  }
123
120
 
124
121
  /**
125
- * Packs a proof into a format compatible with Semaphore.
126
- * @param proof The Groth16 proof generated with SnarkJS.
127
- * @returns The proof compatible with Semaphore.
122
+ * Packs the Groth16 proof points into a format compatible with Semaphore.
123
+ * @param proof The proof points generated with SnarkJS.
124
+ * @returns The proof points compatible with Semaphore.
128
125
  */
129
- function packProof(proof) {
126
+ function packPoints(proof) {
130
127
  return [
131
128
  proof.pi_a[0],
132
129
  proof.pi_a[1],
@@ -142,21 +139,26 @@ function packProof(proof) {
142
139
  /**
143
140
  * Generates a Semaphore proof.
144
141
  * @param identity The Semaphore identity.
145
- * @param group The Semaphore group or its Merkle proof.
142
+ * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
146
143
  * @param scope The external nullifier.
147
144
  * @param message The Semaphore signal.
148
145
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
149
146
  * @param snarkArtifacts The SNARK artifacts.
150
147
  * @returns The Semaphore proof ready to be verified.
151
148
  */
152
- function generateProof(identity, group, message, scope, merkleTreeDepth, snarkArtifacts) {
149
+ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
153
150
  return __awaiter(this, void 0, void 0, function () {
154
- var leafIndex, merkleProof, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
151
+ var merkleProof, leafIndex, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
155
152
  return __generator(this, function (_b) {
156
153
  switch (_b.label) {
157
154
  case 0:
158
- leafIndex = group.indexOf(identity.commitment);
159
- merkleProof = group.generateMerkleProof(leafIndex);
155
+ if ("siblings" in groupOrMerkleProof) {
156
+ merkleProof = groupOrMerkleProof;
157
+ }
158
+ else {
159
+ leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
160
+ merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
161
+ }
160
162
  merkleProofLength = merkleProof.siblings.length;
161
163
  if (merkleTreeDepth !== undefined) {
162
164
  if (merkleTreeDepth < 1 || merkleTreeDepth > 12) {
@@ -180,7 +182,7 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
180
182
  merkleProofSiblings[i] = "0";
181
183
  }
182
184
  }
183
- return [4 /*yield*/, groth16.prove({
185
+ return [4 /*yield*/, snarkjs.groth16.fullProve({
184
186
  secret: identity.secretScalar,
185
187
  merkleProofLength: merkleProofLength,
186
188
  merkleProofIndices: merkleProofIndices,
@@ -196,7 +198,7 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
196
198
  nullifier: publicSignals[1],
197
199
  message: bignumber.BigNumber.from(message).toString(),
198
200
  scope: bignumber.BigNumber.from(scope).toString(),
199
- proof: packProof(proof)
201
+ points: packPoints(proof)
200
202
  }];
201
203
  }
202
204
  });
@@ -204,11 +206,11 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
204
206
  }
205
207
 
206
208
  /**
207
- * Unpacks a proof into its original form.
208
- * @param proof The proof compatible with Semaphore.
209
- * @returns The proof compatible with SnarkJS.
209
+ * Unpacks the Groth16 proof points into their original form.
210
+ * @param proof The proof points compatible with Semaphore.
211
+ * @returns The proof points compatible with SnarkJS.
210
212
  */
211
- function unpackProof(proof) {
213
+ function unpackPoints(proof) {
212
214
  return {
213
215
  pi_a: [proof[0], proof[1]],
214
216
  pi_b: [
@@ -802,7 +804,7 @@ var verificationKeys = {
802
804
  * @returns True if the proof is valid, false otherwise.
803
805
  */
804
806
  function verifyProof(_a) {
805
- var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, proof = _a.proof;
807
+ var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, points = _a.points;
806
808
  return __awaiter(this, void 0, void 0, function () {
807
809
  var verificationKey;
808
810
  return __generator(this, function (_b) {
@@ -811,16 +813,13 @@ function verifyProof(_a) {
811
813
  throw new TypeError("The tree depth must be a number between 1 and 12");
812
814
  }
813
815
  verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
814
- return [2 /*return*/, groth16.verify(verificationKey, {
815
- publicSignals: [merkleTreeRoot, nullifier, hash(message), hash(scope)],
816
- proof: unpackProof(proof)
817
- })];
816
+ return [2 /*return*/, snarkjs.groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackPoints(points))];
818
817
  });
819
818
  });
820
819
  }
821
820
 
822
821
  exports.generateProof = generateProof;
823
822
  exports.getSnarkArtifacts = getSnarkArtifacts;
824
- exports.packProof = packProof;
825
- exports.unpackProof = unpackProof;
823
+ exports.packPoints = packPoints;
824
+ exports.unpackPoints = unpackPoints;
826
825
  exports.verifyProof = verifyProof;
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-alpha
3
+ * @version 4.0.0-alpha.2
4
4
  * @file A library to generate and verify Semaphore proofs.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
7
7
  * @see [Github]{@link https://github.com/semaphore-protocol/semaphore/tree/main/packages/proof}
8
8
  */
9
9
  import { BigNumber } from '@ethersproject/bignumber';
10
- import { prove, verify } from '@zk-kit/groth16';
10
+ import { groth16 } from 'snarkjs';
11
11
  import download from 'download';
12
12
  import fs from 'fs';
13
13
  import tmp from 'tmp';
@@ -88,10 +88,7 @@ function getSnarkArtifacts(treeDepth) {
88
88
  case 0:
89
89
  tmpDir = "semaphore-proof";
90
90
  tmpPath = "".concat(tmp.tmpdir, "/").concat(tmpDir, "-").concat(treeDepth);
91
- if (!fs.existsSync(tmpPath)) {
92
- tmp.dirSync({ name: "".concat(tmpDir, "-").concat(treeDepth) });
93
- }
94
- if (!(fs.readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
91
+ if (!(!fs.existsSync(tmpPath) || fs.readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
95
92
  return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"), tmpPath)];
96
93
  case 1:
97
94
  _a.sent();
@@ -120,11 +117,11 @@ function hash(message) {
120
117
  }
121
118
 
122
119
  /**
123
- * Packs a proof into a format compatible with Semaphore.
124
- * @param proof The Groth16 proof generated with SnarkJS.
125
- * @returns The proof compatible with Semaphore.
120
+ * Packs the Groth16 proof points into a format compatible with Semaphore.
121
+ * @param proof The proof points generated with SnarkJS.
122
+ * @returns The proof points compatible with Semaphore.
126
123
  */
127
- function packProof(proof) {
124
+ function packPoints(proof) {
128
125
  return [
129
126
  proof.pi_a[0],
130
127
  proof.pi_a[1],
@@ -140,21 +137,26 @@ function packProof(proof) {
140
137
  /**
141
138
  * Generates a Semaphore proof.
142
139
  * @param identity The Semaphore identity.
143
- * @param group The Semaphore group or its Merkle proof.
140
+ * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
144
141
  * @param scope The external nullifier.
145
142
  * @param message The Semaphore signal.
146
143
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
147
144
  * @param snarkArtifacts The SNARK artifacts.
148
145
  * @returns The Semaphore proof ready to be verified.
149
146
  */
150
- function generateProof(identity, group, message, scope, merkleTreeDepth, snarkArtifacts) {
147
+ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
151
148
  return __awaiter(this, void 0, void 0, function () {
152
- var leafIndex, merkleProof, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
149
+ var merkleProof, leafIndex, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
153
150
  return __generator(this, function (_b) {
154
151
  switch (_b.label) {
155
152
  case 0:
156
- leafIndex = group.indexOf(identity.commitment);
157
- merkleProof = group.generateMerkleProof(leafIndex);
153
+ if ("siblings" in groupOrMerkleProof) {
154
+ merkleProof = groupOrMerkleProof;
155
+ }
156
+ else {
157
+ leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
158
+ merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
159
+ }
158
160
  merkleProofLength = merkleProof.siblings.length;
159
161
  if (merkleTreeDepth !== undefined) {
160
162
  if (merkleTreeDepth < 1 || merkleTreeDepth > 12) {
@@ -178,7 +180,7 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
178
180
  merkleProofSiblings[i] = "0";
179
181
  }
180
182
  }
181
- return [4 /*yield*/, prove({
183
+ return [4 /*yield*/, groth16.fullProve({
182
184
  secret: identity.secretScalar,
183
185
  merkleProofLength: merkleProofLength,
184
186
  merkleProofIndices: merkleProofIndices,
@@ -194,7 +196,7 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
194
196
  nullifier: publicSignals[1],
195
197
  message: BigNumber.from(message).toString(),
196
198
  scope: BigNumber.from(scope).toString(),
197
- proof: packProof(proof)
199
+ points: packPoints(proof)
198
200
  }];
199
201
  }
200
202
  });
@@ -202,11 +204,11 @@ function generateProof(identity, group, message, scope, merkleTreeDepth, snarkAr
202
204
  }
203
205
 
204
206
  /**
205
- * Unpacks a proof into its original form.
206
- * @param proof The proof compatible with Semaphore.
207
- * @returns The proof compatible with SnarkJS.
207
+ * Unpacks the Groth16 proof points into their original form.
208
+ * @param proof The proof points compatible with Semaphore.
209
+ * @returns The proof points compatible with SnarkJS.
208
210
  */
209
- function unpackProof(proof) {
211
+ function unpackPoints(proof) {
210
212
  return {
211
213
  pi_a: [proof[0], proof[1]],
212
214
  pi_b: [
@@ -800,7 +802,7 @@ var verificationKeys = {
800
802
  * @returns True if the proof is valid, false otherwise.
801
803
  */
802
804
  function verifyProof(_a) {
803
- var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, proof = _a.proof;
805
+ var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, points = _a.points;
804
806
  return __awaiter(this, void 0, void 0, function () {
805
807
  var verificationKey;
806
808
  return __generator(this, function (_b) {
@@ -809,12 +811,9 @@ function verifyProof(_a) {
809
811
  throw new TypeError("The tree depth must be a number between 1 and 12");
810
812
  }
811
813
  verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
812
- return [2 /*return*/, verify(verificationKey, {
813
- publicSignals: [merkleTreeRoot, nullifier, hash(message), hash(scope)],
814
- proof: unpackProof(proof)
815
- })];
814
+ return [2 /*return*/, groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackPoints(points))];
816
815
  });
817
816
  });
818
817
  }
819
818
 
820
- export { generateProof, getSnarkArtifacts, packProof, unpackProof, verifyProof };
819
+ export { generateProof, getSnarkArtifacts, packPoints, unpackPoints, verifyProof };
@@ -1,15 +1,15 @@
1
1
  import { BytesLike, Hexable } from "@ethersproject/bytes";
2
- import { Group } from "@semaphore-protocol/group";
2
+ import type { Group, MerkleProof } from "@semaphore-protocol/group";
3
3
  import type { Identity } from "@semaphore-protocol/identity";
4
4
  import { SemaphoreProof, SnarkArtifacts } from "./types";
5
5
  /**
6
6
  * Generates a Semaphore proof.
7
7
  * @param identity The Semaphore identity.
8
- * @param group The Semaphore group or its Merkle proof.
8
+ * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
9
9
  * @param scope The external nullifier.
10
10
  * @param message The Semaphore signal.
11
11
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
12
12
  * @param snarkArtifacts The SNARK artifacts.
13
13
  * @returns The Semaphore proof ready to be verified.
14
14
  */
15
- export default function generateProof(identity: Identity, group: Group, message: BytesLike | Hexable | number | bigint, scope: BytesLike | Hexable | number | bigint, merkleTreeDepth?: number, snarkArtifacts?: SnarkArtifacts): Promise<SemaphoreProof>;
15
+ export default function generateProof(identity: Identity, groupOrMerkleProof: Group | MerkleProof, message: BytesLike | Hexable | number | bigint, scope: BytesLike | Hexable | number | bigint, merkleTreeDepth?: number, snarkArtifacts?: SnarkArtifacts): Promise<SemaphoreProof>;
@@ -1,5 +1,5 @@
1
1
  import { BytesLike, Hexable } from "@ethersproject/bytes";
2
- import { NumericString } from "@zk-kit/groth16";
2
+ import { NumericString } from "snarkjs";
3
3
  /**
4
4
  * Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
5
5
  * @param message The message to be hashed.
@@ -1,7 +1,7 @@
1
1
  import generateProof from "./generate-proof";
2
2
  import getSnarkArtifacts from "./get-snark-artifacts.node";
3
- import packProof from "./pack-proof";
4
- import unpackProof from "./unpack-proof";
3
+ import packPoints from "./pack-points";
4
+ import unpackPoints from "./unpack-points";
5
5
  import verifyProof from "./verify-proof";
6
6
  export * from "./types";
7
- export { generateProof, getSnarkArtifacts, packProof, unpackProof, verifyProof };
7
+ export { generateProof, getSnarkArtifacts, packPoints, unpackPoints, verifyProof };
@@ -0,0 +1,8 @@
1
+ import { Groth16Proof } from "snarkjs";
2
+ import { PackedPoints } from "./types";
3
+ /**
4
+ * Packs the Groth16 proof points into a format compatible with Semaphore.
5
+ * @param proof The proof points generated with SnarkJS.
6
+ * @returns The proof points compatible with Semaphore.
7
+ */
8
+ export default function packPoints(proof: Groth16Proof): PackedPoints;
@@ -1,4 +1,4 @@
1
- import type { NumericString } from "@zk-kit/groth16";
1
+ import type { NumericString } from "snarkjs";
2
2
  export type BigNumberish = string | number | bigint;
3
3
  export type SnarkArtifacts = {
4
4
  wasmFilePath: string;
@@ -10,9 +10,9 @@ export type SemaphoreProof = {
10
10
  message: NumericString;
11
11
  nullifier: NumericString;
12
12
  scope: NumericString;
13
- proof: PackedProof;
13
+ points: PackedPoints;
14
14
  };
15
- export type PackedProof = [
15
+ export type PackedPoints = [
16
16
  NumericString,
17
17
  NumericString,
18
18
  NumericString,
@@ -0,0 +1,8 @@
1
+ import { Groth16Proof } from "snarkjs";
2
+ import { PackedPoints } from "./types";
3
+ /**
4
+ * Unpacks the Groth16 proof points into their original form.
5
+ * @param proof The proof points compatible with Semaphore.
6
+ * @returns The proof points compatible with SnarkJS.
7
+ */
8
+ export default function unpackPoints(proof: PackedPoints): Groth16Proof;
@@ -5,4 +5,4 @@ import { SemaphoreProof } from "./types";
5
5
  * @param treeDepth The depth of the tree.
6
6
  * @returns True if the proof is valid, false otherwise.
7
7
  */
8
- export default function verifyProof({ merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, proof }: SemaphoreProof): Promise<boolean>;
8
+ export default function verifyProof({ merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points }: SemaphoreProof): Promise<boolean>;
package/package.json CHANGED
@@ -1,17 +1,20 @@
1
1
  {
2
2
  "name": "@semaphore-protocol/proof",
3
- "version": "4.0.0-alpha",
3
+ "version": "4.0.0-alpha.2",
4
4
  "description": "A library to generate and verify Semaphore proofs.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.node.js",
7
+ "browser": "dist/index.browser.mjs",
7
8
  "exports": {
8
- "node": {
9
- "import": "./dist/index.node.mjs",
10
- "require": "./dist/index.node.js"
11
- },
12
- "browser": "./dist/index.browser.mjs",
13
- "default": "./dist/index.browser.mjs",
14
- "types": "./dist/types/index.d.ts"
9
+ ".": {
10
+ "node": {
11
+ "import": "./dist/index.node.mjs",
12
+ "require": "./dist/index.node.js"
13
+ },
14
+ "browser": "./dist/index.browser.mjs",
15
+ "default": "./dist/index.browser.mjs",
16
+ "types": "./dist/types/index.d.ts"
17
+ }
15
18
  },
16
19
  "types": "dist/types/index.d.ts",
17
20
  "files": [
@@ -47,15 +50,16 @@
47
50
  "rollup-plugin-typescript2": "^0.31.2"
48
51
  },
49
52
  "peerDependencies": {
50
- "@semaphore-protocol/group": "4.0.0-alpha",
51
- "@semaphore-protocol/identity": "4.0.0-alpha"
53
+ "@semaphore-protocol/group": "4.0.0-alpha.2",
54
+ "@semaphore-protocol/identity": "4.0.0-alpha.2"
52
55
  },
53
56
  "dependencies": {
54
- "@ethersproject/bignumber": "^5.7.0",
55
- "@ethersproject/bytes": "^5.7.0",
56
- "@ethersproject/keccak256": "^5.7.0",
57
- "@zk-kit/groth16": "0.5.0",
58
- "download": "^8.0.0",
59
- "tmp": "^0.2.1"
57
+ "@ethersproject/bignumber": "5.7.0",
58
+ "@ethersproject/bytes": "5.7.0",
59
+ "@ethersproject/keccak256": "5.7.0",
60
+ "@types/snarkjs": "0.7.8",
61
+ "download": "8.0.0",
62
+ "snarkjs": "0.7.3",
63
+ "tmp": "0.2.1"
60
64
  }
61
65
  }
@@ -1,17 +1,17 @@
1
1
  import { BigNumber } from "@ethersproject/bignumber"
2
2
  import { BytesLike, Hexable } from "@ethersproject/bytes"
3
- import { Group } from "@semaphore-protocol/group"
3
+ import type { Group, MerkleProof } from "@semaphore-protocol/group"
4
4
  import type { Identity } from "@semaphore-protocol/identity"
5
- import { NumericString, prove } from "@zk-kit/groth16"
5
+ import { NumericString, groth16 } from "snarkjs"
6
6
  import getSnarkArtifacts from "./get-snark-artifacts.node"
7
7
  import hash from "./hash"
8
- import packProof from "./pack-proof"
8
+ import packPoints from "./pack-points"
9
9
  import { SemaphoreProof, SnarkArtifacts } from "./types"
10
10
 
11
11
  /**
12
12
  * Generates a Semaphore proof.
13
13
  * @param identity The Semaphore identity.
14
- * @param group The Semaphore group or its Merkle proof.
14
+ * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
15
15
  * @param scope The external nullifier.
16
16
  * @param message The Semaphore signal.
17
17
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
@@ -20,14 +20,21 @@ import { SemaphoreProof, SnarkArtifacts } from "./types"
20
20
  */
21
21
  export default async function generateProof(
22
22
  identity: Identity,
23
- group: Group,
23
+ groupOrMerkleProof: Group | MerkleProof,
24
24
  message: BytesLike | Hexable | number | bigint,
25
25
  scope: BytesLike | Hexable | number | bigint,
26
26
  merkleTreeDepth?: number,
27
27
  snarkArtifacts?: SnarkArtifacts
28
28
  ): Promise<SemaphoreProof> {
29
- const leafIndex = group.indexOf(identity.commitment)
30
- const merkleProof = group.generateMerkleProof(leafIndex)
29
+ let merkleProof
30
+
31
+ if ("siblings" in groupOrMerkleProof) {
32
+ merkleProof = groupOrMerkleProof
33
+ } else {
34
+ const leafIndex = groupOrMerkleProof.indexOf(identity.commitment)
35
+ merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex)
36
+ }
37
+
31
38
  const merkleProofLength = merkleProof.siblings.length
32
39
 
33
40
  if (merkleTreeDepth !== undefined) {
@@ -57,7 +64,7 @@ export default async function generateProof(
57
64
  }
58
65
  }
59
66
 
60
- const { proof, publicSignals } = await prove(
67
+ const { proof, publicSignals } = await groth16.fullProve(
61
68
  {
62
69
  secret: identity.secretScalar,
63
70
  merkleProofLength,
@@ -76,6 +83,6 @@ export default async function generateProof(
76
83
  nullifier: publicSignals[1],
77
84
  message: BigNumber.from(message).toString() as NumericString,
78
85
  scope: BigNumber.from(scope).toString() as NumericString,
79
- proof: packProof(proof)
86
+ points: packPoints(proof)
80
87
  }
81
88
  }
@@ -8,11 +8,7 @@ export default async function getSnarkArtifacts(treeDepth: number): Promise<Snar
8
8
  const tmpDir = "semaphore-proof"
9
9
  const tmpPath = `${tmp.tmpdir}/${tmpDir}-${treeDepth}`
10
10
 
11
- if (!fs.existsSync(tmpPath)) {
12
- tmp.dirSync({ name: `${tmpDir}-${treeDepth}` })
13
- }
14
-
15
- if (fs.readdirSync(tmpPath).length !== 2) {
11
+ if (!fs.existsSync(tmpPath) || fs.readdirSync(tmpPath).length !== 2) {
16
12
  await download(`https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.wasm`, tmpPath)
17
13
  await download(`https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.zkey`, tmpPath)
18
14
  }
package/src/hash.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { BigNumber } from "@ethersproject/bignumber"
2
2
  import { BytesLike, Hexable, zeroPad } from "@ethersproject/bytes"
3
3
  import { keccak256 } from "@ethersproject/keccak256"
4
- import { NumericString } from "@zk-kit/groth16"
4
+ import { NumericString } from "snarkjs"
5
5
 
6
6
  /**
7
7
  * Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
package/src/index.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import generateProof from "./generate-proof"
2
2
  import getSnarkArtifacts from "./get-snark-artifacts.node"
3
- import packProof from "./pack-proof"
4
- import unpackProof from "./unpack-proof"
3
+ import packPoints from "./pack-points"
4
+ import unpackPoints from "./unpack-points"
5
5
  import verifyProof from "./verify-proof"
6
6
 
7
7
  export * from "./types"
8
- export { generateProof, getSnarkArtifacts, packProof, unpackProof, verifyProof }
8
+ export { generateProof, getSnarkArtifacts, packPoints, unpackPoints, verifyProof }
@@ -0,0 +1,20 @@
1
+ import { Groth16Proof } from "snarkjs"
2
+ import { PackedPoints } from "./types"
3
+
4
+ /**
5
+ * Packs the Groth16 proof points into a format compatible with Semaphore.
6
+ * @param proof The proof points generated with SnarkJS.
7
+ * @returns The proof points compatible with Semaphore.
8
+ */
9
+ export default function packPoints(proof: Groth16Proof): PackedPoints {
10
+ return [
11
+ proof.pi_a[0],
12
+ proof.pi_a[1],
13
+ proof.pi_b[0][1],
14
+ proof.pi_b[0][0],
15
+ proof.pi_b[1][1],
16
+ proof.pi_b[1][0],
17
+ proof.pi_c[0],
18
+ proof.pi_c[1]
19
+ ]
20
+ }
@@ -1,4 +1,4 @@
1
- import type { NumericString } from "@zk-kit/groth16"
1
+ import type { NumericString } from "snarkjs"
2
2
 
3
3
  export type BigNumberish = string | number | bigint
4
4
 
@@ -13,10 +13,10 @@ export type SemaphoreProof = {
13
13
  message: NumericString
14
14
  nullifier: NumericString
15
15
  scope: NumericString
16
- proof: PackedProof
16
+ points: PackedPoints
17
17
  }
18
18
 
19
- export type PackedProof = [
19
+ export type PackedPoints = [
20
20
  NumericString,
21
21
  NumericString,
22
22
  NumericString,
@@ -0,0 +1,20 @@
1
+ import { Groth16Proof } from "snarkjs"
2
+ import { PackedPoints } from "./types"
3
+
4
+ /**
5
+ * Unpacks the Groth16 proof points into their original form.
6
+ * @param proof The proof points compatible with Semaphore.
7
+ * @returns The proof points compatible with SnarkJS.
8
+ */
9
+ export default function unpackPoints(proof: PackedPoints): Groth16Proof {
10
+ return {
11
+ pi_a: [proof[0], proof[1]],
12
+ pi_b: [
13
+ [proof[3], proof[2]],
14
+ [proof[5], proof[4]]
15
+ ],
16
+ pi_c: [proof[6], proof[7]],
17
+ protocol: "groth16",
18
+ curve: "bn128"
19
+ }
20
+ }
@@ -1,8 +1,8 @@
1
- import { verify } from "@zk-kit/groth16"
1
+ import { groth16 } from "snarkjs"
2
+ import hash from "./hash"
2
3
  import { SemaphoreProof } from "./types"
3
- import unpackProof from "./unpack-proof"
4
+ import unpackPoints from "./unpack-points"
4
5
  import verificationKeys from "./verification-keys.json"
5
- import hash from "./hash"
6
6
 
7
7
  /**
8
8
  * Verifies a Semaphore proof.
@@ -16,7 +16,7 @@ export default async function verifyProof({
16
16
  nullifier,
17
17
  message,
18
18
  scope,
19
- proof
19
+ points
20
20
  }: SemaphoreProof): Promise<boolean> {
21
21
  // TODO: support all tree depths after trusted-setup.
22
22
  if (merkleTreeDepth < 1 || merkleTreeDepth > 12) {
@@ -29,8 +29,9 @@ export default async function verifyProof({
29
29
  IC: verificationKeys.IC[merkleTreeDepth - 1]
30
30
  }
31
31
 
32
- return verify(verificationKey, {
33
- publicSignals: [merkleTreeRoot, nullifier, hash(message), hash(scope)],
34
- proof: unpackProof(proof)
35
- })
32
+ return groth16.verify(
33
+ verificationKey,
34
+ [merkleTreeRoot, nullifier, hash(message), hash(scope)],
35
+ unpackPoints(points)
36
+ )
36
37
  }
@@ -1,8 +0,0 @@
1
- import { Groth16Proof } from "@zk-kit/groth16";
2
- import { PackedProof } from "./types";
3
- /**
4
- * Packs a proof into a format compatible with Semaphore.
5
- * @param proof The Groth16 proof generated with SnarkJS.
6
- * @returns The proof compatible with Semaphore.
7
- */
8
- export default function packProof(proof: Groth16Proof): PackedProof;
@@ -1,8 +0,0 @@
1
- import { Groth16Proof } from "@zk-kit/groth16";
2
- import { PackedProof } from "./types";
3
- /**
4
- * Unpacks a proof into its original form.
5
- * @param proof The proof compatible with Semaphore.
6
- * @returns The proof compatible with SnarkJS.
7
- */
8
- export default function unpackProof(proof: PackedProof): Groth16Proof;
package/src/pack-proof.ts DELETED
@@ -1,20 +0,0 @@
1
- import { Groth16Proof } from "@zk-kit/groth16"
2
- import { PackedProof } from "./types"
3
-
4
- /**
5
- * Packs a proof into a format compatible with Semaphore.
6
- * @param proof The Groth16 proof generated with SnarkJS.
7
- * @returns The proof compatible with Semaphore.
8
- */
9
- export default function packProof(proof: Groth16Proof): PackedProof {
10
- return [
11
- proof.pi_a[0],
12
- proof.pi_a[1],
13
- proof.pi_b[0][1],
14
- proof.pi_b[0][0],
15
- proof.pi_b[1][1],
16
- proof.pi_b[1][0],
17
- proof.pi_c[0],
18
- proof.pi_c[1]
19
- ]
20
- }
@@ -1,20 +0,0 @@
1
- import { Groth16Proof } from "@zk-kit/groth16"
2
- import { PackedProof } from "./types"
3
-
4
- /**
5
- * Unpacks a proof into its original form.
6
- * @param proof The proof compatible with Semaphore.
7
- * @returns The proof compatible with SnarkJS.
8
- */
9
- export default function unpackProof(proof: PackedProof): Groth16Proof {
10
- return {
11
- pi_a: [proof[0], proof[1]],
12
- pi_b: [
13
- [proof[3], proof[2]],
14
- [proof[5], proof[4]]
15
- ],
16
- pi_c: [proof[6], proof[7]],
17
- protocol: "groth16",
18
- curve: "bn128"
19
- }
20
- }