@semaphore-protocol/proof 4.0.0-beta.3 → 4.0.0-beta.5

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-beta.3
3
+ * @version 4.0.0-beta.5
4
4
  * @file A library to generate and verify Semaphore proofs.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
@@ -15,73 +15,19 @@ import { keccak256 } from 'ethers/crypto';
15
15
  import { toBeHex, toBigInt as toBigInt$1 } from 'ethers/utils';
16
16
  import { encodeBytes32String } from 'ethers/abi';
17
17
 
18
- var __assign = function() {
19
- __assign = Object.assign || function __assign(t) {
20
- for (var s, i = 1, n = arguments.length; i < n; i++) {
21
- s = arguments[i];
22
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
23
- }
24
- return t;
25
- };
26
- return __assign.apply(this, arguments);
27
- };
28
- function __awaiter(thisArg, _arguments, P, generator) {
29
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
30
- return new (P || (P = Promise))(function (resolve, reject) {
31
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
32
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
33
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
34
- step((generator = generator.apply(thisArg, _arguments || [])).next());
35
- });
36
- }
37
- function __generator(thisArg, body) {
38
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
39
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
40
- function verb(n) { return function (v) { return step([n, v]); }; }
41
- function step(op) {
42
- if (f) throw new TypeError("Generator is already executing.");
43
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
44
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
45
- if (y = 0, t) op = [op[0] & 2, t.value];
46
- switch (op[0]) {
47
- case 0: case 1: t = op; break;
48
- case 4: _.label++; return { value: op[1], done: false };
49
- case 5: _.label++; y = op[1]; op = [0]; continue;
50
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
51
- default:
52
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
53
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
54
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
55
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
56
- if (t[2]) _.ops.pop();
57
- _.trys.pop(); continue;
58
- }
59
- op = body.call(thisArg, _);
60
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
61
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
62
- }
63
- }
64
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
65
- var e = new Error(message);
66
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
67
- };
68
-
18
+ /* istanbul ignore file */
69
19
  /**
70
20
  * Returns the zero-knowledge artifact paths. Artifacts exist for each tree
71
21
  * depth supported by Semaphore, and they were generated in a trusted-setup.
72
22
  * @param treeDepth The depth of the tree.
73
23
  * @returns The zero-knowledge artifacts paths.
74
24
  */
75
- function getSnarkArtifacts(treeDepth) {
76
- return __awaiter(this, void 0, void 0, function () {
77
- return __generator(this, function (_a) {
78
- requireNumber(treeDepth, "treeDepth");
79
- return [2 /*return*/, {
80
- wasmFilePath: "https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"),
81
- zkeyFilePath: "https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.zkey")
82
- }];
83
- });
84
- });
25
+ async function getSnarkArtifacts(treeDepth) {
26
+ requireNumber(treeDepth, "treeDepth");
27
+ return {
28
+ wasmFilePath: `https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.wasm`,
29
+ zkeyFilePath: `https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.zkey`
30
+ };
85
31
  }
86
32
 
87
33
  /**
@@ -124,89 +70,80 @@ function toBigInt(value) {
124
70
  * or they will be automatically fetched.
125
71
  * @param identity The Semaphore identity.
126
72
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
127
- * @param scope The Semaphore scope.
128
73
  * @param message The Semaphore message.
74
+ * @param scope The Semaphore scope.
129
75
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
130
76
  * @param snarkArtifacts The SNARK artifacts.
131
77
  * @returns The Semaphore proof ready to be verified.
132
78
  */
