@semaphore-protocol/proof 4.0.0-alpha.8 → 4.0.0-beta

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
@@ -18,7 +18,7 @@
18
18
  <a href="https://npmjs.org/package/@semaphore-protocol/proof">
19
19
  <img alt="Downloads" src="https://img.shields.io/npm/dm/@semaphore-protocol/proof.svg?style=flat-square" />
20
20
  </a>
21
- <a href="https://js.semaphore.pse.dev/proof">
21
+ <a href="https://js.semaphore.pse.dev/modules/_semaphore_protocol_proof">
22
22
  <img alt="Documentation typedoc" src="https://img.shields.io/badge/docs-typedoc-744C7C?style=flat-square">
23
23
  </a>
24
24
  <a href="https://eslint.org/">
@@ -49,8 +49,8 @@
49
49
  </h4>
50
50
  </div>
51
51
 
52
- | This library provides utility functions to generate and verify Semaphore proofs compatible with the Semaphore [circuits](https://github.com/semaphore-protocol/semaphore/tree/main/circuits). Generating valid zero-knowledge proofs requires files that can only be obtained in an attested [trusted-setup ceremony](https://storage.googleapis.com/trustedsetup-a86f4.appspot.com/semaphore/semaphore_top_index.html). For a complete list of ready-to-use files visit [trusted-setup-pse.org](http://www.trusted-setup-pse.org/). |
53
- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
52
+ | This library provides utility functions to generate and verify Semaphore proofs compatible with the Semaphore [circuits](https://github.com/semaphore-protocol/semaphore/tree/main/circuits). Generating valid zero-knowledge proofs requires files that can only be obtained in an attested trusted-setup ceremony. |
53
+ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
54
 
55
55
  ## 🛠 Install
56
56
 
@@ -70,6 +70,8 @@ yarn add @semaphore-protocol/identity @semaphore-protocol/group @semaphore-proto
70
70
 
71
71
  ## 📜 Usage
72
72
 
73
+ For more information on the functions provided by `@semaphore-protocol/proof`, please refer to the [TypeDoc documentation](https://js.semaphore.pse.dev/modules/_semaphore_protocol_proof).
74
+
73
75
  \# **generateProof**(
74
76
  identity: _Identity_,
75
77
  group: _Group_,
@@ -1,11 +1,14 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-alpha.8
3
+ * @version 4.0.0-beta
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
+ import { packGroth16Proof, unpackGroth16Proof } from '@zk-kit/utils';
10
+ export { packGroth16Proof, unpackGroth16Proof } from '@zk-kit/utils';
11
+ import { requireNumber, requireDefined, requireObject, requireTypes, requireString, requireArray } from '@semaphore-protocol/utils/errors';
9
12
  import { groth16 } from 'snarkjs';
10
13
  import { keccak256 } from 'ethers/crypto';
11
14
  import { toBeHex, toBigInt as toBigInt$1 } from 'ethers/utils';
@@ -82,9 +85,16 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
82
85
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
83
86
  };
84
87
 
88
+ /**
89
+ * Returns the zero-knowledge artifact paths. Artifacts exist for each tree
90
+ * depth supported by Semaphore, and they were generated in a trusted-setup.
91
+ * @param treeDepth The depth of the tree.
92
+ * @returns The zero-knowledge artifacts paths.
93
+ */
85
94
  function getSnarkArtifacts(treeDepth) {
86
95
  return __awaiter(this, void 0, void 0, function () {
87
96
  return __generator(this, function (_a) {
97
+ requireNumber(treeDepth, "treeDepth");
88
98
  return [2 /*return*/, {
89
99
  wasmFilePath: "https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"),
90
100
  zkeyFilePath: "https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.zkey")
@@ -103,23 +113,10 @@ function hash(message) {
103
113
  }
104
114
 
105
115
  /**
106
- * Packs the Groth16 proof points into a format compatible with Semaphore.
107
- * @param proof The proof points generated with SnarkJS.
108
- * @returns The proof points compatible with Semaphore.
116
+ * Converts a bignumberish to a bigint.
117
+ * @param value The value to be converted to bigint.
118
+ * @return The value converted to bigint.
109
119
  */
110
- function packPoints(proof) {
111
- return [
112
- proof.pi_a[0],
113
- proof.pi_a[1],
114
- proof.pi_b[0][1],
115
- proof.pi_b[0][0],
116
- proof.pi_b[1][1],
117
- proof.pi_b[1][0],
118
- proof.pi_c[0],
119
- proof.pi_c[1]
120
- ];
121
- }
122
-
123
120
  function toBigInt(value) {
124
121
  try {
125
122
  return toBigInt$1(value);
@@ -133,7 +130,17 @@ function toBigInt(value) {
133
130
  }
134
131
 
135
132
  /**
136
- * Generates a Semaphore proof.
133
+ * It generates a Semaphore proof, i.e. a zero-knowledge proof that an identity that
134
+ * is part of a group has shared an anonymous message.
135
+ * The message may be any arbitrary user-defined value (e.g. a vote), or the hash of that value.
136
+ * The scope is a value used like a topic on which users can generate a valid proof only once,
137
+ * for example the id of an election in which voters can only vote once.
138
+ * The hash of the identity's scope and secret scalar is called a nullifier and can be
139
+ * used to verify whether that identity has already generated a valid proof in that scope.
140
+ * The depth of the tree determines which zero-knowledge artifacts to use to generate the proof.
141
+ * If it is not defined, it will be inferred from the group or Merkle proof passed as the second parameter.
142
+ * Finally, the artifacts themselves can be passed manually with file paths,
143
+ * or they will be automatically fetched.
137
144
  * @param identity The Semaphore identity.
138
145
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
139
146
  * @param scope The Semaphore scope.
@@ -148,8 +155,26 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
148
155
  return __generator(this, function (_b) {
149
156
  switch (_b.label) {
150
157
  case 0:
158
+ requireDefined(identity, "identity");
159
+ requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
160
+ requireDefined(message, "message");
161
+ requireDefined(scope, "scope");
162
+ requireObject(identity, "identity");
163
+ requireObject(groupOrMerkleProof, "groupOrMerkleProof");
164
+ requireTypes(message, "message", ["string", "bigint", "number", "uint8array"]);
165
+ requireTypes(scope, "scope", ["string", "bigint", "number", "uint8array"]);
166
+ if (merkleTreeDepth) {
167
+ requireNumber(merkleTreeDepth, "merkleTreeDepth");
168
+ }
169
+ if (snarkArtifacts) {
170
+ requireObject(snarkArtifacts, "snarkArtifacts");
171
+ }
172
+ // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
173
+ // They will be converted to bigints anyway.
151
174
  message = toBigInt(message);
152
175
  scope = toBigInt(scope);
176
+ // The second parameter can be either a Merkle proof or a group.
177
+ // If it is a group the Merkle proof will be calculated here.
153
178
  if ("siblings" in groupOrMerkleProof) {
154
179
  merkleProof = groupOrMerkleProof;
155
180
  }
@@ -196,31 +221,13 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
196
221
  nullifier: publicSignals[1],
197
222
  message: message.toString(),
198
223
  scope: scope.toString(),
199
- points: packPoints(proof)
224
+ points: packGroth16Proof(proof)
200
225
  }];
201
226
  }
202
227
  });
203
228
  });
204
229
  }
205
230
 
206
- /**
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.
210
- */
211
- function unpackPoints(proof) {
212
- return {
213
- pi_a: [proof[0], proof[1]],
214
- pi_b: [
215
- [proof[3], proof[2]],
216
- [proof[5], proof[4]]
217
- ],
218
- pi_c: [proof[6], proof[7]],
219
- protocol: "groth16",
220
- curve: "bn128"
221
- };
222
- }
223
-
224
231
  var protocol = "groth16";
225
232
  var curve = "bn128";
226
233
  var nPublic = 4;
@@ -796,23 +803,32 @@ var verificationKeys = {
796
803
  };
797
804
 
798
805
  /**
799
- * Verifies a Semaphore proof.
806
+ * Verifies whether a Semaphore proof is valid. Depending on the depth of the tree used to
807
+ * generate the proof, a different verification key will be used.
800
808
  * @param proof The Semaphore proof.
801
809
  * @returns True if the proof is valid, false otherwise.
802
810
  */
803
- function verifyProof(_a) {
804
- var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, points = _a.points;
811
+ function verifyProof(proof) {
805
812
  return __awaiter(this, void 0, void 0, function () {
806
- var verificationKey;
807
- return __generator(this, function (_b) {
813
+ var merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points, verificationKey;
814
+ return __generator(this, function (_a) {
815
+ requireDefined(proof, "proof");
816
+ requireObject(proof, "proof");
817
+ merkleTreeDepth = proof.merkleTreeDepth, merkleTreeRoot = proof.merkleTreeRoot, nullifier = proof.nullifier, message = proof.message, scope = proof.scope, points = proof.points;
818
+ requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
819
+ requireString(merkleTreeRoot, "proof.merkleTreeRoot");
820
+ requireString(nullifier, "proof.nullifier");
821
+ requireString(message, "proof.message");
822
+ requireString(scope, "proof.scope");
823
+ requireArray(points, "proof.points");
808
824
  // TODO: support all tree depths after trusted-setup.
809
825
  if (merkleTreeDepth < 1 || merkleTreeDepth > 12) {
810
826
  throw new TypeError("The tree depth must be a number between 1 and 12");
811
827
  }
812
828
  verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
813
- return [2 /*return*/, groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackPoints(points))];
829
+ return [2 /*return*/, groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackGroth16Proof(points))];
814
830
  });
815
831
  });
816
832
  }
817
833
 
818
- export { generateProof, getSnarkArtifacts, packPoints, unpackPoints, verifyProof };
834
+ export { generateProof, verifyProof };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-alpha.8
3
+ * @version 4.0.0-beta
4
4
  * @file A library to generate and verify Semaphore proofs.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
@@ -8,6 +8,8 @@
8
8
  */
9
9
  'use strict';
10
10
 
11
+ var utils = require('@zk-kit/utils');
12
+ var errors = require('@semaphore-protocol/utils/errors');
11
13
  var snarkjs = require('snarkjs');
12
14
  var node_fs = require('node:fs');
13
15
  var promises$1 = require('node:fs/promises');
@@ -16,7 +18,7 @@ var node_path = require('node:path');
16
18
  var node_stream = require('node:stream');
17
19
  var promises = require('node:stream/promises');
18
20
  var crypto = require('ethers/crypto');
19
- var utils = require('ethers/utils');
21
+ var utils$1 = require('ethers/utils');
20
22
  var abi = require('ethers/abi');
21
23
 
22
24
  /******************************************************************************
@@ -90,6 +92,11 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
90
92
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
91
93
  };
92
94
 
95
+ /**
96
+ * A utility function to download the zero-knowledge artifacts from an external server.
97
+ * @param url The URL from which to download the artifacts.
98
+ * @param outputPath The path in which to save the artifacts.
99
+ */
93
100
  function download(url, outputPath) {
94
101
  return __awaiter(this, void 0, void 0, function () {
95
102
  var response, dir, fileStream;
@@ -114,12 +121,20 @@ function download(url, outputPath) {
114
121
  });
115
122
  });
116
123
  }
124
+ /**
125
+ * Downloads the zero-knowledge artifacts and returns their paths.
126
+ * Artifacts exist for each tree depth supported by Semaphore, and
127
+ * they were generated in a trusted-setup.
128
+ * @param treeDepth The depth of the tree.
129
+ * @returns The zero-knowledge artifacts paths.
130
+ */
117
131
  function getSnarkArtifacts(treeDepth) {
118
132
  return __awaiter(this, void 0, void 0, function () {
119
133
  var tmpDir, tmpPath;
120
134
  return __generator(this, function (_a) {
121
135
  switch (_a.label) {
122
136
  case 0:
137
+ errors.requireNumber(treeDepth, "treeDepth");
123
138
  tmpDir = "semaphore-proof";
124
139
  tmpPath = "".concat(os.tmpdir(), "/").concat(tmpDir, "-").concat(treeDepth);
125
140
  if (!(!node_fs.existsSync(tmpPath) || node_fs.readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
@@ -145,41 +160,38 @@ function getSnarkArtifacts(treeDepth) {
145
160
  * @returns The message digest.
146
161
  */
147
162
  function hash(message) {
148
- return (BigInt(crypto.keccak256(utils.toBeHex(message, 32))) >> BigInt(8)).toString();
163
+ return (BigInt(crypto.keccak256(utils$1.toBeHex(message, 32))) >> BigInt(8)).toString();
149
164
  }
150
165
 
151
166
  /**
152
- * Packs the Groth16 proof points into a format compatible with Semaphore.
153
- * @param proof The proof points generated with SnarkJS.
154
- * @returns The proof points compatible with Semaphore.
167
+ * Converts a bignumberish to a bigint.
168
+ * @param value The value to be converted to bigint.
169
+ * @return The value converted to bigint.
155
170
  */
156
- function packPoints(proof) {
157
- return [
158
- proof.pi_a[0],
159
- proof.pi_a[1],
160
- proof.pi_b[0][1],
161
- proof.pi_b[0][0],
162
- proof.pi_b[1][1],
163
- proof.pi_b[1][0],
164
- proof.pi_c[0],
165
- proof.pi_c[1]
166
- ];
167
- }
168
-
169
171
  function toBigInt(value) {
170
172
  try {
171
- return utils.toBigInt(value);
173
+ return utils$1.toBigInt(value);
172
174
  }
173
175
  catch (error) {
174
176
  if (typeof value === "string") {
175
- return utils.toBigInt(abi.encodeBytes32String(value));
177
+ return utils$1.toBigInt(abi.encodeBytes32String(value));
176
178
  }
177
179
  throw TypeError(error.message);
178
180
  }
179
181
  }
180
182
 
181
183
  /**
182
- * Generates a Semaphore proof.
184
+ * It generates a Semaphore proof, i.e. a zero-knowledge proof that an identity that
185
+ * is part of a group has shared an anonymous message.
186
+ * The message may be any arbitrary user-defined value (e.g. a vote), or the hash of that value.
187
+ * The scope is a value used like a topic on which users can generate a valid proof only once,
188
+ * for example the id of an election in which voters can only vote once.
189
+ * The hash of the identity's scope and secret scalar is called a nullifier and can be
190
+ * used to verify whether that identity has already generated a valid proof in that scope.
191
+ * The depth of the tree determines which zero-knowledge artifacts to use to generate the proof.
192
+ * If it is not defined, it will be inferred from the group or Merkle proof passed as the second parameter.
193
+ * Finally, the artifacts themselves can be passed manually with file paths,
194
+ * or they will be automatically fetched.
183
195
  * @param identity The Semaphore identity.
184
196
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
185
197
  * @param scope The Semaphore scope.
@@ -194,8 +206,26 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
194
206
  return __generator(this, function (_b) {
195
207
  switch (_b.label) {
196
208
  case 0:
209
+ errors.requireDefined(identity, "identity");
210
+ errors.requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
211
+ errors.requireDefined(message, "message");
212
+ errors.requireDefined(scope, "scope");
213
+ errors.requireObject(identity, "identity");
214
+ errors.requireObject(groupOrMerkleProof, "groupOrMerkleProof");
215
+ errors.requireTypes(message, "message", ["string", "bigint", "number", "uint8array"]);
216
+ errors.requireTypes(scope, "scope", ["string", "bigint", "number", "uint8array"]);
217
+ if (merkleTreeDepth) {
218
+ errors.requireNumber(merkleTreeDepth, "merkleTreeDepth");
219
+ }
220
+ if (snarkArtifacts) {
221
+ errors.requireObject(snarkArtifacts, "snarkArtifacts");
222
+ }
223
+ // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
224
+ // They will be converted to bigints anyway.
197
225
  message = toBigInt(message);
198
226
  scope = toBigInt(scope);
227
+ // The second parameter can be either a Merkle proof or a group.
228
+ // If it is a group the Merkle proof will be calculated here.
199
229
  if ("siblings" in groupOrMerkleProof) {
200
230
  merkleProof = groupOrMerkleProof;
201
231
  }
@@ -242,31 +272,13 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
242
272
  nullifier: publicSignals[1],
243
273
  message: message.toString(),
244
274
  scope: scope.toString(),
245
- points: packPoints(proof)
275
+ points: utils.packGroth16Proof(proof)
246
276
  }];
247
277
  }
248
278
  });
249
279
  });
250
280
  }
251
281
 
252
- /**
253
- * Unpacks the Groth16 proof points into their original form.
254
- * @param proof The proof points compatible with Semaphore.
255
- * @returns The proof points compatible with SnarkJS.
256
- */
257
- function unpackPoints(proof) {
258
- return {
259
- pi_a: [proof[0], proof[1]],
260
- pi_b: [
261
- [proof[3], proof[2]],
262
- [proof[5], proof[4]]
263
- ],
264
- pi_c: [proof[6], proof[7]],
265
- protocol: "groth16",
266
- curve: "bn128"
267
- };
268
- }
269
-
270
282
  var protocol = "groth16";
271
283
  var curve = "bn128";
272
284
  var nPublic = 4;
@@ -842,27 +854,41 @@ var verificationKeys = {
842
854
  };
843
855
 
844
856
  /**
845
- * Verifies a Semaphore proof.
857
+ * Verifies whether a Semaphore proof is valid. Depending on the depth of the tree used to
858
+ * generate the proof, a different verification key will be used.
846
859
  * @param proof The Semaphore proof.
847
860
  * @returns True if the proof is valid, false otherwise.
848
861
  */
849
- function verifyProof(_a) {
850
- var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, points = _a.points;
862
+ function verifyProof(proof) {
851
863
  return __awaiter(this, void 0, void 0, function () {
852
- var verificationKey;
853
- return __generator(this, function (_b) {
864
+ var merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points, verificationKey;
865
+ return __generator(this, function (_a) {
866
+ errors.requireDefined(proof, "proof");
867
+ errors.requireObject(proof, "proof");
868
+ merkleTreeDepth = proof.merkleTreeDepth, merkleTreeRoot = proof.merkleTreeRoot, nullifier = proof.nullifier, message = proof.message, scope = proof.scope, points = proof.points;
869
+ errors.requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
870
+ errors.requireString(merkleTreeRoot, "proof.merkleTreeRoot");
871
+ errors.requireString(nullifier, "proof.nullifier");
872
+ errors.requireString(message, "proof.message");
873
+ errors.requireString(scope, "proof.scope");
874
+ errors.requireArray(points, "proof.points");
854
875
  // TODO: support all tree depths after trusted-setup.
855
876
  if (merkleTreeDepth < 1 || merkleTreeDepth > 12) {
856
877
  throw new TypeError("The tree depth must be a number between 1 and 12");
857
878
  }
858
879
  verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
859
- return [2 /*return*/, snarkjs.groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackPoints(points))];
880
+ return [2 /*return*/, snarkjs.groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], utils.unpackGroth16Proof(points))];
860
881
  });
861
882
  });
862
883
  }
863
884
 
885
+ Object.defineProperty(exports, "packGroth16Proof", {
886
+ enumerable: true,
887
+ get: function () { return utils.packGroth16Proof; }
888
+ });
889
+ Object.defineProperty(exports, "unpackGroth16Proof", {
890
+ enumerable: true,
891
+ get: function () { return utils.unpackGroth16Proof; }
892
+ });
864
893
  exports.generateProof = generateProof;
865
- exports.getSnarkArtifacts = getSnarkArtifacts;
866
- exports.packPoints = packPoints;
867
- exports.unpackPoints = unpackPoints;
868
894
  exports.verifyProof = verifyProof;
@@ -1,11 +1,14 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-alpha.8
3
+ * @version 4.0.0-beta
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
+ import { packGroth16Proof, unpackGroth16Proof } from '@zk-kit/utils';
10
+ export { packGroth16Proof, unpackGroth16Proof } from '@zk-kit/utils';
11
+ import { requireNumber, requireDefined, requireObject, requireTypes, requireString, requireArray } from '@semaphore-protocol/utils/errors';
9
12
  import { groth16 } from 'snarkjs';
10
13
  import { existsSync, readdirSync, createWriteStream } from 'node:fs';
11
14
  import { mkdir } from 'node:fs/promises';
@@ -88,6 +91,11 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
88
91
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
89
92
  };
90
93
 
94
+ /**
95
+ * A utility function to download the zero-knowledge artifacts from an external server.
96
+ * @param url The URL from which to download the artifacts.
97
+ * @param outputPath The path in which to save the artifacts.
98
+ */
91
99
  function download(url, outputPath) {
92
100
  return __awaiter(this, void 0, void 0, function () {
93
101
  var response, dir, fileStream;
@@ -112,12 +120,20 @@ function download(url, outputPath) {
112
120
  });
113
121
  });
114
122
  }
123
+ /**
124
+ * Downloads the zero-knowledge artifacts and returns their paths.
125
+ * Artifacts exist for each tree depth supported by Semaphore, and
126
+ * they were generated in a trusted-setup.
127
+ * @param treeDepth The depth of the tree.
128
+ * @returns The zero-knowledge artifacts paths.
129
+ */
115
130
  function getSnarkArtifacts(treeDepth) {
116
131
  return __awaiter(this, void 0, void 0, function () {
117
132
  var tmpDir, tmpPath;
118
133
  return __generator(this, function (_a) {
119
134
  switch (_a.label) {
120
135
  case 0:
136
+ requireNumber(treeDepth, "treeDepth");
121
137
  tmpDir = "semaphore-proof";
122
138
  tmpPath = "".concat(os.tmpdir(), "/").concat(tmpDir, "-").concat(treeDepth);
123
139
  if (!(!existsSync(tmpPath) || readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
@@ -147,23 +163,10 @@ function hash(message) {
147
163
  }
148
164
 
149
165
  /**
150
- * Packs the Groth16 proof points into a format compatible with Semaphore.
151
- * @param proof The proof points generated with SnarkJS.
152
- * @returns The proof points compatible with Semaphore.
166
+ * Converts a bignumberish to a bigint.
167
+ * @param value The value to be converted to bigint.
168
+ * @return The value converted to bigint.
153
169
  */
154
- function packPoints(proof) {
155
- return [
156
- proof.pi_a[0],
157
- proof.pi_a[1],
158
- proof.pi_b[0][1],
159
- proof.pi_b[0][0],
160
- proof.pi_b[1][1],
161
- proof.pi_b[1][0],
162
- proof.pi_c[0],
163
- proof.pi_c[1]
164
- ];
165
- }
166
-
167
170
  function toBigInt(value) {
168
171
  try {
169
172
  return toBigInt$1(value);
@@ -177,7 +180,17 @@ function toBigInt(value) {
177
180
  }
178
181
 
179
182
  /**
180
- * Generates a Semaphore proof.
183
+ * It generates a Semaphore proof, i.e. a zero-knowledge proof that an identity that
184
+ * is part of a group has shared an anonymous message.
185
+ * The message may be any arbitrary user-defined value (e.g. a vote), or the hash of that value.
186
+ * The scope is a value used like a topic on which users can generate a valid proof only once,
187
+ * for example the id of an election in which voters can only vote once.
188
+ * The hash of the identity's scope and secret scalar is called a nullifier and can be
189
+ * used to verify whether that identity has already generated a valid proof in that scope.
190
+ * The depth of the tree determines which zero-knowledge artifacts to use to generate the proof.
191
+ * If it is not defined, it will be inferred from the group or Merkle proof passed as the second parameter.
192
+ * Finally, the artifacts themselves can be passed manually with file paths,
193
+ * or they will be automatically fetched.
181
194
  * @param identity The Semaphore identity.
182
195
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
183
196
  * @param scope The Semaphore scope.
@@ -192,8 +205,26 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
192
205
  return __generator(this, function (_b) {
193
206
  switch (_b.label) {
194
207
  case 0:
208
+ requireDefined(identity, "identity");
209
+ requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
210
+ requireDefined(message, "message");
211
+ requireDefined(scope, "scope");
212
+ requireObject(identity, "identity");
213
+ requireObject(groupOrMerkleProof, "groupOrMerkleProof");
214
+ requireTypes(message, "message", ["string", "bigint", "number", "uint8array"]);
215
+ requireTypes(scope, "scope", ["string", "bigint", "number", "uint8array"]);
216
+ if (merkleTreeDepth) {
217
+ requireNumber(merkleTreeDepth, "merkleTreeDepth");
218
+ }
219
+ if (snarkArtifacts) {
220
+ requireObject(snarkArtifacts, "snarkArtifacts");
221
+ }
222
+ // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
223
+ // They will be converted to bigints anyway.
195
224
  message = toBigInt(message);
196
225
  scope = toBigInt(scope);
226
+ // The second parameter can be either a Merkle proof or a group.
227
+ // If it is a group the Merkle proof will be calculated here.
197
228
  if ("siblings" in groupOrMerkleProof) {
198
229
  merkleProof = groupOrMerkleProof;
199
230
  }
@@ -240,31 +271,13 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
240
271
  nullifier: publicSignals[1],
241
272
  message: message.toString(),
242
273
  scope: scope.toString(),
243
- points: packPoints(proof)
274
+ points: packGroth16Proof(proof)
244
275
  }];
245
276
  }
246
277
  });
247
278
  });
248
279
  }
249
280
 
250
- /**
251
- * Unpacks the Groth16 proof points into their original form.
252
- * @param proof The proof points compatible with Semaphore.
253
- * @returns The proof points compatible with SnarkJS.
254
- */
255
- function unpackPoints(proof) {
256
- return {
257
- pi_a: [proof[0], proof[1]],
258
- pi_b: [
259
- [proof[3], proof[2]],
260
- [proof[5], proof[4]]
261
- ],
262
- pi_c: [proof[6], proof[7]],
263
- protocol: "groth16",
264
- curve: "bn128"
265
- };
266
- }
267
-
268
281
  var protocol = "groth16";
269
282
  var curve = "bn128";
270
283
  var nPublic = 4;
@@ -840,23 +853,32 @@ var verificationKeys = {
840
853
  };
841
854
 
842
855
  /**
843
- * Verifies a Semaphore proof.
856
+ * Verifies whether a Semaphore proof is valid. Depending on the depth of the tree used to
857
+ * generate the proof, a different verification key will be used.
844
858
  * @param proof The Semaphore proof.
845
859
  * @returns True if the proof is valid, false otherwise.
846
860
  */
847
- function verifyProof(_a) {
848
- var merkleTreeDepth = _a.merkleTreeDepth, merkleTreeRoot = _a.merkleTreeRoot, nullifier = _a.nullifier, message = _a.message, scope = _a.scope, points = _a.points;
861
+ function verifyProof(proof) {
849
862
  return __awaiter(this, void 0, void 0, function () {
850
- var verificationKey;
851
- return __generator(this, function (_b) {
863
+ var merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points, verificationKey;
864
+ return __generator(this, function (_a) {
865
+ requireDefined(proof, "proof");
866
+ requireObject(proof, "proof");
867
+ merkleTreeDepth = proof.merkleTreeDepth, merkleTreeRoot = proof.merkleTreeRoot, nullifier = proof.nullifier, message = proof.message, scope = proof.scope, points = proof.points;
868
+ requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
869
+ requireString(merkleTreeRoot, "proof.merkleTreeRoot");
870
+ requireString(nullifier, "proof.nullifier");
871
+ requireString(message, "proof.message");
872
+ requireString(scope, "proof.scope");
873
+ requireArray(points, "proof.points");
852
874
  // TODO: support all tree depths after trusted-setup.
853
875
  if (merkleTreeDepth < 1 || merkleTreeDepth > 12) {
854
876
  throw new TypeError("The tree depth must be a number between 1 and 12");
855
877
  }
856
878
  verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
857
- return [2 /*return*/, groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackPoints(points))];
879
+ return [2 /*return*/, groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackGroth16Proof(points))];
858
880
  });
859
881
  });
860
882
  }
861
883
 
862
- export { generateProof, getSnarkArtifacts, packPoints, unpackPoints, verifyProof };
884
+ export { generateProof, verifyProof };
@@ -2,7 +2,17 @@ import type { Group, MerkleProof } from "@semaphore-protocol/group";
2
2
  import type { Identity } from "@semaphore-protocol/identity";
3
3
  import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types";
4
4
  /**
5
- * Generates a Semaphore proof.
5
+ * It generates a Semaphore proof, i.e. a zero-knowledge proof that an identity that
6
+ * is part of a group has shared an anonymous message.
7
+ * The message may be any arbitrary user-defined value (e.g. a vote), or the hash of that value.
8
+ * The scope is a value used like a topic on which users can generate a valid proof only once,
9
+ * for example the id of an election in which voters can only vote once.
10
+ * The hash of the identity's scope and secret scalar is called a nullifier and can be
11
+ * used to verify whether that identity has already generated a valid proof in that scope.
12
+ * The depth of the tree determines which zero-knowledge artifacts to use to generate the proof.
13
+ * If it is not defined, it will be inferred from the group or Merkle proof passed as the second parameter.
14
+ * Finally, the artifacts themselves can be passed manually with file paths,
15
+ * or they will be automatically fetched.
6
16
  * @param identity The Semaphore identity.
7
17
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
8
18
  * @param scope The Semaphore scope.
@@ -1,2 +1,8 @@
1
1
  import { SnarkArtifacts } from "./types";
2
+ /**
3
+ * Returns the zero-knowledge artifact paths. Artifacts exist for each tree
4
+ * depth supported by Semaphore, and they were generated in a trusted-setup.
5
+ * @param treeDepth The depth of the tree.
6
+ * @returns The zero-knowledge artifacts paths.
7
+ */
2
8
  export default function getSnarkArtifacts(treeDepth: number): Promise<SnarkArtifacts>;
@@ -1,2 +1,9 @@
1
1
  import { SnarkArtifacts } from "./types";
2
+ /**
3
+ * Downloads the zero-knowledge artifacts and returns their paths.
4
+ * Artifacts exist for each tree depth supported by Semaphore, and
5
+ * they were generated in a trusted-setup.
6
+ * @param treeDepth The depth of the tree.
7
+ * @returns The zero-knowledge artifacts paths.
8
+ */
2
9
  export default function getSnarkArtifacts(treeDepth: number): Promise<SnarkArtifacts>;
@@ -1,7 +1,5 @@
1
+ import { packGroth16Proof, unpackGroth16Proof } from "@zk-kit/utils";
1
2
  import generateProof from "./generate-proof";
2
- import getSnarkArtifacts from "./get-snark-artifacts.node";
3
- import packPoints from "./pack-points";
4
- import unpackPoints from "./unpack-points";
5
3
  import verifyProof from "./verify-proof";
6
4
  export * from "./types";
7
- export { generateProof, getSnarkArtifacts, packPoints, unpackPoints, verifyProof };
5
+ export { generateProof, packGroth16Proof, unpackGroth16Proof, verifyProof };
@@ -1,2 +1,7 @@
1
1
  import { BigNumberish } from "./types";
2
+ /**
3
+ * Converts a bignumberish to a bigint.
4
+ * @param value The value to be converted to bigint.
5
+ * @return The value converted to bigint.
6
+ */
2
7
  export default function toBigInt(value: BigNumberish | Uint8Array | string): bigint;
@@ -1,7 +1,8 @@
1
1
  import { SemaphoreProof } from "./types";
2
2
  /**
3
- * Verifies a Semaphore proof.
3
+ * Verifies whether a Semaphore proof is valid. Depending on the depth of the tree used to
4
+ * generate the proof, a different verification key will be used.
4
5
  * @param proof The Semaphore proof.
5
6
  * @returns True if the proof is valid, false otherwise.
6
7
  */
7
- export default function verifyProof({ merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points }: SemaphoreProof): Promise<boolean>;
8
+ export default function verifyProof(proof: SemaphoreProof): Promise<boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semaphore-protocol/proof",
3
- "version": "4.0.0-alpha.8",
3
+ "version": "4.0.0-beta",
4
4
  "description": "A library to generate and verify Semaphore proofs.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -41,19 +41,21 @@
41
41
  "@rollup/plugin-alias": "^5.1.0",
42
42
  "@rollup/plugin-json": "^6.1.0",
43
43
  "@types/download": "^8.0.5",
44
+ "@types/snarkjs": "0.7.8",
44
45
  "@types/tmp": "^0.2.6",
45
46
  "poseidon-lite": "^0.2.0",
46
47
  "rimraf": "^5.0.5",
47
- "rollup": "^4.0.2",
48
+ "rollup": "^4.9.6",
48
49
  "rollup-plugin-cleanup": "^3.2.1",
49
50
  "rollup-plugin-typescript2": "^0.36.0"
50
51
  },
51
52
  "peerDependencies": {
52
- "@semaphore-protocol/group": "4.0.0-alpha.8",
53
- "@semaphore-protocol/identity": "4.0.0-alpha.8"
53
+ "@semaphore-protocol/group": "4.0.0-beta",
54
+ "@semaphore-protocol/identity": "4.0.0-beta"
54
55
  },
55
56
  "dependencies": {
56
- "@types/snarkjs": "0.7.8",
57
+ "@semaphore-protocol/utils": "4.0.0-beta",
58
+ "@zk-kit/utils": "0.2.0",
57
59
  "ethers": "6.10.0",
58
60
  "snarkjs": "0.7.3"
59
61
  }
@@ -1,14 +1,25 @@
1
1
  import type { Group, MerkleProof } from "@semaphore-protocol/group"
2
2
  import type { Identity } from "@semaphore-protocol/identity"
3
+ import { requireDefined, requireNumber, requireObject, requireTypes } from "@semaphore-protocol/utils/errors"
3
4
  import { NumericString, groth16 } from "snarkjs"
5
+ import { packGroth16Proof } from "@zk-kit/utils"
4
6
  import getSnarkArtifacts from "./get-snark-artifacts.node"
5
7
  import hash from "./hash"
6
- import packPoints from "./pack-points"
7
- import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types"
8
8
  import toBigInt from "./to-bigint"
9
+ import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types"
9
10
 
10
11
  /**
11
- * Generates a Semaphore proof.
12
+ * It generates a Semaphore proof, i.e. a zero-knowledge proof that an identity that
13
+ * is part of a group has shared an anonymous message.
14
+ * The message may be any arbitrary user-defined value (e.g. a vote), or the hash of that value.
15
+ * The scope is a value used like a topic on which users can generate a valid proof only once,
16
+ * for example the id of an election in which voters can only vote once.
17
+ * The hash of the identity's scope and secret scalar is called a nullifier and can be
18
+ * used to verify whether that identity has already generated a valid proof in that scope.
19
+ * The depth of the tree determines which zero-knowledge artifacts to use to generate the proof.
20
+ * If it is not defined, it will be inferred from the group or Merkle proof passed as the second parameter.
21
+ * Finally, the artifacts themselves can be passed manually with file paths,
22
+ * or they will be automatically fetched.
12
23
  * @param identity The Semaphore identity.
13
24
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
14
25
  * @param scope The Semaphore scope.
@@ -25,11 +36,33 @@ export default async function generateProof(
25
36
  merkleTreeDepth?: number,
26
37
  snarkArtifacts?: SnarkArtifacts
27
38
  ): Promise<SemaphoreProof> {
39
+ requireDefined(identity, "identity")
40
+ requireDefined(groupOrMerkleProof, "groupOrMerkleProof")
41
+ requireDefined(message, "message")
42
+ requireDefined(scope, "scope")
43
+
44
+ requireObject(identity, "identity")
45
+ requireObject(groupOrMerkleProof, "groupOrMerkleProof")
46
+ requireTypes(message, "message", ["string", "bigint", "number", "uint8array"])
47
+ requireTypes(scope, "scope", ["string", "bigint", "number", "uint8array"])
48
+
49
+ if (merkleTreeDepth) {
50
+ requireNumber(merkleTreeDepth, "merkleTreeDepth")
51
+ }
52
+
53
+ if (snarkArtifacts) {
54
+ requireObject(snarkArtifacts, "snarkArtifacts")
55
+ }
56
+
57
+ // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
58
+ // They will be converted to bigints anyway.
28
59
  message = toBigInt(message)
29
60
  scope = toBigInt(scope)
30
61
 
31
62
  let merkleProof
32
63
 
64
+ // The second parameter can be either a Merkle proof or a group.
65
+ // If it is a group the Merkle proof will be calculated here.
33
66
  if ("siblings" in groupOrMerkleProof) {
34
67
  merkleProof = groupOrMerkleProof
35
68
  } else {
@@ -84,6 +117,6 @@ export default async function generateProof(
84
117
  nullifier: publicSignals[1],
85
118
  message: message.toString() as NumericString,
86
119
  scope: scope.toString() as NumericString,
87
- points: packPoints(proof)
120
+ points: packGroth16Proof(proof)
88
121
  }
89
122
  }
@@ -1,7 +1,16 @@
1
1
  /* istanbul ignore file */
2
+ import { requireNumber } from "@semaphore-protocol/utils/errors"
2
3
  import { SnarkArtifacts } from "./types"
3
4
 
5
+ /**
6
+ * Returns the zero-knowledge artifact paths. Artifacts exist for each tree
7
+ * depth supported by Semaphore, and they were generated in a trusted-setup.
8
+ * @param treeDepth The depth of the tree.
9
+ * @returns The zero-knowledge artifacts paths.
10
+ */
4
11
  export default async function getSnarkArtifacts(treeDepth: number): Promise<SnarkArtifacts> {
12
+ requireNumber(treeDepth, "treeDepth")
13
+
5
14
  return {
6
15
  wasmFilePath: `https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.wasm`,
7
16
  zkeyFilePath: `https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.zkey`
@@ -1,4 +1,5 @@
1
1
  /* istanbul ignore file */
2
+ import { requireNumber } from "@semaphore-protocol/utils/errors"
2
3
  import { createWriteStream, existsSync, readdirSync } from "node:fs"
3
4
  import { mkdir } from "node:fs/promises"
4
5
  import os from "node:os"
@@ -7,6 +8,11 @@ import { Readable } from "node:stream"
7
8
  import { finished } from "node:stream/promises"
8
9
  import { SnarkArtifacts } from "./types"
9
10
 
11
+ /**
12
+ * A utility function to download the zero-knowledge artifacts from an external server.
13
+ * @param url The URL from which to download the artifacts.
14
+ * @param outputPath The path in which to save the artifacts.
15
+ */
10
16
  async function download(url: string, outputPath: string) {
11
17
  const response = await fetch(url)
12
18
 
@@ -22,7 +28,16 @@ async function download(url: string, outputPath: string) {
22
28
  await finished(Readable.fromWeb(response.body as any).pipe(fileStream))
23
29
  }
24
30
 
31
+ /**
32
+ * Downloads the zero-knowledge artifacts and returns their paths.
33
+ * Artifacts exist for each tree depth supported by Semaphore, and
34
+ * they were generated in a trusted-setup.
35
+ * @param treeDepth The depth of the tree.
36
+ * @returns The zero-knowledge artifacts paths.
37
+ */
25
38
  export default async function getSnarkArtifacts(treeDepth: number): Promise<SnarkArtifacts> {
39
+ requireNumber(treeDepth, "treeDepth")
40
+
26
41
  const tmpDir = "semaphore-proof"
27
42
  const tmpPath = `${os.tmpdir()}/${tmpDir}-${treeDepth}`
28
43
 
package/src/index.ts CHANGED
@@ -1,8 +1,6 @@
1
+ import { packGroth16Proof, unpackGroth16Proof } from "@zk-kit/utils"
1
2
  import generateProof from "./generate-proof"
2
- import getSnarkArtifacts from "./get-snark-artifacts.node"
3
- import packPoints from "./pack-points"
4
- import unpackPoints from "./unpack-points"
5
3
  import verifyProof from "./verify-proof"
6
4
 
7
5
  export * from "./types"
8
- export { generateProof, getSnarkArtifacts, packPoints, unpackPoints, verifyProof }
6
+ export { generateProof, packGroth16Proof, unpackGroth16Proof, verifyProof }
package/src/to-bigint.ts CHANGED
@@ -2,6 +2,11 @@ import { encodeBytes32String } from "ethers/abi"
2
2
  import { toBigInt as _toBigInt } from "ethers/utils"
3
3
  import { BigNumberish } from "./types"
4
4
 
5
+ /**
6
+ * Converts a bignumberish to a bigint.
7
+ * @param value The value to be converted to bigint.
8
+ * @return The value converted to bigint.
9
+ */
5
10
  export default function toBigInt(value: BigNumberish | Uint8Array | string): bigint {
6
11
  try {
7
12
  return _toBigInt(value)
@@ -1,22 +1,35 @@
1
+ import {
2
+ requireArray,
3
+ requireDefined,
4
+ requireNumber,
5
+ requireObject,
6
+ requireString
7
+ } from "@semaphore-protocol/utils/errors"
1
8
  import { groth16 } from "snarkjs"
9
+ import { unpackGroth16Proof } from "@zk-kit/utils"
2
10
  import hash from "./hash"
3
11
  import { SemaphoreProof } from "./types"
4
- import unpackPoints from "./unpack-points"
5
12
  import verificationKeys from "./verification-keys.json"
6
13
 
7
14
  /**
8
- * Verifies a Semaphore proof.
15
+ * Verifies whether a Semaphore proof is valid. Depending on the depth of the tree used to
16
+ * generate the proof, a different verification key will be used.
9
17
  * @param proof The Semaphore proof.
10
18
  * @returns True if the proof is valid, false otherwise.
11
19
  */
12
- export default async function verifyProof({
13
- merkleTreeDepth,
14
- merkleTreeRoot,
15
- nullifier,
16
- message,
17
- scope,
18
- points
19
- }: SemaphoreProof): Promise<boolean> {
20
+ export default async function verifyProof(proof: SemaphoreProof): Promise<boolean> {
21
+ requireDefined(proof, "proof")
22
+ requireObject(proof, "proof")
23
+
24
+ const { merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points } = proof
25
+
26
+ requireNumber(merkleTreeDepth, "proof.merkleTreeDepth")
27
+ requireString(merkleTreeRoot, "proof.merkleTreeRoot")
28
+ requireString(nullifier, "proof.nullifier")
29
+ requireString(message, "proof.message")
30
+ requireString(scope, "proof.scope")
31
+ requireArray(points, "proof.points")
32
+
20
33
  // TODO: support all tree depths after trusted-setup.
21
34
  if (merkleTreeDepth < 1 || merkleTreeDepth > 12) {
22
35
  throw new TypeError("The tree depth must be a number between 1 and 12")
@@ -31,6 +44,6 @@ export default async function verifyProof({
31
44
  return groth16.verify(
32
45
  verificationKey,
33
46
  [merkleTreeRoot, nullifier, hash(message), hash(scope)],
34
- unpackPoints(points)
47
+ unpackGroth16Proof(points)
35
48
  )
36
49
  }
@@ -1,8 +0,0 @@
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,8 +0,0 @@
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;
@@ -1,20 +0,0 @@
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,20 +0,0 @@
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
- }