@semaphore-protocol/proof 4.0.0-alpha.6 → 4.0.0-alpha.8
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 +11 -11
- package/dist/index.browser.js +23 -11
- package/dist/index.node.cjs +57 -18
- package/dist/index.node.js +57 -18
- package/dist/types/generate-proof.d.ts +4 -5
- package/dist/types/hash.d.ts +2 -2
- package/dist/types/to-bigint.d.ts +2 -0
- package/package.json +5 -10
- package/src/generate-proof.ts +11 -10
- package/src/get-snark-artifacts.node.ts +31 -7
- package/src/hash.ts +5 -8
- package/src/to-bigint.ts +15 -0
package/README.md
CHANGED
|
@@ -73,8 +73,8 @@ yarn add @semaphore-protocol/identity @semaphore-protocol/group @semaphore-proto
|
|
|
73
73
|
\# **generateProof**(
|
|
74
74
|
identity: _Identity_,
|
|
75
75
|
group: _Group_,
|
|
76
|
-
message:
|
|
77
|
-
scope:
|
|
76
|
+
message: _BigNumberish_ | _Uint8Array_ | string,
|
|
77
|
+
scope: _BigNumberish_ | _Uint8Array_ | string,
|
|
78
78
|
merkleTreeDepth: _number_,
|
|
79
79
|
snarkArtifacts?: _SnarkArtifacts_
|
|
80
80
|
): Promise\<_SemaphoreProof_>
|
|
@@ -83,23 +83,23 @@ snarkArtifacts?: _SnarkArtifacts_
|
|
|
83
83
|
import { Identity } from "@semaphore-protocol/identity"
|
|
84
84
|
import { Group } from "@semaphore-protocol/group"
|
|
85
85
|
import { generateProof } from "@semaphore-protocol/proof"
|
|
86
|
-
import { utils } from "ethers"
|
|
87
86
|
|
|
88
|
-
const
|
|
89
|
-
const
|
|
87
|
+
const identity1 = new Identity()
|
|
88
|
+
const identity2 = new Identity()
|
|
89
|
+
const identity3 = new Identity()
|
|
90
90
|
|
|
91
|
-
const
|
|
92
|
-
const message = utils.formatBytes32String("Hello world")
|
|
91
|
+
const group = new Group([identity1.commitment, identity2.commitment, identity3.commitment])
|
|
93
92
|
|
|
94
|
-
|
|
93
|
+
const message = "Hello world"
|
|
94
|
+
const scope = "Semaphore"
|
|
95
95
|
|
|
96
|
-
const proof1 = await generateProof(
|
|
96
|
+
const proof1 = await generateProof(identity1, group, message, scope)
|
|
97
97
|
|
|
98
98
|
// You can also specify the maximum tree depth supported by the proof.
|
|
99
|
-
const proof2 = await generateProof(
|
|
99
|
+
const proof2 = await generateProof(identity2, group, message, scope, 20)
|
|
100
100
|
|
|
101
101
|
// You can also specify the default zkey/wasm files.
|
|
102
|
-
const proof3 = await generateProof(
|
|
102
|
+
const proof3 = await generateProof(identity3, group, message, scope, 20, {
|
|
103
103
|
wasmFilePath: "./semaphore.wasm",
|
|
104
104
|
zkeyFilePath: "./semaphore.zkey"
|
|
105
105
|
})
|
package/dist/index.browser.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @semaphore-protocol/proof
|
|
3
|
-
* @version 4.0.0-alpha.
|
|
3
|
+
* @version 4.0.0-alpha.8
|
|
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 { BigNumber } from '@ethersproject/bignumber';
|
|
10
9
|
import { groth16 } from 'snarkjs';
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
10
|
+
import { keccak256 } from 'ethers/crypto';
|
|
11
|
+
import { toBeHex, toBigInt as toBigInt$1 } from 'ethers/utils';
|
|
12
|
+
import { encodeBytes32String } from 'ethers/abi';
|
|
13
13
|
|
|
14
14
|
/******************************************************************************
|
|
15
15
|
Copyright (c) Microsoft Corporation.
|
|
@@ -99,9 +99,7 @@ function getSnarkArtifacts(treeDepth) {
|
|
|
99
99
|
* @returns The message digest.
|
|
100
100
|
*/
|
|
101
101
|
function hash(message) {
|
|
102
|
-
|
|
103
|
-
message = zeroPad(message, 32);
|
|
104
|
-
return (BigInt(keccak256(message)) >> BigInt(8)).toString();
|
|
102
|
+
return (BigInt(keccak256(toBeHex(message, 32))) >> BigInt(8)).toString();
|
|
105
103
|
}
|
|
106
104
|
|
|
107
105
|
/**
|
|
@@ -122,12 +120,24 @@ function packPoints(proof) {
|
|
|
122
120
|
];
|
|
123
121
|
}
|
|
124
122
|
|
|
123
|
+
function toBigInt(value) {
|
|
124
|
+
try {
|
|
125
|
+
return toBigInt$1(value);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (typeof value === "string") {
|
|
129
|
+
return toBigInt$1(encodeBytes32String(value));
|
|
130
|
+
}
|
|
131
|
+
throw TypeError(error.message);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
125
135
|
/**
|
|
126
136
|
* Generates a Semaphore proof.
|
|
127
137
|
* @param identity The Semaphore identity.
|
|
128
138
|
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
129
|
-
* @param scope The
|
|
130
|
-
* @param message The Semaphore
|
|
139
|
+
* @param scope The Semaphore scope.
|
|
140
|
+
* @param message The Semaphore message.
|
|
131
141
|
* @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
|
|
132
142
|
* @param snarkArtifacts The SNARK artifacts.
|
|
133
143
|
* @returns The Semaphore proof ready to be verified.
|
|
@@ -138,6 +148,8 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
|
|
|
138
148
|
return __generator(this, function (_b) {
|
|
139
149
|
switch (_b.label) {
|
|
140
150
|
case 0:
|
|
151
|
+
message = toBigInt(message);
|
|
152
|
+
scope = toBigInt(scope);
|
|
141
153
|
if ("siblings" in groupOrMerkleProof) {
|
|
142
154
|
merkleProof = groupOrMerkleProof;
|
|
143
155
|
}
|
|
@@ -182,8 +194,8 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
|
|
|
182
194
|
merkleTreeDepth: merkleTreeDepth,
|
|
183
195
|
merkleTreeRoot: publicSignals[0],
|
|
184
196
|
nullifier: publicSignals[1],
|
|
185
|
-
message:
|
|
186
|
-
scope:
|
|
197
|
+
message: message.toString(),
|
|
198
|
+
scope: scope.toString(),
|
|
187
199
|
points: packPoints(proof)
|
|
188
200
|
}];
|
|
189
201
|
}
|
package/dist/index.node.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @semaphore-protocol/proof
|
|
3
|
-
* @version 4.0.0-alpha.
|
|
3
|
+
* @version 4.0.0-alpha.8
|
|
4
4
|
* @file A library to generate and verify Semaphore proofs.
|
|
5
5
|
* @copyright Ethereum Foundation 2024
|
|
6
6
|
* @license MIT
|
|
@@ -8,13 +8,16 @@
|
|
|
8
8
|
*/
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
|
-
var bignumber = require('@ethersproject/bignumber');
|
|
12
11
|
var snarkjs = require('snarkjs');
|
|
13
|
-
var
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
12
|
+
var node_fs = require('node:fs');
|
|
13
|
+
var promises$1 = require('node:fs/promises');
|
|
14
|
+
var os = require('node:os');
|
|
15
|
+
var node_path = require('node:path');
|
|
16
|
+
var node_stream = require('node:stream');
|
|
17
|
+
var promises = require('node:stream/promises');
|
|
18
|
+
var crypto = require('ethers/crypto');
|
|
19
|
+
var utils = require('ethers/utils');
|
|
20
|
+
var abi = require('ethers/abi');
|
|
18
21
|
|
|
19
22
|
/******************************************************************************
|
|
20
23
|
Copyright (c) Microsoft Corporation.
|
|
@@ -87,6 +90,30 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
87
90
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
88
91
|
};
|
|
89
92
|
|
|
93
|
+
function download(url, outputPath) {
|
|
94
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
95
|
+
var response, dir, fileStream;
|
|
96
|
+
return __generator(this, function (_a) {
|
|
97
|
+
switch (_a.label) {
|
|
98
|
+
case 0: return [4 /*yield*/, fetch(url)];
|
|
99
|
+
case 1:
|
|
100
|
+
response = _a.sent();
|
|
101
|
+
if (!response.ok) {
|
|
102
|
+
throw new Error("Failed to fetch ".concat(url, ": ").concat(response.statusText));
|
|
103
|
+
}
|
|
104
|
+
dir = node_path.dirname(outputPath);
|
|
105
|
+
return [4 /*yield*/, promises$1.mkdir(dir, { recursive: true })];
|
|
106
|
+
case 2:
|
|
107
|
+
_a.sent();
|
|
108
|
+
fileStream = node_fs.createWriteStream(outputPath);
|
|
109
|
+
return [4 /*yield*/, promises.finished(node_stream.Readable.fromWeb(response.body).pipe(fileStream))];
|
|
110
|
+
case 3:
|
|
111
|
+
_a.sent();
|
|
112
|
+
return [2 /*return*/];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
}
|
|
90
117
|
function getSnarkArtifacts(treeDepth) {
|
|
91
118
|
return __awaiter(this, void 0, void 0, function () {
|
|
92
119
|
var tmpDir, tmpPath;
|
|
@@ -94,12 +121,12 @@ function getSnarkArtifacts(treeDepth) {
|
|
|
94
121
|
switch (_a.label) {
|
|
95
122
|
case 0:
|
|
96
123
|
tmpDir = "semaphore-proof";
|
|
97
|
-
tmpPath = "".concat(
|
|
98
|
-
if (!(!
|
|
99
|
-
return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"), tmpPath)];
|
|
124
|
+
tmpPath = "".concat(os.tmpdir(), "/").concat(tmpDir, "-").concat(treeDepth);
|
|
125
|
+
if (!(!node_fs.existsSync(tmpPath) || node_fs.readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
|
|
126
|
+
return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"), "".concat(tmpPath, "/semaphore.wasm"))];
|
|
100
127
|
case 1:
|
|
101
128
|
_a.sent();
|
|
102
|
-
return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.zkey"), tmpPath)];
|
|
129
|
+
return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.zkey"), "".concat(tmpPath, "/semaphore.zkey"))];
|
|
103
130
|
case 2:
|
|
104
131
|
_a.sent();
|
|
105
132
|
_a.label = 3;
|
|
@@ -118,9 +145,7 @@ function getSnarkArtifacts(treeDepth) {
|
|
|
118
145
|
* @returns The message digest.
|
|
119
146
|
*/
|
|
120
147
|
function hash(message) {
|
|
121
|
-
|
|
122
|
-
message = bytes.zeroPad(message, 32);
|
|
123
|
-
return (BigInt(keccak256.keccak256(message)) >> BigInt(8)).toString();
|
|
148
|
+
return (BigInt(crypto.keccak256(utils.toBeHex(message, 32))) >> BigInt(8)).toString();
|
|
124
149
|
}
|
|
125
150
|
|
|
126
151
|
/**
|
|
@@ -141,12 +166,24 @@ function packPoints(proof) {
|
|
|
141
166
|
];
|
|
142
167
|
}
|
|
143
168
|
|
|
169
|
+
function toBigInt(value) {
|
|
170
|
+
try {
|
|
171
|
+
return utils.toBigInt(value);
|
|
172
|
+
}
|
|
173
|
+
catch (error) {
|
|
174
|
+
if (typeof value === "string") {
|
|
175
|
+
return utils.toBigInt(abi.encodeBytes32String(value));
|
|
176
|
+
}
|
|
177
|
+
throw TypeError(error.message);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
144
181
|
/**
|
|
145
182
|
* Generates a Semaphore proof.
|
|
146
183
|
* @param identity The Semaphore identity.
|
|
147
184
|
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
148
|
-
* @param scope The
|
|
149
|
-
* @param message The Semaphore
|
|
185
|
+
* @param scope The Semaphore scope.
|
|
186
|
+
* @param message The Semaphore message.
|
|
150
187
|
* @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
|
|
151
188
|
* @param snarkArtifacts The SNARK artifacts.
|
|
152
189
|
* @returns The Semaphore proof ready to be verified.
|
|
@@ -157,6 +194,8 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
|
|
|
157
194
|
return __generator(this, function (_b) {
|
|
158
195
|
switch (_b.label) {
|
|
159
196
|
case 0:
|
|
197
|
+
message = toBigInt(message);
|
|
198
|
+
scope = toBigInt(scope);
|
|
160
199
|
if ("siblings" in groupOrMerkleProof) {
|
|
161
200
|
merkleProof = groupOrMerkleProof;
|
|
162
201
|
}
|
|
@@ -201,8 +240,8 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
|
|
|
201
240
|
merkleTreeDepth: merkleTreeDepth,
|
|
202
241
|
merkleTreeRoot: publicSignals[0],
|
|
203
242
|
nullifier: publicSignals[1],
|
|
204
|
-
message:
|
|
205
|
-
scope:
|
|
243
|
+
message: message.toString(),
|
|
244
|
+
scope: scope.toString(),
|
|
206
245
|
points: packPoints(proof)
|
|
207
246
|
}];
|
|
208
247
|
}
|
package/dist/index.node.js
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @semaphore-protocol/proof
|
|
3
|
-
* @version 4.0.0-alpha.
|
|
3
|
+
* @version 4.0.0-alpha.8
|
|
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 { BigNumber } from '@ethersproject/bignumber';
|
|
10
9
|
import { groth16 } from 'snarkjs';
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
10
|
+
import { existsSync, readdirSync, createWriteStream } from 'node:fs';
|
|
11
|
+
import { mkdir } from 'node:fs/promises';
|
|
12
|
+
import os from 'node:os';
|
|
13
|
+
import { dirname } from 'node:path';
|
|
14
|
+
import { Readable } from 'node:stream';
|
|
15
|
+
import { finished } from 'node:stream/promises';
|
|
16
|
+
import { keccak256 } from 'ethers/crypto';
|
|
17
|
+
import { toBeHex, toBigInt as toBigInt$1 } from 'ethers/utils';
|
|
18
|
+
import { encodeBytes32String } from 'ethers/abi';
|
|
16
19
|
|
|
17
20
|
/******************************************************************************
|
|
18
21
|
Copyright (c) Microsoft Corporation.
|
|
@@ -85,6 +88,30 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
85
88
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
86
89
|
};
|
|
87
90
|
|
|
91
|
+
function download(url, outputPath) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
93
|
+
var response, dir, fileStream;
|
|
94
|
+
return __generator(this, function (_a) {
|
|
95
|
+
switch (_a.label) {
|
|
96
|
+
case 0: return [4 /*yield*/, fetch(url)];
|
|
97
|
+
case 1:
|
|
98
|
+
response = _a.sent();
|
|
99
|
+
if (!response.ok) {
|
|
100
|
+
throw new Error("Failed to fetch ".concat(url, ": ").concat(response.statusText));
|
|
101
|
+
}
|
|
102
|
+
dir = dirname(outputPath);
|
|
103
|
+
return [4 /*yield*/, mkdir(dir, { recursive: true })];
|
|
104
|
+
case 2:
|
|
105
|
+
_a.sent();
|
|
106
|
+
fileStream = createWriteStream(outputPath);
|
|
107
|
+
return [4 /*yield*/, finished(Readable.fromWeb(response.body).pipe(fileStream))];
|
|
108
|
+
case 3:
|
|
109
|
+
_a.sent();
|
|
110
|
+
return [2 /*return*/];
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
88
115
|
function getSnarkArtifacts(treeDepth) {
|
|
89
116
|
return __awaiter(this, void 0, void 0, function () {
|
|
90
117
|
var tmpDir, tmpPath;
|
|
@@ -92,12 +119,12 @@ function getSnarkArtifacts(treeDepth) {
|
|
|
92
119
|
switch (_a.label) {
|
|
93
120
|
case 0:
|
|
94
121
|
tmpDir = "semaphore-proof";
|
|
95
|
-
tmpPath = "".concat(
|
|
96
|
-
if (!(!
|
|
97
|
-
return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"), tmpPath)];
|
|
122
|
+
tmpPath = "".concat(os.tmpdir(), "/").concat(tmpDir, "-").concat(treeDepth);
|
|
123
|
+
if (!(!existsSync(tmpPath) || readdirSync(tmpPath).length !== 2)) return [3 /*break*/, 3];
|
|
124
|
+
return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.wasm"), "".concat(tmpPath, "/semaphore.wasm"))];
|
|
98
125
|
case 1:
|
|
99
126
|
_a.sent();
|
|
100
|
-
return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.zkey"), tmpPath)];
|
|
127
|
+
return [4 /*yield*/, download("https://semaphore.cedoor.dev/artifacts/".concat(treeDepth, "/semaphore.zkey"), "".concat(tmpPath, "/semaphore.zkey"))];
|
|
101
128
|
case 2:
|
|
102
129
|
_a.sent();
|
|
103
130
|
_a.label = 3;
|
|
@@ -116,9 +143,7 @@ function getSnarkArtifacts(treeDepth) {
|
|
|
116
143
|
* @returns The message digest.
|
|
117
144
|
*/
|
|
118
145
|
function hash(message) {
|
|
119
|
-
|
|
120
|
-
message = zeroPad(message, 32);
|
|
121
|
-
return (BigInt(keccak256(message)) >> BigInt(8)).toString();
|
|
146
|
+
return (BigInt(keccak256(toBeHex(message, 32))) >> BigInt(8)).toString();
|
|
122
147
|
}
|
|
123
148
|
|
|
124
149
|
/**
|
|
@@ -139,12 +164,24 @@ function packPoints(proof) {
|
|
|
139
164
|
];
|
|
140
165
|
}
|
|
141
166
|
|
|
167
|
+
function toBigInt(value) {
|
|
168
|
+
try {
|
|
169
|
+
return toBigInt$1(value);
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
if (typeof value === "string") {
|
|
173
|
+
return toBigInt$1(encodeBytes32String(value));
|
|
174
|
+
}
|
|
175
|
+
throw TypeError(error.message);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
142
179
|
/**
|
|
143
180
|
* Generates a Semaphore proof.
|
|
144
181
|
* @param identity The Semaphore identity.
|
|
145
182
|
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
146
|
-
* @param scope The
|
|
147
|
-
* @param message The Semaphore
|
|
183
|
+
* @param scope The Semaphore scope.
|
|
184
|
+
* @param message The Semaphore message.
|
|
148
185
|
* @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
|
|
149
186
|
* @param snarkArtifacts The SNARK artifacts.
|
|
150
187
|
* @returns The Semaphore proof ready to be verified.
|
|
@@ -155,6 +192,8 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
|
|
|
155
192
|
return __generator(this, function (_b) {
|
|
156
193
|
switch (_b.label) {
|
|
157
194
|
case 0:
|
|
195
|
+
message = toBigInt(message);
|
|
196
|
+
scope = toBigInt(scope);
|
|
158
197
|
if ("siblings" in groupOrMerkleProof) {
|
|
159
198
|
merkleProof = groupOrMerkleProof;
|
|
160
199
|
}
|
|
@@ -199,8 +238,8 @@ function generateProof(identity, groupOrMerkleProof, message, scope, merkleTreeD
|
|
|
199
238
|
merkleTreeDepth: merkleTreeDepth,
|
|
200
239
|
merkleTreeRoot: publicSignals[0],
|
|
201
240
|
nullifier: publicSignals[1],
|
|
202
|
-
message:
|
|
203
|
-
scope:
|
|
241
|
+
message: message.toString(),
|
|
242
|
+
scope: scope.toString(),
|
|
204
243
|
points: packPoints(proof)
|
|
205
244
|
}];
|
|
206
245
|
}
|
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
import { BytesLike, Hexable } from "@ethersproject/bytes";
|
|
2
1
|
import type { Group, MerkleProof } from "@semaphore-protocol/group";
|
|
3
2
|
import type { Identity } from "@semaphore-protocol/identity";
|
|
4
|
-
import { SemaphoreProof, SnarkArtifacts } from "./types";
|
|
3
|
+
import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types";
|
|
5
4
|
/**
|
|
6
5
|
* Generates a Semaphore proof.
|
|
7
6
|
* @param identity The Semaphore identity.
|
|
8
7
|
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
9
|
-
* @param scope The
|
|
10
|
-
* @param message The Semaphore
|
|
8
|
+
* @param scope The Semaphore scope.
|
|
9
|
+
* @param message The Semaphore message.
|
|
11
10
|
* @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
|
|
12
11
|
* @param snarkArtifacts The SNARK artifacts.
|
|
13
12
|
* @returns The Semaphore proof ready to be verified.
|
|
14
13
|
*/
|
|
15
|
-
export default function generateProof(identity: Identity, groupOrMerkleProof: Group | MerkleProof, message:
|
|
14
|
+
export default function generateProof(identity: Identity, groupOrMerkleProof: Group | MerkleProof, message: BigNumberish | Uint8Array | string, scope: BigNumberish | Uint8Array | string, merkleTreeDepth?: number, snarkArtifacts?: SnarkArtifacts): Promise<SemaphoreProof>;
|
package/dist/types/hash.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { BytesLike, Hexable } from "@ethersproject/bytes";
|
|
2
1
|
import { NumericString } from "snarkjs";
|
|
2
|
+
import { BigNumberish } from "./types";
|
|
3
3
|
/**
|
|
4
4
|
* Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
|
|
5
5
|
* @param message The message to be hashed.
|
|
6
6
|
* @returns The message digest.
|
|
7
7
|
*/
|
|
8
|
-
export default function hash(message:
|
|
8
|
+
export default function hash(message: BigNumberish): NumericString;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semaphore-protocol/proof",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.8",
|
|
4
4
|
"description": "A library to generate and verify Semaphore proofs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -38,7 +38,6 @@
|
|
|
38
38
|
"access": "public"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"@ethersproject/strings": "^5.7.0",
|
|
42
41
|
"@rollup/plugin-alias": "^5.1.0",
|
|
43
42
|
"@rollup/plugin-json": "^6.1.0",
|
|
44
43
|
"@types/download": "^8.0.5",
|
|
@@ -50,16 +49,12 @@
|
|
|
50
49
|
"rollup-plugin-typescript2": "^0.36.0"
|
|
51
50
|
},
|
|
52
51
|
"peerDependencies": {
|
|
53
|
-
"@semaphore-protocol/group": "4.0.0-alpha.
|
|
54
|
-
"@semaphore-protocol/identity": "4.0.0-alpha.
|
|
52
|
+
"@semaphore-protocol/group": "4.0.0-alpha.8",
|
|
53
|
+
"@semaphore-protocol/identity": "4.0.0-alpha.8"
|
|
55
54
|
},
|
|
56
55
|
"dependencies": {
|
|
57
|
-
"@ethersproject/bignumber": "5.7.0",
|
|
58
|
-
"@ethersproject/bytes": "5.7.0",
|
|
59
|
-
"@ethersproject/keccak256": "5.7.0",
|
|
60
56
|
"@types/snarkjs": "0.7.8",
|
|
61
|
-
"
|
|
62
|
-
"snarkjs": "0.7.3"
|
|
63
|
-
"tmp": "0.2.1"
|
|
57
|
+
"ethers": "6.10.0",
|
|
58
|
+
"snarkjs": "0.7.3"
|
|
64
59
|
}
|
|
65
60
|
}
|
package/src/generate-proof.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
|
-
import { BigNumber } from "@ethersproject/bignumber"
|
|
2
|
-
import { BytesLike, Hexable } from "@ethersproject/bytes"
|
|
3
1
|
import type { Group, MerkleProof } from "@semaphore-protocol/group"
|
|
4
2
|
import type { Identity } from "@semaphore-protocol/identity"
|
|
5
3
|
import { NumericString, groth16 } from "snarkjs"
|
|
6
4
|
import getSnarkArtifacts from "./get-snark-artifacts.node"
|
|
7
5
|
import hash from "./hash"
|
|
8
6
|
import packPoints from "./pack-points"
|
|
9
|
-
import { SemaphoreProof, SnarkArtifacts } from "./types"
|
|
7
|
+
import { BigNumberish, SemaphoreProof, SnarkArtifacts } from "./types"
|
|
8
|
+
import toBigInt from "./to-bigint"
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Generates a Semaphore proof.
|
|
13
12
|
* @param identity The Semaphore identity.
|
|
14
13
|
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
15
|
-
* @param scope The
|
|
16
|
-
* @param message The Semaphore
|
|
14
|
+
* @param scope The Semaphore scope.
|
|
15
|
+
* @param message The Semaphore message.
|
|
17
16
|
* @param merkleTreeDepth The depth of the tree with which the circuit was compiled.
|
|
18
17
|
* @param snarkArtifacts The SNARK artifacts.
|
|
19
18
|
* @returns The Semaphore proof ready to be verified.
|
|
@@ -21,11 +20,14 @@ import { SemaphoreProof, SnarkArtifacts } from "./types"
|
|
|
21
20
|
export default async function generateProof(
|
|
22
21
|
identity: Identity,
|
|
23
22
|
groupOrMerkleProof: Group | MerkleProof,
|
|
24
|
-
message:
|
|
25
|
-
scope:
|
|
23
|
+
message: BigNumberish | Uint8Array | string,
|
|
24
|
+
scope: BigNumberish | Uint8Array | string,
|
|
26
25
|
merkleTreeDepth?: number,
|
|
27
26
|
snarkArtifacts?: SnarkArtifacts
|
|
28
27
|
): Promise<SemaphoreProof> {
|
|
28
|
+
message = toBigInt(message)
|
|
29
|
+
scope = toBigInt(scope)
|
|
30
|
+
|
|
29
31
|
let merkleProof
|
|
30
32
|
|
|
31
33
|
if ("siblings" in groupOrMerkleProof) {
|
|
@@ -46,7 +48,6 @@ export default async function generateProof(
|
|
|
46
48
|
}
|
|
47
49
|
|
|
48
50
|
// If the Snark artifacts are not defined they will be automatically downloaded.
|
|
49
|
-
/* istanbul ignore next */
|
|
50
51
|
if (!snarkArtifacts) {
|
|
51
52
|
snarkArtifacts = await getSnarkArtifacts(merkleTreeDepth)
|
|
52
53
|
}
|
|
@@ -81,8 +82,8 @@ export default async function generateProof(
|
|
|
81
82
|
merkleTreeDepth,
|
|
82
83
|
merkleTreeRoot: publicSignals[0],
|
|
83
84
|
nullifier: publicSignals[1],
|
|
84
|
-
message:
|
|
85
|
-
scope:
|
|
85
|
+
message: message.toString() as NumericString,
|
|
86
|
+
scope: scope.toString() as NumericString,
|
|
86
87
|
points: packPoints(proof)
|
|
87
88
|
}
|
|
88
89
|
}
|
|
@@ -1,16 +1,40 @@
|
|
|
1
1
|
/* istanbul ignore file */
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
2
|
+
import { createWriteStream, existsSync, readdirSync } from "node:fs"
|
|
3
|
+
import { mkdir } from "node:fs/promises"
|
|
4
|
+
import os from "node:os"
|
|
5
|
+
import { dirname } from "node:path"
|
|
6
|
+
import { Readable } from "node:stream"
|
|
7
|
+
import { finished } from "node:stream/promises"
|
|
5
8
|
import { SnarkArtifacts } from "./types"
|
|
6
9
|
|
|
10
|
+
async function download(url: string, outputPath: string) {
|
|
11
|
+
const response = await fetch(url)
|
|
12
|
+
|
|
13
|
+
if (!response.ok) {
|
|
14
|
+
throw new Error(`Failed to fetch ${url}: ${response.statusText}`)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Ensure the directory exists.
|
|
18
|
+
const dir = dirname(outputPath)
|
|
19
|
+
await mkdir(dir, { recursive: true })
|
|
20
|
+
|
|
21
|
+
const fileStream = createWriteStream(outputPath)
|
|
22
|
+
await finished(Readable.fromWeb(response.body as any).pipe(fileStream))
|
|
23
|
+
}
|
|
24
|
+
|
|
7
25
|
export default async function getSnarkArtifacts(treeDepth: number): Promise<SnarkArtifacts> {
|
|
8
26
|
const tmpDir = "semaphore-proof"
|
|
9
|
-
const tmpPath = `${
|
|
27
|
+
const tmpPath = `${os.tmpdir()}/${tmpDir}-${treeDepth}`
|
|
10
28
|
|
|
11
|
-
if (!
|
|
12
|
-
await download(
|
|
13
|
-
|
|
29
|
+
if (!existsSync(tmpPath) || readdirSync(tmpPath).length !== 2) {
|
|
30
|
+
await download(
|
|
31
|
+
`https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.wasm`,
|
|
32
|
+
`${tmpPath}/semaphore.wasm`
|
|
33
|
+
)
|
|
34
|
+
await download(
|
|
35
|
+
`https://semaphore.cedoor.dev/artifacts/${treeDepth}/semaphore.zkey`,
|
|
36
|
+
`${tmpPath}/semaphore.zkey`
|
|
37
|
+
)
|
|
14
38
|
}
|
|
15
39
|
|
|
16
40
|
return {
|
package/src/hash.ts
CHANGED
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { keccak256 } from "@ethersproject/keccak256"
|
|
1
|
+
import { keccak256 } from "ethers/crypto"
|
|
2
|
+
import { toBeHex } from "ethers/utils"
|
|
4
3
|
import { NumericString } from "snarkjs"
|
|
4
|
+
import { BigNumberish } from "./types"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Creates a keccak256 hash of a message compatible with the SNARK scalar modulus.
|
|
8
8
|
* @param message The message to be hashed.
|
|
9
9
|
* @returns The message digest.
|
|
10
10
|
*/
|
|
11
|
-
export default function hash(message:
|
|
12
|
-
|
|
13
|
-
message = zeroPad(message, 32)
|
|
14
|
-
|
|
15
|
-
return (BigInt(keccak256(message)) >> BigInt(8)).toString() as NumericString
|
|
11
|
+
export default function hash(message: BigNumberish): NumericString {
|
|
12
|
+
return (BigInt(keccak256(toBeHex(message, 32))) >> BigInt(8)).toString()
|
|
16
13
|
}
|
package/src/to-bigint.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { encodeBytes32String } from "ethers/abi"
|
|
2
|
+
import { toBigInt as _toBigInt } from "ethers/utils"
|
|
3
|
+
import { BigNumberish } from "./types"
|
|
4
|
+
|
|
5
|
+
export default function toBigInt(value: BigNumberish | Uint8Array | string): bigint {
|
|
6
|
+
try {
|
|
7
|
+
return _toBigInt(value)
|
|
8
|
+
} catch (error: any) {
|
|
9
|
+
if (typeof value === "string") {
|
|
10
|
+
return _toBigInt(encodeBytes32String(value))
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
throw TypeError(error.message)
|
|
14
|
+
}
|
|
15
|
+
}
|