133
- function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
134
- return __awaiter(this, void 0, void 0, function () {
135
- var merkleProof, leafIndex, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
136
- return __generator(this, function (_b) {
137
- switch (_b.label) {
138
- case 0:
139
- requireDefined(identity, "identity");
140
- requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
141
- requireDefined(message, "message");
142
- requireDefined(scope, "scope");
143
- requireObject(identity, "identity");
144
- requireObject(groupOrMerkleProof, "groupOrMerkleProof");
145
- requireTypes(message, "message", ["string", "bigint", "number", "Uint8Array"]);
146
- requireTypes(scope, "scope", ["string", "bigint", "number", "Uint8Array"]);
147
- if (merkleTreeDepth) {
148
- requireNumber(merkleTreeDepth, "merkleTreeDepth");
149
- }
150
- if (snarkArtifacts) {
151
- requireObject(snarkArtifacts, "snarkArtifacts");
152
- }
153
- // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
154
- // They will be converted to bigints anyway.
155
- message = toBigInt(message);
156
- scope = toBigInt(scope);
157
- // The second parameter can be either a Merkle proof or a group.
158
- // If it is a group the Merkle proof will be calculated here.
159
- if ("siblings" in groupOrMerkleProof) {
160
- merkleProof = groupOrMerkleProof;
161
- }
162
- else {
163
- leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
164
- merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
165
- }
166
- merkleProofLength = merkleProof.siblings.length;
167
- if (merkleTreeDepth !== undefined) {
168
- if (merkleTreeDepth < MIN_DEPTH || merkleTreeDepth > MAX_DEPTH) {
169
- throw new TypeError("The tree depth must be a number between ".concat(MIN_DEPTH, " and ").concat(MAX_DEPTH));
170
- }
171
- }
172
- else {
173
- merkleTreeDepth = merkleProofLength;
174
- }
175
- if (!!snarkArtifacts) return [3 /*break*/, 2];
176
- return [4 /*yield*/, getSnarkArtifacts(merkleTreeDepth)];
177
- case 1:
178
- snarkArtifacts = _b.sent();
179
- _b.label = 2;
180
- case 2:
181
- merkleProofIndices = [];
182
- merkleProofSiblings = merkleProof.siblings;
183
- for (i = 0; i < merkleTreeDepth; i += 1) {
184
- merkleProofIndices.push((merkleProof.index >> i) & 1);
185
- if (merkleProofSiblings[i] === undefined) {
186
- merkleProofSiblings[i] = "0";
187
- }
188
- }
189
- return [4 /*yield*/, groth16.fullProve({
190
- secret: identity.secretScalar,
191
- merkleProofLength: merkleProofLength,
192
- merkleProofIndices: merkleProofIndices,
193
- merkleProofSiblings: merkleProofSiblings,
194
- scope: hash(scope),
195
- message: hash(message)
196
- }, snarkArtifacts.wasmFilePath, snarkArtifacts.zkeyFilePath)];
197
- case 3:
198
- _a = _b.sent(), proof = _a.proof, publicSignals = _a.publicSignals;
199
- return [2 /*return*/, {
200
- merkleTreeDepth: merkleTreeDepth,
201
- merkleTreeRoot: publicSignals[0],
202
- nullifier: publicSignals[1],
203
- message: message.toString(),
204
- scope: scope.toString(),
205
- points: packGroth16Proof(proof)
206
- }];
207
- }
208
- });
209
- });
79
+ async function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
80
+ requireDefined(identity, "identity");
81
+ requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
82
+ requireDefined(message, "message");
83
+ requireDefined(scope, "scope");
84
+ requireObject(identity, "identity");
85
+ requireObject(groupOrMerkleProof, "groupOrMerkleProof");
86
+ requireTypes(message, "message", ["string", "bigint", "number", "Uint8Array"]);
87
+ requireTypes(scope, "scope", ["string", "bigint", "number", "Uint8Array"]);
88
+ if (merkleTreeDepth) {
89
+ requireNumber(merkleTreeDepth, "merkleTreeDepth");
90
+ }
91
+ if (snarkArtifacts) {
92
+ requireObject(snarkArtifacts, "snarkArtifacts");
93
+ }
94
+ // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
95
+ // They will be converted to bigints anyway.
96
+ message = toBigInt(message);
97
+ scope = toBigInt(scope);
98
+ let merkleProof;
99
+ // The second parameter can be either a Merkle proof or a group.
100
+ // If it is a group the Merkle proof will be calculated here.
101
+ if ("siblings" in groupOrMerkleProof) {
102
+ merkleProof = groupOrMerkleProof;
103
+ }
104
+ else {
105
+ const leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
106
+ merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
107
+ }
108
+ const merkleProofLength = merkleProof.siblings.length;
109
+ if (merkleTreeDepth !== undefined) {
110
+ if (merkleTreeDepth < MIN_DEPTH || merkleTreeDepth > MAX_DEPTH) {
111
+ throw new TypeError(`The tree depth must be a number between ${MIN_DEPTH} and ${MAX_DEPTH}`);
112
+ }
113
+ }
114
+ else {
115
+ merkleTreeDepth = merkleProofLength;
116
+ }
117
+ // If the Snark artifacts are not defined they will be automatically downloaded.
118
+ if (!snarkArtifacts) {
119
+ snarkArtifacts = await getSnarkArtifacts(merkleTreeDepth);
120
+ }
121
+ // The index must be converted to a list of indices, 1 for each tree level.
122
+ // The missing siblings can be set to 0, as they won't be used in the circuit.
123
+ const merkleProofIndices = [];
124
+ const merkleProofSiblings = merkleProof.siblings;
125
+ for (let i = 0; i < merkleTreeDepth; i += 1) {
126
+ merkleProofIndices.push((merkleProof.index >> i) & 1);
127
+ if (merkleProofSiblings[i] === undefined) {
128
+ merkleProofSiblings[i] = "0";
129
+ }
130
+ }
131
+ const { proof, publicSignals } = await groth16.fullProve({
132
+ secret: identity.secretScalar,
133
+ merkleProofLength,
134
+ merkleProofIndices,
135
+ merkleProofSiblings,
136
+ scope: hash(scope),
137
+ message: hash(message)
138
+ }, snarkArtifacts.wasmFilePath, snarkArtifacts.zkeyFilePath);
139
+ return {
140
+ merkleTreeDepth,
141
+ merkleTreeRoot: publicSignals[0],
142
+ nullifier: publicSignals[1],
143
+ message: message.toString(),
144
+ scope: scope.toString(),
145
+ points: packGroth16Proof(proof)
146
+ };
210
147
  }
211
148
 
212
149
  var protocol = "groth16";
@@ -789,26 +726,25 @@ var verificationKeys = {
789
726
  * @param proof The Semaphore proof.
790
727
  * @returns True if the proof is valid, false otherwise.
791
728
  */
792
- function verifyProof(proof) {
793
- return __awaiter(this, void 0, void 0, function () {
794
- var merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points, verificationKey;
795
- return __generator(this, function (_a) {
796
- requireDefined(proof, "proof");
797
- requireObject(proof, "proof");
798
- merkleTreeDepth = proof.merkleTreeDepth, merkleTreeRoot = proof.merkleTreeRoot, nullifier = proof.nullifier, message = proof.message, scope = proof.scope, points = proof.points;
799
- requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
800
- requireString(merkleTreeRoot, "proof.merkleTreeRoot");
801
- requireString(nullifier, "proof.nullifier");
802
- requireString(message, "proof.message");
803
- requireString(scope, "proof.scope");
804
- requireArray(points, "proof.points");
805
- if (merkleTreeDepth < MIN_DEPTH || merkleTreeDepth > MAX_DEPTH) {
806
- throw new TypeError("The tree depth must be a number between ".concat(MIN_DEPTH, " and ").concat(MAX_DEPTH));
807
- }
808
- verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
809
- return [2 /*return*/, groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackGroth16Proof(points))];
810
- });
811
- });
729
+ async function verifyProof(proof) {
730
+ requireDefined(proof, "proof");
731
+ requireObject(proof, "proof");
732
+ const { merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points } = proof;
733
+ requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
734
+ requireString(merkleTreeRoot, "proof.merkleTreeRoot");
735
+ requireString(nullifier, "proof.nullifier");
736
+ requireString(message, "proof.message");
737
+ requireString(scope, "proof.scope");
738
+ requireArray(points, "proof.points");
739
+ if (merkleTreeDepth < MIN_DEPTH || merkleTreeDepth > MAX_DEPTH) {
740
+ throw new TypeError(`The tree depth must be a number between ${MIN_DEPTH} and ${MAX_DEPTH}`);
741
+ }
742
+ const verificationKey = {
743
+ ...verificationKeys,
744
+ vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1],
745
+ IC: verificationKeys.IC[merkleTreeDepth - 1]
746
+ };
747
+ return groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackGroth16Proof(points));
812
748
  }
