@semaphore-protocol/proof 0.1.0 → 0.2.0

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