813
749
 
814
750
  export { generateProof, verifyProof };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-beta.3
3
+ * @version 4.0.0-beta.5
4
4
  * @file A library to generate and verify Semaphore proofs.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
@@ -13,94 +13,31 @@ var constants = require('@semaphore-protocol/utils/constants');
13
13
  var errorHandlers = require('@zk-kit/utils/error-handlers');
14
14
  var snarkjs = require('snarkjs');
15
15
  var node_fs = require('node:fs');
16
- var promises$1 = require('node:fs/promises');
16
+ var promises = require('node:fs/promises');
17
17
  var os = require('node:os');
18
18
  var node_path = require('node:path');
19
19
  var node_stream = require('node:stream');
20
- var promises = require('node:stream/promises');
20
+ var promises$1 = require('node:stream/promises');
21
21
  var crypto = require('ethers/crypto');
22
22
  var utils = require('ethers/utils');
23
23
  var abi = require('ethers/abi');
24
24
 
25
- var __assign = function() {
26
- __assign = Object.assign || function __assign(t) {
27
- for (var s, i = 1, n = arguments.length; i < n; i++) {
28
- s = arguments[i];
29
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
30
- }
31
- return t;
32
- };
33
- return __assign.apply(this, arguments);
34
- };
35
- function __awaiter(thisArg, _arguments, P, generator) {
36
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
- return new (P || (P = Promise))(function (resolve, reject) {
38
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
- step((generator = generator.apply(thisArg, _arguments || [])).next());
42
- });
43
- }
44
- function __generator(thisArg, body) {
45
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
46
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
47
- function verb(n) { return function (v) { return step([n, v]); }; }
48
- function step(op) {
49
- if (f) throw new TypeError("Generator is already executing.");
50
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
51
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
52
- if (y = 0, t) op = [op[0] & 2, t.value];
53
- switch (op[0]) {
54
- case 0: case 1: t = op; break;
55
- case 4: _.label++; return { value: op[1], done: false };
56
- case 5: _.label++; y = op[1]; op = [0]; continue;
57
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
58
- default:
59
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
60
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
61
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
62
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
63
- if (t[2]) _.ops.pop();
64
- _.trys.pop(); continue;
65
- }
66
- op = body.call(thisArg, _);
67
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
68
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
69
- }
70
- }
71
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
72
- var e = new Error(message);
73
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
74
- };
75
-
25
+ /* istanbul ignore file */
76
26
  /**
77
27
  * A utility function to download the zero-knowledge artifacts from an external server.
78
28
  * @param url The URL from which to download the artifacts.
79
29
  * @param outputPath The path in which to save the artifacts.
80
30
  */
81
- function download(url, outputPath) {
82
- return __awaiter(this, void 0, void 0, function () {
83
- var response, dir, fileStream;
84
- return __generator(this, function (_a) {
85
- switch (_a.label) {
86
- case 0: return [4 /*yield*/, fetch(url)];
87
- case 1:
88
- response = _a.sent();
89
- if (!response.ok) {
90
- throw new Error("Failed to fetch ".concat(url, ": ").concat(response.statusText));
91
- }
92
- dir = node_path.dirname(outputPath);
93
- return [4 /*yield*/, promises$1.mkdir(dir, { recursive: true })];
94
- case 2:
95
- _a.sent();
96
- fileStream = node_fs.createWriteStream(outputPath);
97
- return [4 /*yield*/, promises.finished(node_stream.Readable.fromWeb(response.body).pipe(fileStream))];
98
- case 3:
99
- _a.sent();
100
- return [2 /*return*/];
101
- }
102
- });
103
- });
31
+ async function download(url, outputPath) {
32
+ const response = await fetch(url);
33
+ if (!response.ok) {
34
+ throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
35
+ }
36
+ // Ensure the directory exists.
37
+ const dir = node_path.dirname(outputPath);
38
+ await promises.mkdir(dir, { recursive: true });
39
+ const fileStream = node_fs.createWriteStream(outputPath);
40
+ await promises$1.finished(node_stream.Readable.fromWeb(response.body).pipe(fileStream));
104
41
  }
105
42
  /**
106
43
  * Downloads the zero-knowledge artifacts and returns their paths.
@@ -109,30 +46,18 @@ function download(url, outputPath) {
109
46
  * @param treeDepth The depth of the tree.
110
47
  * @returns The zero-knowledge artifacts paths.
111
48
  */
112
- function getSnarkArtifacts(treeDepth) {
113
- return __awaiter(this, void 0, void 0, function () {
114
- var tmpDir, tmpPath;
115
- return __generator(this, function (_a) {
116
- switch (_a.label) {
117
- case 0:
118
- errorHandlers.requireNumber(treeDepth, "treeDepth");
119
- tmpDir = "semaphore-proof";
120
- tmpPath = "".concat(os.tmpdir(), "/").concat(tmpDir, "-").concat(treeDepth);
121
- if (!(!node_fs.existsSync(tmpPath) || node_fs.readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
122
- return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"), "".concat(tmpPath, "/semaphore.wasm"))];
123
- case 1:
124
- _a.sent();
125
- return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.zkey"), "".concat(tmpPath, "/semaphore.zkey"))];
126
- case 2:
127
- _a.sent();
128
- _a.label = 3;
129
- case 3: return [2 /*return*/, {
130
- wasmFilePath: "".concat(tmpPath, "/semaphore.wasm"),
131
- zkeyFilePath: "".concat(tmpPath, "/semaphore.zkey")
132
- }];
133
- }
134
- });
135
- });
49
+ async function getSnarkArtifacts(treeDepth) {
50
+ errorHandlers.requireNumber(treeDepth, "treeDepth");
51
+ const tmpDir = "semaphore-proof";
52
+ const tmpPath = `${os.tmpdir()}/${tmpDir}-${treeDepth}`;
53
+ if (!node_fs.existsSync(tmpPath) || node_fs.readdirSync(tmpPath).length !== 2) {
54
+ await download(`https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.wasm`, `${tmpPath}/semaphore.wasm`);
55
+ await download(`https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.zkey`, `${tmpPath}/semaphore.zkey`);
56
+ }
57
+ return {
58
+ wasmFilePath: `${tmpPath}/semaphore.wasm`,
59
+ zkeyFilePath: `${tmpPath}/semaphore.zkey`
60
+ };
136
61
  }
137
62
 
138
63
  /**
@@ -175,89 +100,80 @@ function toBigInt(value) {
175
100
  * or they will be automatically fetched.
176
101
  * @param identity The Semaphore identity.
177
102
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
178
- * @param scope The Semaphore scope.
179
103
  * @param message The Semaphore message.
104
+ * @param scope The Semaphore scope.
180
105
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
181
106
  * @param snarkArtifacts The SNARK artifacts.
182
107
  * @returns The Semaphore proof ready to be verified.
183
108
  */
184
- function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
185
- return __awaiter(this, void 0, void 0, function () {
186
- var merkleProof, leafIndex, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
187
- return __generator(this, function (_b) {
188
- switch (_b.label) {
189
- case 0:
190
- errorHandlers.requireDefined(identity, "identity");
191
- errorHandlers.requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
192
- errorHandlers.requireDefined(message, "message");
193
- errorHandlers.requireDefined(scope, "scope");
194
- errorHandlers.requireObject(identity, "identity");
195
- errorHandlers.requireObject(groupOrMerkleProof, "groupOrMerkleProof");
196
- errorHandlers.requireTypes(message, "message", ["string", "bigint", "number", "Uint8Array"]);
197
- errorHandlers.requireTypes(scope, "scope", ["string", "bigint", "number", "Uint8Array"]);
198
- if (merkleTreeDepth) {
199
- errorHandlers.requireNumber(merkleTreeDepth, "merkleTreeDepth");
200
- }
201
- if (snarkArtifacts) {
202
- errorHandlers.requireObject(snarkArtifacts, "snarkArtifacts");
203
- }
204
- // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
205
- // They will be converted to bigints anyway.
206
- message = toBigInt(message);
207
- scope = toBigInt(scope);
208
- // The second parameter can be either a Merkle proof or a group.
209
- // If it is a group the Merkle proof will be calculated here.
210
- if ("siblings" in groupOrMerkleProof) {
211
- merkleProof = groupOrMerkleProof;
212
- }
213
- else {
214
- leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
215
- merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
216
- }
217
- merkleProofLength = merkleProof.siblings.length;
218
- if (merkleTreeDepth !== undefined) {
219
- if (merkleTreeDepth < constants.MIN_DEPTH || merkleTreeDepth > constants.MAX_DEPTH) {
220
- throw new TypeError("The tree depth must be a number between ".concat(constants.MIN_DEPTH, " and ").concat(constants.MAX_DEPTH));
221
- }
222
- }
223
- else {
224
- merkleTreeDepth = merkleProofLength;
225
- }
226
- if (!!snarkArtifacts) return [3 /*break*/, 2];
227
- return [4 /*yield*/, getSnarkArtifacts(merkleTreeDepth)];
228
- case 1:
229
- snarkArtifacts = _b.sent();
230
- _b.label = 2;
231
- case 2:
232
- merkleProofIndices = [];
233
- merkleProofSiblings = merkleProof.siblings;
234
- for (i = 0; i < merkleTreeDepth; i += 1) {
235
- merkleProofIndices.push((merkleProof.index >> i) & 1);
236
- if (merkleProofSiblings[i] === undefined) {
237
- merkleProofSiblings[i] = "0";
238
- }
239
- }
240
- return [4 /*yield*/, snarkjs.groth16.fullProve({
241
- secret: identity.secretScalar,
242
- merkleProofLength: merkleProofLength,
243
- merkleProofIndices: merkleProofIndices,
244
- merkleProofSiblings: merkleProofSiblings,
245
- scope: hash(scope),
246
- message: hash(message)
247
- }, snarkArtifacts.wasmFilePath, snarkArtifacts.zkeyFilePath)];
248
- case 3:
249
- _a = _b.sent(), proof = _a.proof, publicSignals = _a.publicSignals;
250
- return [2 /*return*/, {
251
- merkleTreeDepth: merkleTreeDepth,
252
- merkleTreeRoot: publicSignals[0],
253
- nullifier: publicSignals[1],
254
- message: message.toString(),
255
- scope: scope.toString(),
256
- points: proofPacking.packGroth16Proof(proof)
257
- }];
258
- }
259
- });
260
- });
109
+ async function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
110
+ errorHandlers.requireDefined(identity, "identity");
111
+ errorHandlers.requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
112
+ errorHandlers.requireDefined(message, "message");
113
+ errorHandlers.requireDefined(scope, "scope");
114
+ errorHandlers.requireObject(identity, "identity");
115
+ errorHandlers.requireObject(groupOrMerkleProof, "groupOrMerkleProof");
116
+ errorHandlers.requireTypes(message, "message", ["string", "bigint", "number", "Uint8Array"]);
117
+ errorHandlers.requireTypes(scope, "scope", ["string", "bigint", "number", "Uint8Array"]);
118
+ if (merkleTreeDepth) {
119
+ errorHandlers.requireNumber(merkleTreeDepth, "merkleTreeDepth");
120
+ }
121
+ if (snarkArtifacts) {
122
+ errorHandlers.requireObject(snarkArtifacts, "snarkArtifacts");
123
+ }
124
+ // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
125
+ // They will be converted to bigints anyway.
126
+ message = toBigInt(message);
127
+ scope = toBigInt(scope);
128
+ let merkleProof;
129
+ // The second parameter can be either a Merkle proof or a group.
130
+ // If it is a group the Merkle proof will be calculated here.
131
+ if ("siblings" in groupOrMerkleProof) {
132
+ merkleProof = groupOrMerkleProof;
133
+ }
134
+ else {
135
+ const leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
136
+ merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
137
+ }
138
+ const merkleProofLength = merkleProof.siblings.length;
139
+ if (merkleTreeDepth !== undefined) {
140
+ if (merkleTreeDepth < constants.MIN_DEPTH || merkleTreeDepth > constants.MAX_DEPTH) {
141
+ throw new TypeError(`The tree depth must be a number between ${constants.MIN_DEPTH} and ${constants.MAX_DEPTH}`);
142
+ }
143
+ }
144
+ else {
145
+ merkleTreeDepth = merkleProofLength;
146
+ }
147
+ // If the Snark artifacts are not defined they will be automatically downloaded.
148
+ if (!snarkArtifacts) {
149
+ snarkArtifacts = await getSnarkArtifacts(merkleTreeDepth);
150
+ }
151
+ // The index must be converted to a list of indices, 1 for each tree level.
152
+ // The missing siblings can be set to 0, as they won't be used in the circuit.
153
+ const merkleProofIndices = [];
154
+ const merkleProofSiblings = merkleProof.siblings;
155
+ for (let i = 0; i < merkleTreeDepth; i += 1) {
156
+ merkleProofIndices.push((merkleProof.index >> i) & 1);
157
+ if (merkleProofSiblings[i] === undefined) {
158
+ merkleProofSiblings[i] = "0";
159
+ }
160
+ }
161
+ const { proof, publicSignals } = await snarkjs.groth16.fullProve({
162
+ secret: identity.secretScalar,
163
+ merkleProofLength,
164
+ merkleProofIndices,
165
+ merkleProofSiblings,
166
+ scope: hash(scope),
167
+ message: hash(message)
168
+ }, snarkArtifacts.wasmFilePath, snarkArtifacts.zkeyFilePath);
169
+ return {
170
+ merkleTreeDepth,
171
+ merkleTreeRoot: publicSignals[0],
172
+ nullifier: publicSignals[1],
173
+ message: message.toString(),
174
+ scope: scope.toString(),
175
+ points: proofPacking.packGroth16Proof(proof)
176
+ };
261
177
  }
262
178
 
263
179
  var protocol = "groth16";
@@ -840,26 +756,25 @@ var verificationKeys = {
840
756
  * @param proof The Semaphore proof.
841
757
  * @returns True if the proof is valid, false otherwise.
842
758
  */
843
- function verifyProof(proof) {
844
- return __awaiter(this, void 0, void 0, function () {
845
- var merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points, verificationKey;
846
- return __generator(this, function (_a) {
847
- errorHandlers.requireDefined(proof, "proof");
848
- errorHandlers.requireObject(proof, "proof");
849
- merkleTreeDepth = proof.merkleTreeDepth, merkleTreeRoot = proof.merkleTreeRoot, nullifier = proof.nullifier, message = proof.message, scope = proof.scope, points = proof.points;
850
- errorHandlers.requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
851
- errorHandlers.requireString(merkleTreeRoot, "proof.merkleTreeRoot");
852
- errorHandlers.requireString(nullifier, "proof.nullifier");
853
- errorHandlers.requireString(message, "proof.message");
854
- errorHandlers.requireString(scope, "proof.scope");
855
- errorHandlers.requireArray(points, "proof.points");
856
- if (merkleTreeDepth < constants.MIN_DEPTH || merkleTreeDepth > constants.MAX_DEPTH) {
857
- throw new TypeError("The tree depth must be a number between ".concat(constants.MIN_DEPTH, " and ").concat(constants.MAX_DEPTH));
858
- }
859
- verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
860
- return [2 /*return*/, snarkjs.groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], proofPacking.unpackGroth16Proof(points))];
861
- });
862
- });
759
+ async function verifyProof(proof) {
760
+ errorHandlers.requireDefined(proof, "proof");
761
+ errorHandlers.requireObject(proof, "proof");
762
+ const { merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points } = proof;
763
+ errorHandlers.requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
764
+ errorHandlers.requireString(merkleTreeRoot, "proof.merkleTreeRoot");
765
+ errorHandlers.requireString(nullifier, "proof.nullifier");
766
+ errorHandlers.requireString(message, "proof.message");
767
+ errorHandlers.requireString(scope, "proof.scope");
768
+ errorHandlers.requireArray(points, "proof.points");
769
+ if (merkleTreeDepth < constants.MIN_DEPTH || merkleTreeDepth > constants.MAX_DEPTH) {
770
+ throw new TypeError(`The tree depth must be a number between ${constants.MIN_DEPTH} and ${constants.MAX_DEPTH}`);
771
+ }
772
+ const verificationKey = {
773
+ ...verificationKeys,
774
+ vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1],
775
+ IC: verificationKeys.IC[merkleTreeDepth - 1]
776
+ };
777
+ return snarkjs.groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], proofPacking.unpackGroth16Proof(points));
863
778
  }
864
779
 
865
780
  Object.defineProperty(exports, "packGroth16Proof", {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/proof
3
- * @version 4.0.0-beta.3
3
+ * @version 4.0.0-beta.5
4
4
  * @file A library to generate and verify Semaphore proofs.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
@@ -21,85 +21,22 @@ import { keccak256 } from 'ethers/crypto';
21
21
  import { toBeHex, toBigInt as toBigInt$1 } from 'ethers/utils';
22
22
  import { encodeBytes32String } from 'ethers/abi';
23
23
 
24
- var __assign = function() {
25
- __assign = Object.assign || function __assign(t) {
26
- for (var s, i = 1, n = arguments.length; i < n; i++) {
27
- s = arguments[i];
28
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
29
- }
30
- return t;
31
- };
32
- return __assign.apply(this, arguments);
33
- };
34
- function __awaiter(thisArg, _arguments, P, generator) {
35
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
36
- return new (P || (P = Promise))(function (resolve, reject) {
37
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
38
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
39
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
40
- step((generator = generator.apply(thisArg, _arguments || [])).next());
41
- });
42
- }
43
- function __generator(thisArg, body) {
44
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
45
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
46
- function verb(n) { return function (v) { return step([n, v]); }; }
47
- function step(op) {
48
- if (f) throw new TypeError("Generator is already executing.");
49
- while (g && (g = 0, op[0] && (_ = 0)), _) try {
50
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
51
- if (y = 0, t) op = [op[0] & 2, t.value];
52
- switch (op[0]) {
53
- case 0: case 1: t = op; break;
54
- case 4: _.label++; return { value: op[1], done: false };
55
- case 5: _.label++; y = op[1]; op = [0]; continue;
56
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
57
- default:
58
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
59
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
60
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
61
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
62
- if (t[2]) _.ops.pop();
63
- _.trys.pop(); continue;
64
- }
65
- op = body.call(thisArg, _);
66
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
67
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
68
- }
69
- }
70
- typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
71
- var e = new Error(message);
72
- return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
73
- };
74
-
24
+ /* istanbul ignore file */
75
25
  /**
76
26
  * A utility function to download the zero-knowledge artifacts from an external server.
77
27
  * @param url The URL from which to download the artifacts.
78
28
  * @param outputPath The path in which to save the artifacts.
79
29
  */
80
- function download(url, outputPath) {
81
- return __awaiter(this, void 0, void 0, function () {
82
- var response, dir, fileStream;
83
- return __generator(this, function (_a) {
84
- switch (_a.label) {
85
- case 0: return [4 /*yield*/, fetch(url)];
86
- case 1:
87
- response = _a.sent();
88
- if (!response.ok) {
89
- throw new Error("Failed to fetch ".concat(url, ": ").concat(response.statusText));
90
- }
91
- dir = dirname(outputPath);
92
- return [4 /*yield*/, mkdir(dir, { recursive: true })];
93
- case 2:
94
- _a.sent();
95
- fileStream = createWriteStream(outputPath);
96
- return [4 /*yield*/, finished(Readable.fromWeb(response.body).pipe(fileStream))];
97
- case 3:
98
- _a.sent();
99
- return [2 /*return*/];
100
- }
101
- });
102
- });
30
+ async function download(url, outputPath) {
31
+ const response = await fetch(url);
32
+ if (!response.ok) {
33
+ throw new Error(`Failed to fetch ${url}: ${response.statusText}`);
34
+ }
35
+ // Ensure the directory exists.
36
+ const dir = dirname(outputPath);
37
+ await mkdir(dir, { recursive: true });
38
+ const fileStream = createWriteStream(outputPath);
39
+ await finished(Readable.fromWeb(response.body).pipe(fileStream));
103
40
  }
104
41
  /**
105
42
  * Downloads the zero-knowledge artifacts and returns their paths.
@@ -108,30 +45,18 @@ function download(url, outputPath) {
108
45
  * @param treeDepth The depth of the tree.
109
46
  * @returns The zero-knowledge artifacts paths.
110
47
  */
111
- function getSnarkArtifacts(treeDepth) {
112
- return __awaiter(this, void 0, void 0, function () {
113
- var tmpDir, tmpPath;
114
- return __generator(this, function (_a) {
115
- switch (_a.label) {
116
- case 0:
117
- requireNumber(treeDepth, "treeDepth");
118
- tmpDir = "semaphore-proof";
119
- tmpPath = "".concat(os.tmpdir(), "/").concat(tmpDir, "-").concat(treeDepth);
120
- if (!(!existsSync(tmpPath) || readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
121
- return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"), "".concat(tmpPath, "/semaphore.wasm"))];
122
- case 1:
123
- _a.sent();
124
- return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.zkey"), "".concat(tmpPath, "/semaphore.zkey"))];
125
- case 2:
126
- _a.sent();
127
- _a.label = 3;
128
- case 3: return [2 /*return*/, {
129
- wasmFilePath: "".concat(tmpPath, "/semaphore.wasm"),
130
- zkeyFilePath: "".concat(tmpPath, "/semaphore.zkey")
131
- }];
132
- }
133
- });
134
- });
48
+ async function getSnarkArtifacts(treeDepth) {
49
+ requireNumber(treeDepth, "treeDepth");
50
+ const tmpDir = "semaphore-proof";
51
+ const tmpPath = `${os.tmpdir()}/${tmpDir}-${treeDepth}`;
52
+ if (!existsSync(tmpPath) || readdirSync(tmpPath).length !== 2) {
53
+ await download(`https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.wasm`, `${tmpPath}/semaphore.wasm`);
54
+ await download(`https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.zkey`, `${tmpPath}/semaphore.zkey`);
55
+ }
56
+ return {
57
+ wasmFilePath: `${tmpPath}/semaphore.wasm`,
58
+ zkeyFilePath: `${tmpPath}/semaphore.zkey`
59
+ };
135
60
  }
136
61
 
137
62
  /**
@@ -174,89 +99,80 @@ function toBigInt(value) {
174
99
  * or they will be automatically fetched.
175
100
  * @param identity The Semaphore identity.
176
101
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
177
- * @param scope The Semaphore scope.
178
102
  * @param message The Semaphore message.
103
+ * @param scope The Semaphore scope.
179
104
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
180
105
  * @param snarkArtifacts The SNARK artifacts.
181
106
  * @returns The Semaphore proof ready to be verified.
182
107
  */
183
- function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
184
- return __awaiter(this, void 0, void 0, function () {
185
- var merkleProof, leafIndex, merkleProofLength, merkleProofIndices, merkleProofSiblings, i, _a, proof, publicSignals;
186
- return __generator(this, function (_b) {
187
- switch (_b.label) {
188
- case 0:
189
- requireDefined(identity, "identity");
190
- requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
191
- requireDefined(message, "message");
192
- requireDefined(scope, "scope");
193
- requireObject(identity, "identity");
194
- requireObject(groupOrMerkleProof, "groupOrMerkleProof");
195
- requireTypes(message, "message", ["string", "bigint", "number", "Uint8Array"]);
196
- requireTypes(scope, "scope", ["string", "bigint", "number", "Uint8Array"]);
197
- if (merkleTreeDepth) {
198
- requireNumber(merkleTreeDepth, "merkleTreeDepth");
199
- }
200
- if (snarkArtifacts) {
201
- requireObject(snarkArtifacts, "snarkArtifacts");
202
- }
203
- // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
204
- // They will be converted to bigints anyway.
205
- message = toBigInt(message);
206
- scope = toBigInt(scope);
207
- // The second parameter can be either a Merkle proof or a group.
208
- // If it is a group the Merkle proof will be calculated here.
209
- if ("siblings" in groupOrMerkleProof) {
210
- merkleProof = groupOrMerkleProof;
211
- }
212
- else {
213
- leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
214
- merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
215
- }
216
- merkleProofLength = merkleProof.siblings.length;
217
- if (merkleTreeDepth !== undefined) {
218
- if (merkleTreeDepth < MIN_DEPTH || merkleTreeDepth > MAX_DEPTH) {
219
- throw new TypeError("The tree depth must be a number between ".concat(MIN_DEPTH, " and ").concat(MAX_DEPTH));
220
- }
221
- }
222
- else {
223
- merkleTreeDepth = merkleProofLength;
224
- }
225
- if (!!snarkArtifacts) return [3 /*break*/, 2];
226
- return [4 /*yield*/, getSnarkArtifacts(merkleTreeDepth)];
227
- case 1:
228
- snarkArtifacts = _b.sent();
229
- _b.label = 2;
230
- case 2:
231
- merkleProofIndices = [];
232
- merkleProofSiblings = merkleProof.siblings;
233
- for (i = 0; i < merkleTreeDepth; i += 1) {
234
- merkleProofIndices.push((merkleProof.index >> i) & 1);
235
- if (merkleProofSiblings[i] === undefined) {
236
- merkleProofSiblings[i] = "0";
237
- }
238
- }
239
- return [4 /*yield*/, groth16.fullProve({
240
- secret: identity.secretScalar,
241
- merkleProofLength: merkleProofLength,
242
- merkleProofIndices: merkleProofIndices,
243
- merkleProofSiblings: merkleProofSiblings,
244
- scope: hash(scope),
245
- message: hash(message)
246
- }, snarkArtifacts.wasmFilePath, snarkArtifacts.zkeyFilePath)];
247
- case 3:
248
- _a = _b.sent(), proof = _a.proof, publicSignals = _a.publicSignals;
249
- return [2 /*return*/, {
250
- merkleTreeDepth: merkleTreeDepth,
251
- merkleTreeRoot: publicSignals[0],
252
- nullifier: publicSignals[1],
253
- message: message.toString(),
254
- scope: scope.toString(),
255
- points: packGroth16Proof(proof)
256
- }];
257
- }
258
- });
259
- });
108
+ async function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeDepth, snarkArtifacts) {
109
+ requireDefined(identity, "identity");
110
+ requireDefined(groupOrMerkleProof, "groupOrMerkleProof");
111
+ requireDefined(message, "message");
112
+ requireDefined(scope, "scope");
113
+ requireObject(identity, "identity");
114
+ requireObject(groupOrMerkleProof, "groupOrMerkleProof");
115
+ requireTypes(message, "message", ["string", "bigint", "number", "Uint8Array"]);
116
+ requireTypes(scope, "scope", ["string", "bigint", "number", "Uint8Array"]);
117
+ if (merkleTreeDepth) {
118
+ requireNumber(merkleTreeDepth, "merkleTreeDepth");
119
+ }
120
+ if (snarkArtifacts) {
121
+ requireObject(snarkArtifacts, "snarkArtifacts");
122
+ }
123
+ // Message and scope can be strings, numbers or buffers (i.e. Uint8Array).
124
+ // They will be converted to bigints anyway.
125
+ message = toBigInt(message);
126
+ scope = toBigInt(scope);
127
+ let merkleProof;
128
+ // The second parameter can be either a Merkle proof or a group.
129
+ // If it is a group the Merkle proof will be calculated here.
130
+ if ("siblings" in groupOrMerkleProof) {
131
+ merkleProof = groupOrMerkleProof;
132
+ }
133
+ else {
134
+ const leafIndex = groupOrMerkleProof.indexOf(identity.commitment);
135
+ merkleProof = groupOrMerkleProof.generateMerkleProof(leafIndex);
136
+ }
137
+ const merkleProofLength = merkleProof.siblings.length;
138
+ if (merkleTreeDepth !== undefined) {
139
+ if (merkleTreeDepth < MIN_DEPTH || merkleTreeDepth > MAX_DEPTH) {
140
+ throw new TypeError(`The tree depth must be a number between ${MIN_DEPTH} and ${MAX_DEPTH}`);
141
+ }
142
+ }
143
+ else {
144
+ merkleTreeDepth = merkleProofLength;
145
+ }
146
+ // If the Snark artifacts are not defined they will be automatically downloaded.
147
+ if (!snarkArtifacts) {
148
+ snarkArtifacts = await getSnarkArtifacts(merkleTreeDepth);
149
+ }
150
+ // The index must be converted to a list of indices, 1 for each tree level.
151
+ // The missing siblings can be set to 0, as they won't be used in the circuit.
152
+ const merkleProofIndices = [];
153
+ const merkleProofSiblings = merkleProof.siblings;
154
+ for (let i = 0; i < merkleTreeDepth; i += 1) {
155
+ merkleProofIndices.push((merkleProof.index >> i) & 1);
156
+ if (merkleProofSiblings[i] === undefined) {
157
+ merkleProofSiblings[i] = "0";
158
+ }
159
+ }
160
+ const { proof, publicSignals } = await groth16.fullProve({
161
+ secret: identity.secretScalar,
162
+ merkleProofLength,
163
+ merkleProofIndices,
164
+ merkleProofSiblings,
165
+ scope: hash(scope),
166
+ message: hash(message)
167
+ }, snarkArtifacts.wasmFilePath, snarkArtifacts.zkeyFilePath);
168
+ return {
169
+ merkleTreeDepth,
170
+ merkleTreeRoot: publicSignals[0],
171
+ nullifier: publicSignals[1],
172
+ message: message.toString(),
173
+ scope: scope.toString(),
174
+ points: packGroth16Proof(proof)
175
+ };
260
176
  }
261
177
 
262
178
  var protocol = "groth16";
@@ -839,26 +755,25 @@ var verificationKeys = {
839
755
  * @param proof The Semaphore proof.
840
756
  * @returns True if the proof is valid, false otherwise.
841
757
  */
842
- function verifyProof(proof) {
843
- return __awaiter(this, void 0, void 0, function () {
844
- var merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points, verificationKey;
845
- return __generator(this, function (_a) {
846
- requireDefined(proof, "proof");
847
- requireObject(proof, "proof");
848
- merkleTreeDepth = proof.merkleTreeDepth, merkleTreeRoot = proof.merkleTreeRoot, nullifier = proof.nullifier, message = proof.message, scope = proof.scope, points = proof.points;
849
- requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
850
- requireString(merkleTreeRoot, "proof.merkleTreeRoot");
851
- requireString(nullifier, "proof.nullifier");
852
- requireString(message, "proof.message");
853
- requireString(scope, "proof.scope");
854
- requireArray(points, "proof.points");
855
- if (merkleTreeDepth < MIN_DEPTH || merkleTreeDepth > MAX_DEPTH) {
856
- throw new TypeError("The tree depth must be a number between ".concat(MIN_DEPTH, " and ").concat(MAX_DEPTH));
857
- }
858
- verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1], IC: verificationKeys.IC[merkleTreeDepth - 1] });
859
- return [2 /*return*/, groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackGroth16Proof(points))];
860
- });
861
- });
758
+ async function verifyProof(proof) {
759
+ requireDefined(proof, "proof");
760
+ requireObject(proof, "proof");
761
+ const { merkleTreeDepth, merkleTreeRoot, nullifier, message, scope, points } = proof;
762
+ requireNumber(merkleTreeDepth, "proof.merkleTreeDepth");
763
+ requireString(merkleTreeRoot, "proof.merkleTreeRoot");
764
+ requireString(nullifier, "proof.nullifier");
765
+ requireString(message, "proof.message");
766
+ requireString(scope, "proof.scope");
767
+ requireArray(points, "proof.points");
768
+ if (merkleTreeDepth < MIN_DEPTH || merkleTreeDepth > MAX_DEPTH) {
769
+ throw new TypeError(`The tree depth must be a number between ${MIN_DEPTH} and ${MAX_DEPTH}`);
770
+ }
771
+ const verificationKey = {
772
+ ...verificationKeys,
773
+ vk_delta_2: verificationKeys.vk_delta_2[merkleTreeDepth - 1],
774
+ IC: verificationKeys.IC[merkleTreeDepth - 1]
775
+ };
776
+ return groth16.verify(verificationKey, [merkleTreeRoot, nullifier, hash(message), hash(scope)], unpackGroth16Proof(points));
862
777
  }
863
778
 
864
779
  export { generateProof, verifyProof };
@@ -16,8 +16,8 @@ import { SemaphoreProof, SnarkArtifacts } from "./types";
16
16
  * or they will be automatically fetched.
17
17
  * @param identity The Semaphore identity.
18
18
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
19
- * @param scope The Semaphore scope.
20
19
  * @param message The Semaphore message.
20
+ * @param scope The Semaphore scope.
21
21
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
22
22
  * @param snarkArtifacts The SNARK artifacts.
23
23
  * @returns The Semaphore proof ready to be verified.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semaphore-protocol/proof",
3
- "version": "4.0.0-beta.3",
3
+ "version": "4.0.0-beta.5",
4
4
  "description": "A library to generate and verify Semaphore proofs.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -48,16 +48,13 @@
48
48
  "rollup-plugin-cleanup": "^3.2.1"
49
49
  },
50
50
  "peerDependencies": {
51
- "@semaphore-protocol/group": "4.0.0-beta.3",
52
- "@semaphore-protocol/identity": "4.0.0-beta.3"
51
+ "@semaphore-protocol/group": "4.0.0-beta.5",
52
+ "@semaphore-protocol/identity": "4.0.0-beta.5"
53
53
  },
54
54
  "dependencies": {
55
- "@semaphore-protocol/utils": "4.0.0-beta.3",
55
+ "@semaphore-protocol/utils": "4.0.0-beta.5",
56
56
  "@zk-kit/utils": "0.8.1",
57
57
  "ethers": "6.10.0",
58
58
  "snarkjs": "0.7.3"
59
- },
60
- "resolutions": {
61
- "web-worker": "1.2.0"
62
59
  }
63
60
  }
@@ -24,8 +24,8 @@ import { SemaphoreProof, SnarkArtifacts } from "./types"
24
24
  * or they will be automatically fetched.
25
25
  * @param identity The Semaphore identity.
26
26
  * @param groupOrMerkleProof The Semaphore group or its Merkle proof.
27
- * @param scope The Semaphore scope.
28
27
  * @param message The Semaphore message.
28
+ * @param scope The Semaphore scope.
29
29
  * @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
30
30
  * @param snarkArtifacts The SNARK artifacts.
31
31
  * @returns The Semaphore proof ready to be verified.