@semaphore-protocol/proof 3.0.0-beta.7 → 3.0.0-beta.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 +3 -27
- package/dist/index.mjs +57 -37
- package/dist/index.node.js +56 -37
- package/dist/types/generateProof.d.ts +9 -0
- package/dist/types/index.d.ts +1 -2
- package/dist/types/packProof.d.ts +7 -0
- package/dist/types/types/index.d.ts +4 -7
- package/dist/types/unpackProof.d.ts +7 -0
- package/dist/types/verifyProof.d.ts +3 -3
- package/package.json +4 -4
- package/src/generateProof.ts +16 -7
- package/src/index.test.ts +18 -11
- package/src/index.ts +1 -2
- package/src/packProof.ts +19 -0
- package/src/types/index.ts +4 -8
- package/src/unpackProof.ts +19 -0
- package/src/verifyProof.ts +10 -10
- package/dist/types/packToSolidityProof.d.ts +0 -7
- package/src/packToSolidityProof.ts +0 -19
package/README.md
CHANGED
|
@@ -73,12 +73,12 @@ yarn add @semaphore-protocol/identity @semaphore-protocol/group @semaphore-proto
|
|
|
73
73
|
import { Identity } from "@semaphore-protocol/identity"
|
|
74
74
|
import { Group } from "@semaphore-protocol/group"
|
|
75
75
|
import { generateProof } from "@semaphore-protocol/proof"
|
|
76
|
-
import {
|
|
76
|
+
import { utils } from "ethers"
|
|
77
77
|
|
|
78
78
|
const identity = new Identity()
|
|
79
79
|
const group = new Group()
|
|
80
|
-
const externalNullifier =
|
|
81
|
-
const signal = formatBytes32String("Hello world")
|
|
80
|
+
const externalNullifier = utils.formatBytes32String("Topic")
|
|
81
|
+
const signal = utils.formatBytes32String("Hello world")
|
|
82
82
|
|
|
83
83
|
group.addMembers([...identityCommitments, identity.generateCommitment()])
|
|
84
84
|
|
|
@@ -98,27 +98,3 @@ import { verifyProof } from "@semaphore-protocol/proof"
|
|
|
98
98
|
|
|
99
99
|
await verifyProof(fullProof, 20)
|
|
100
100
|
```
|
|
101
|
-
|
|
102
|
-
\# **packToSolidityProof**(proof: _Proof_): _SolidityProof_
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
import { packToSolidityProof } from "@semaphore-protocol/proof"
|
|
106
|
-
|
|
107
|
-
const solidityProof = packToSolidityProof(fullProof.proof)
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
\# **generateNullifierHash**(externalNullifier: _BigNumberish_, identityNullifier: _BigNumberish_): _bigint_
|
|
111
|
-
|
|
112
|
-
```typescript
|
|
113
|
-
import { generateNullifierHash } from "@semaphore-protocol/proof"
|
|
114
|
-
|
|
115
|
-
const nullifierHash = generateNullifierHash(externalNullifier, identity.getNullifier())
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
\# **generateSignalHash**(signal: _string_): _bigint_
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import { generateSignalHash } from "@semaphore-protocol/proof"
|
|
122
|
-
|
|
123
|
-
const signalHash = generateSignalHash(signal)
|
|
124
|
-
```
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @semaphore-protocol/proof
|
|
3
|
-
* @version 3.0.0-beta.
|
|
3
|
+
* @version 3.0.0-beta.8
|
|
4
4
|
* @file A library to generate and verify Semaphore proofs.
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
7
7
|
* @see [Github]{@link https://github.com/semaphore-protocol/semaphore/tree/main/packages/proof}
|
|
8
8
|
*/
|
|
9
|
-
import { groth16 } from 'snarkjs';
|
|
10
9
|
import { BigNumber } from '@ethersproject/bignumber';
|
|
10
|
+
import { groth16 } from 'snarkjs';
|
|
11
11
|
import { zeroPad } from '@ethersproject/bytes';
|
|
12
12
|
import { keccak256 } from '@ethersproject/keccak256';
|
|
13
13
|
|
|
@@ -86,6 +86,33 @@ function hash(message) {
|
|
|
86
86
|
return BigInt(keccak256(message)) >> BigInt(8);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* Packs a proof into a format compatible with Semaphore.
|
|
91
|
+
* @param originalProof The proof generated with SnarkJS.
|
|
92
|
+
* @returns The proof compatible with Semaphore.
|
|
93
|
+
*/
|
|
94
|
+
function packProof(originalProof) {
|
|
95
|
+
return [
|
|
96
|
+
originalProof.pi_a[0],
|
|
97
|
+
originalProof.pi_a[1],
|
|
98
|
+
originalProof.pi_b[0][1],
|
|
99
|
+
originalProof.pi_b[0][0],
|
|
100
|
+
originalProof.pi_b[1][1],
|
|
101
|
+
originalProof.pi_b[1][0],
|
|
102
|
+
originalProof.pi_c[0],
|
|
103
|
+
originalProof.pi_c[1]
|
|
104
|
+
];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Generates a Semaphore proof.
|
|
109
|
+
* @param identity The Semaphore identity.
|
|
110
|
+
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
111
|
+
* @param externalNullifier The external nullifier.
|
|
112
|
+
* @param signal The Semaphore signal.
|
|
113
|
+
* @param snarkArtifacts The SNARK artifacts.
|
|
114
|
+
* @returns The Semaphore proof ready to be verified.
|
|
115
|
+
*/
|
|
89
116
|
function generateProof(_a, groupOrMerkleProof, externalNullifier, signal, snarkArtifacts) {
|
|
90
117
|
var trapdoor = _a.trapdoor, nullifier = _a.nullifier, commitment = _a.commitment;
|
|
91
118
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -120,19 +147,35 @@ function generateProof(_a, groupOrMerkleProof, externalNullifier, signal, snarkA
|
|
|
120
147
|
case 1:
|
|
121
148
|
_b = _c.sent(), proof = _b.proof, publicSignals = _b.publicSignals;
|
|
122
149
|
return [2 /*return*/, {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
externalNullifier: publicSignals[3]
|
|
129
|
-
}
|
|
150
|
+
merkleTreeRoot: publicSignals[0],
|
|
151
|
+
nullifierHash: publicSignals[1],
|
|
152
|
+
signal: BigNumber.from(signal).toString(),
|
|
153
|
+
externalNullifier: BigNumber.from(externalNullifier).toString(),
|
|
154
|
+
proof: packProof(proof)
|
|
130
155
|
}];
|
|
131
156
|
}
|
|
132
157
|
});
|
|
133
158
|
});
|
|
134
159
|
}
|
|
135
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Unpacks a proof into its original form.
|
|
163
|
+
* @param proof The proof compatible with Semaphore.
|
|
164
|
+
* @returns The proof compatible with SnarkJS.
|
|
165
|
+
*/
|
|
166
|
+
function unpackProof(proof) {
|
|
167
|
+
return {
|
|
168
|
+
pi_a: [proof[0], proof[1]],
|
|
169
|
+
pi_b: [
|
|
170
|
+
[proof[3], proof[2]],
|
|
171
|
+
[proof[5], proof[4]]
|
|
172
|
+
],
|
|
173
|
+
pi_c: [proof[6], proof[7]],
|
|
174
|
+
protocol: "groth16",
|
|
175
|
+
curve: "bn128"
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
136
179
|
var protocol = "groth16";
|
|
137
180
|
var curve = "bn128";
|
|
138
181
|
var nPublic = 4;
|
|
@@ -913,41 +956,18 @@ var verificationKeys = {
|
|
|
913
956
|
};
|
|
914
957
|
|
|
915
958
|
/**
|
|
916
|
-
* Verifies a
|
|
917
|
-
* @param fullProof The SnarkJS
|
|
959
|
+
* Verifies a Semaphore proof.
|
|
960
|
+
* @param fullProof The SnarkJS Semaphore proof.
|
|
918
961
|
* @param treeDepth The Merkle tree depth.
|
|
919
962
|
* @returns True if the proof is valid, false otherwise.
|
|
920
963
|
*/
|
|
921
964
|
function verifyProof(_a, treeDepth) {
|
|
922
|
-
var
|
|
965
|
+
var merkleTreeRoot = _a.merkleTreeRoot, nullifierHash = _a.nullifierHash, externalNullifier = _a.externalNullifier, signal = _a.signal, proof = _a.proof;
|
|
923
966
|
if (treeDepth < 16 || treeDepth > 32) {
|
|
924
967
|
throw new TypeError("The tree depth must be a number between 16 and 32");
|
|
925
968
|
}
|
|
926
969
|
var verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[treeDepth - 16], IC: verificationKeys.IC[treeDepth - 16] });
|
|
927
|
-
return groth16.verify(verificationKey, [
|
|
928
|
-
publicSignals.merkleTreeRoot,
|
|
929
|
-
publicSignals.nullifierHash,
|
|
930
|
-
publicSignals.signalHash,
|
|
931
|
-
publicSignals.externalNullifier
|
|
932
|
-
], proof);
|
|
933
|
-
}
|
|
934
|
-
|
|
935
|
-
/**
|
|
936
|
-
* Makes a proof compatible with the Verifier.sol method inputs.
|
|
937
|
-
* @param proof The proof generated with SnarkJS.
|
|
938
|
-
* @returns The Solidity compatible proof.
|
|
939
|
-
*/
|
|
940
|
-
function packToSolidityProof(proof) {
|
|
941
|
-
return [
|
|
942
|
-
proof.pi_a[0],
|
|
943
|
-
proof.pi_a[1],
|
|
944
|
-
proof.pi_b[0][1],
|
|
945
|
-
proof.pi_b[0][0],
|
|
946
|
-
proof.pi_b[1][1],
|
|
947
|
-
proof.pi_b[1][0],
|
|
948
|
-
proof.pi_c[0],
|
|
949
|
-
proof.pi_c[1]
|
|
950
|
-
];
|
|
970
|
+
return groth16.verify(verificationKey, [merkleTreeRoot, nullifierHash, hash(signal), hash(externalNullifier)], unpackProof(proof));
|
|
951
971
|
}
|
|
952
972
|
|
|
953
|
-
export { generateProof,
|
|
973
|
+
export { generateProof, verifyProof };
|
package/dist/index.node.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @module @semaphore-protocol/proof
|
|
3
|
-
* @version 3.0.0-beta.
|
|
3
|
+
* @version 3.0.0-beta.8
|
|
4
4
|
* @file A library to generate and verify Semaphore proofs.
|
|
5
5
|
* @copyright Ethereum Foundation 2022
|
|
6
6
|
* @license MIT
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
12
12
|
|
|
13
|
-
var snarkjs = require('snarkjs');
|
|
14
13
|
var bignumber = require('@ethersproject/bignumber');
|
|
14
|
+
var snarkjs = require('snarkjs');
|
|
15
15
|
var bytes = require('@ethersproject/bytes');
|
|
16
16
|
var keccak256 = require('@ethersproject/keccak256');
|
|
17
17
|
|
|
@@ -90,6 +90,33 @@ function hash(message) {
|
|
|
90
90
|
return BigInt(keccak256.keccak256(message)) >> BigInt(8);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/**
|
|
94
|
+
* Packs a proof into a format compatible with Semaphore.
|
|
95
|
+
* @param originalProof The proof generated with SnarkJS.
|
|
96
|
+
* @returns The proof compatible with Semaphore.
|
|
97
|
+
*/
|
|
98
|
+
function packProof(originalProof) {
|
|
99
|
+
return [
|
|
100
|
+
originalProof.pi_a[0],
|
|
101
|
+
originalProof.pi_a[1],
|
|
102
|
+
originalProof.pi_b[0][1],
|
|
103
|
+
originalProof.pi_b[0][0],
|
|
104
|
+
originalProof.pi_b[1][1],
|
|
105
|
+
originalProof.pi_b[1][0],
|
|
106
|
+
originalProof.pi_c[0],
|
|
107
|
+
originalProof.pi_c[1]
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Generates a Semaphore proof.
|
|
113
|
+
* @param identity The Semaphore identity.
|
|
114
|
+
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
115
|
+
* @param externalNullifier The external nullifier.
|
|
116
|
+
* @param signal The Semaphore signal.
|
|
117
|
+
* @param snarkArtifacts The SNARK artifacts.
|
|
118
|
+
* @returns The Semaphore proof ready to be verified.
|
|
119
|
+
*/
|
|
93
120
|
function generateProof(_a, groupOrMerkleProof, externalNullifier, signal, snarkArtifacts) {
|
|
94
121
|
var trapdoor = _a.trapdoor, nullifier = _a.nullifier, commitment = _a.commitment;
|
|
95
122
|
return __awaiter(this, void 0, void 0, function () {
|
|
@@ -124,19 +151,35 @@ function generateProof(_a, groupOrMerkleProof, externalNullifier, signal, snarkA
|
|
|
124
151
|
case 1:
|
|
125
152
|
_b = _c.sent(), proof = _b.proof, publicSignals = _b.publicSignals;
|
|
126
153
|
return [2 /*return*/, {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
externalNullifier: publicSignals[3]
|
|
133
|
-
}
|
|
154
|
+
merkleTreeRoot: publicSignals[0],
|
|
155
|
+
nullifierHash: publicSignals[1],
|
|
156
|
+
signal: bignumber.BigNumber.from(signal).toString(),
|
|
157
|
+
externalNullifier: bignumber.BigNumber.from(externalNullifier).toString(),
|
|
158
|
+
proof: packProof(proof)
|
|
134
159
|
}];
|
|
135
160
|
}
|
|
136
161
|
});
|
|
137
162
|
});
|
|
138
163
|
}
|
|
139
164
|
|
|
165
|
+
/**
|
|
166
|
+
* Unpacks a proof into its original form.
|
|
167
|
+
* @param proof The proof compatible with Semaphore.
|
|
168
|
+
* @returns The proof compatible with SnarkJS.
|
|
169
|
+
*/
|
|
170
|
+
function unpackProof(proof) {
|
|
171
|
+
return {
|
|
172
|
+
pi_a: [proof[0], proof[1]],
|
|
173
|
+
pi_b: [
|
|
174
|
+
[proof[3], proof[2]],
|
|
175
|
+
[proof[5], proof[4]]
|
|
176
|
+
],
|
|
177
|
+
pi_c: [proof[6], proof[7]],
|
|
178
|
+
protocol: "groth16",
|
|
179
|
+
curve: "bn128"
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
140
183
|
var protocol = "groth16";
|
|
141
184
|
var curve = "bn128";
|
|
142
185
|
var nPublic = 4;
|
|
@@ -917,43 +960,19 @@ var verificationKeys = {
|
|
|
917
960
|
};
|
|
918
961
|
|
|
919
962
|
/**
|
|
920
|
-
* Verifies a
|
|
921
|
-
* @param fullProof The SnarkJS
|
|
963
|
+
* Verifies a Semaphore proof.
|
|
964
|
+
* @param fullProof The SnarkJS Semaphore proof.
|
|
922
965
|
* @param treeDepth The Merkle tree depth.
|
|
923
966
|
* @returns True if the proof is valid, false otherwise.
|
|
924
967
|
*/
|
|
925
968
|
function verifyProof(_a, treeDepth) {
|
|
926
|
-
var
|
|
969
|
+
var merkleTreeRoot = _a.merkleTreeRoot, nullifierHash = _a.nullifierHash, externalNullifier = _a.externalNullifier, signal = _a.signal, proof = _a.proof;
|
|
927
970
|
if (treeDepth < 16 || treeDepth > 32) {
|
|
928
971
|
throw new TypeError("The tree depth must be a number between 16 and 32");
|
|
929
972
|
}
|
|
930
973
|
var verificationKey = __assign(__assign({}, verificationKeys), { vk_delta_2: verificationKeys.vk_delta_2[treeDepth - 16], IC: verificationKeys.IC[treeDepth - 16] });
|
|
931
|
-
return snarkjs.groth16.verify(verificationKey, [
|
|
932
|
-
publicSignals.merkleTreeRoot,
|
|
933
|
-
publicSignals.nullifierHash,
|
|
934
|
-
publicSignals.signalHash,
|
|
935
|
-
publicSignals.externalNullifier
|
|
936
|
-
], proof);
|
|
937
|
-
}
|
|
938
|
-
|
|
939
|
-
/**
|
|
940
|
-
* Makes a proof compatible with the Verifier.sol method inputs.
|
|
941
|
-
* @param proof The proof generated with SnarkJS.
|
|
942
|
-
* @returns The Solidity compatible proof.
|
|
943
|
-
*/
|
|
944
|
-
function packToSolidityProof(proof) {
|
|
945
|
-
return [
|
|
946
|
-
proof.pi_a[0],
|
|
947
|
-
proof.pi_a[1],
|
|
948
|
-
proof.pi_b[0][1],
|
|
949
|
-
proof.pi_b[0][0],
|
|
950
|
-
proof.pi_b[1][1],
|
|
951
|
-
proof.pi_b[1][0],
|
|
952
|
-
proof.pi_c[0],
|
|
953
|
-
proof.pi_c[1]
|
|
954
|
-
];
|
|
974
|
+
return snarkjs.groth16.verify(verificationKey, [merkleTreeRoot, nullifierHash, hash(signal), hash(externalNullifier)], unpackProof(proof));
|
|
955
975
|
}
|
|
956
976
|
|
|
957
977
|
exports.generateProof = generateProof;
|
|
958
|
-
exports.packToSolidityProof = packToSolidityProof;
|
|
959
978
|
exports.verifyProof = verifyProof;
|
|
@@ -3,4 +3,13 @@ import { Group } from "@semaphore-protocol/group";
|
|
|
3
3
|
import type { Identity } from "@semaphore-protocol/identity";
|
|
4
4
|
import { MerkleProof } from "@zk-kit/incremental-merkle-tree";
|
|
5
5
|
import { FullProof, SnarkArtifacts } from "./types";
|
|
6
|
+
/**
|
|
7
|
+
* Generates a Semaphore proof.
|
|
8
|
+
* @param identity The Semaphore identity.
|
|
9
|
+
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
10
|
+
* @param externalNullifier The external nullifier.
|
|
11
|
+
* @param signal The Semaphore signal.
|
|
12
|
+
* @param snarkArtifacts The SNARK artifacts.
|
|
13
|
+
* @returns The Semaphore proof ready to be verified.
|
|
14
|
+
*/
|
|
6
15
|
export default function generateProof({ trapdoor, nullifier, commitment }: Identity, groupOrMerkleProof: Group | MerkleProof, externalNullifier: BytesLike | Hexable | number | bigint, signal: BytesLike | Hexable | number | bigint, snarkArtifacts?: SnarkArtifacts): Promise<FullProof>;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import generateProof from "./generateProof";
|
|
2
2
|
import verifyProof from "./verifyProof";
|
|
3
|
-
|
|
4
|
-
export { generateProof, verifyProof, packToSolidityProof };
|
|
3
|
+
export { generateProof, verifyProof };
|
|
5
4
|
export * from "./types";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SnarkJSProof, Proof } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Packs a proof into a format compatible with Semaphore.
|
|
4
|
+
* @param originalProof The proof generated with SnarkJS.
|
|
5
|
+
* @returns The proof compatible with Semaphore.
|
|
6
|
+
*/
|
|
7
|
+
export default function packProof(originalProof: SnarkJSProof): Proof;
|
|
@@ -3,7 +3,7 @@ export type SnarkArtifacts = {
|
|
|
3
3
|
wasmFilePath: string;
|
|
4
4
|
zkeyFilePath: string;
|
|
5
5
|
};
|
|
6
|
-
export type
|
|
6
|
+
export type SnarkJSProof = {
|
|
7
7
|
pi_a: BigNumberish[];
|
|
8
8
|
pi_b: BigNumberish[][];
|
|
9
9
|
pi_c: BigNumberish[];
|
|
@@ -11,16 +11,13 @@ export type Proof = {
|
|
|
11
11
|
curve: string;
|
|
12
12
|
};
|
|
13
13
|
export type FullProof = {
|
|
14
|
-
proof: Proof;
|
|
15
|
-
publicSignals: PublicSignals;
|
|
16
|
-
};
|
|
17
|
-
export type PublicSignals = {
|
|
18
14
|
merkleTreeRoot: BigNumberish;
|
|
15
|
+
signal: BigNumberish;
|
|
19
16
|
nullifierHash: BigNumberish;
|
|
20
|
-
signalHash: BigNumberish;
|
|
21
17
|
externalNullifier: BigNumberish;
|
|
18
|
+
proof: Proof;
|
|
22
19
|
};
|
|
23
|
-
export type
|
|
20
|
+
export type Proof = [
|
|
24
21
|
BigNumberish,
|
|
25
22
|
BigNumberish,
|
|
26
23
|
BigNumberish,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SnarkJSProof, Proof } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Unpacks a proof into its original form.
|
|
4
|
+
* @param proof The proof compatible with Semaphore.
|
|
5
|
+
* @returns The proof compatible with SnarkJS.
|
|
6
|
+
*/
|
|
7
|
+
export default function unpackProof(proof: Proof): SnarkJSProof;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { FullProof } from "./types";
|
|
2
2
|
/**
|
|
3
|
-
* Verifies a
|
|
4
|
-
* @param fullProof The SnarkJS
|
|
3
|
+
* Verifies a Semaphore proof.
|
|
4
|
+
* @param fullProof The SnarkJS Semaphore proof.
|
|
5
5
|
* @param treeDepth The Merkle tree depth.
|
|
6
6
|
* @returns True if the proof is valid, false otherwise.
|
|
7
7
|
*/
|
|
8
|
-
export default function verifyProof({
|
|
8
|
+
export default function verifyProof({ merkleTreeRoot, nullifierHash, externalNullifier, signal, proof }: FullProof, treeDepth: number): Promise<boolean>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@semaphore-protocol/proof",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.8",
|
|
4
4
|
"description": "A library to generate and verify Semaphore proofs.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/index.node.js",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"typedoc": "^0.22.11"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@semaphore-protocol/group": "3.0.0-beta.
|
|
41
|
-
"@semaphore-protocol/identity": "3.0.0-beta.
|
|
40
|
+
"@semaphore-protocol/group": "3.0.0-beta.8",
|
|
41
|
+
"@semaphore-protocol/identity": "3.0.0-beta.8"
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@ethersproject/bignumber": "^5.5.0",
|
|
@@ -46,6 +46,6 @@
|
|
|
46
46
|
"@ethersproject/keccak256": "^5.7.0",
|
|
47
47
|
"@ethersproject/strings": "^5.5.0",
|
|
48
48
|
"@zk-kit/incremental-merkle-tree": "0.4.3",
|
|
49
|
-
"snarkjs": "
|
|
49
|
+
"snarkjs": "0.4.13"
|
|
50
50
|
}
|
|
51
51
|
}
|
package/src/generateProof.ts
CHANGED
|
@@ -1,11 +1,22 @@
|
|
|
1
|
+
import { BigNumber } from "@ethersproject/bignumber"
|
|
1
2
|
import { BytesLike, Hexable } from "@ethersproject/bytes"
|
|
2
3
|
import { Group } from "@semaphore-protocol/group"
|
|
3
4
|
import type { Identity } from "@semaphore-protocol/identity"
|
|
4
5
|
import { MerkleProof } from "@zk-kit/incremental-merkle-tree"
|
|
5
6
|
import { groth16 } from "snarkjs"
|
|
6
7
|
import hash from "./hash"
|
|
8
|
+
import packProof from "./packProof"
|
|
7
9
|
import { FullProof, SnarkArtifacts } from "./types"
|
|
8
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Generates a Semaphore proof.
|
|
13
|
+
* @param identity The Semaphore identity.
|
|
14
|
+
* @param groupOrMerkleProof The Semaphore group or its Merkle proof.
|
|
15
|
+
* @param externalNullifier The external nullifier.
|
|
16
|
+
* @param signal The Semaphore signal.
|
|
17
|
+
* @param snarkArtifacts The SNARK artifacts.
|
|
18
|
+
* @returns The Semaphore proof ready to be verified.
|
|
19
|
+
*/
|
|
9
20
|
export default async function generateProof(
|
|
10
21
|
{ trapdoor, nullifier, commitment }: Identity,
|
|
11
22
|
groupOrMerkleProof: Group | MerkleProof,
|
|
@@ -48,12 +59,10 @@ export default async function generateProof(
|
|
|
48
59
|
)
|
|
49
60
|
|
|
50
61
|
return {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
externalNullifier: publicSignals[3]
|
|
57
|
-
}
|
|
62
|
+
merkleTreeRoot: publicSignals[0],
|
|
63
|
+
nullifierHash: publicSignals[1],
|
|
64
|
+
signal: BigNumber.from(signal).toString(),
|
|
65
|
+
externalNullifier: BigNumber.from(externalNullifier).toString(),
|
|
66
|
+
proof: packProof(proof)
|
|
58
67
|
}
|
|
59
68
|
}
|
package/src/index.test.ts
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
|
+
import { formatBytes32String } from "@ethersproject/strings"
|
|
1
2
|
import { Group } from "@semaphore-protocol/group"
|
|
2
3
|
import { Identity } from "@semaphore-protocol/identity"
|
|
3
4
|
import { getCurveFromName } from "ffjavascript"
|
|
4
5
|
import generateProof from "./generateProof"
|
|
5
6
|
import hash from "./hash"
|
|
6
|
-
import
|
|
7
|
+
import packProof from "./packProof"
|
|
7
8
|
import { FullProof } from "./types"
|
|
9
|
+
import unpackProof from "./unpackProof"
|
|
8
10
|
import verifyProof from "./verifyProof"
|
|
9
11
|
|
|
10
12
|
describe("Proof", () => {
|
|
11
13
|
const treeDepth = Number(process.env.TREE_DEPTH) || 20
|
|
12
14
|
|
|
13
|
-
const externalNullifier =
|
|
14
|
-
const signal =
|
|
15
|
+
const externalNullifier = formatBytes32String("Topic")
|
|
16
|
+
const signal = formatBytes32String("Hello world")
|
|
15
17
|
|
|
16
18
|
const wasmFilePath = `./snark-artifacts/${treeDepth}/semaphore.wasm`
|
|
17
19
|
const zkeyFilePath = `./snark-artifacts/${treeDepth}/semaphore.zkey`
|
|
@@ -65,7 +67,7 @@ describe("Proof", () => {
|
|
|
65
67
|
})
|
|
66
68
|
|
|
67
69
|
expect(typeof fullProof).toBe("object")
|
|
68
|
-
expect(fullProof.
|
|
70
|
+
expect(fullProof.merkleTreeRoot).toBe(group.root.toString())
|
|
69
71
|
}, 20000)
|
|
70
72
|
|
|
71
73
|
it("Should generate a Semaphore proof passing a Merkle proof as parameter", async () => {
|
|
@@ -79,7 +81,7 @@ describe("Proof", () => {
|
|
|
79
81
|
})
|
|
80
82
|
|
|
81
83
|
expect(typeof fullProof).toBe("object")
|
|
82
|
-
expect(fullProof.
|
|
84
|
+
expect(fullProof.merkleTreeRoot).toBe(group.root.toString())
|
|
83
85
|
}, 20000)
|
|
84
86
|
})
|
|
85
87
|
|
|
@@ -101,13 +103,17 @@ describe("Proof", () => {
|
|
|
101
103
|
it("Should hash the signal value correctly", async () => {
|
|
102
104
|
const signalHash = hash(signal)
|
|
103
105
|
|
|
104
|
-
expect(signalHash.toString()).toBe(
|
|
106
|
+
expect(signalHash.toString()).toBe(
|
|
107
|
+
"8665846418922331996225934941481656421248110469944536651334918563951783029"
|
|
108
|
+
)
|
|
105
109
|
})
|
|
106
110
|
|
|
107
111
|
it("Should hash the external nullifier value correctly", async () => {
|
|
108
112
|
const externalNullifierHash = hash(externalNullifier)
|
|
109
113
|
|
|
110
|
-
expect(externalNullifierHash.toString()).toBe(
|
|
114
|
+
expect(externalNullifierHash.toString()).toBe(
|
|
115
|
+
"244178201824278269437519042830883072613014992408751798420801126401127326826"
|
|
116
|
+
)
|
|
111
117
|
})
|
|
112
118
|
|
|
113
119
|
it("Should hash a number", async () => {
|
|
@@ -141,11 +147,12 @@ describe("Proof", () => {
|
|
|
141
147
|
})
|
|
142
148
|
})
|
|
143
149
|
|
|
144
|
-
describe("#
|
|
145
|
-
it("Should return a
|
|
146
|
-
const
|
|
150
|
+
describe("# packProof/unpackProof", () => {
|
|
151
|
+
it("Should return a packed proof", async () => {
|
|
152
|
+
const originalProof = unpackProof(fullProof.proof)
|
|
153
|
+
const proof = packProof(originalProof)
|
|
147
154
|
|
|
148
|
-
expect(
|
|
155
|
+
expect(proof).toStrictEqual(fullProof.proof)
|
|
149
156
|
})
|
|
150
157
|
})
|
|
151
158
|
})
|
package/src/index.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import generateProof from "./generateProof"
|
|
2
2
|
import verifyProof from "./verifyProof"
|
|
3
|
-
import packToSolidityProof from "./packToSolidityProof"
|
|
4
3
|
|
|
5
|
-
export { generateProof, verifyProof
|
|
4
|
+
export { generateProof, verifyProof }
|
|
6
5
|
export * from "./types"
|
package/src/packProof.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SnarkJSProof, Proof } from "./types"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Packs a proof into a format compatible with Semaphore.
|
|
5
|
+
* @param originalProof The proof generated with SnarkJS.
|
|
6
|
+
* @returns The proof compatible with Semaphore.
|
|
7
|
+
*/
|
|
8
|
+
export default function packProof(originalProof: SnarkJSProof): Proof {
|
|
9
|
+
return [
|
|
10
|
+
originalProof.pi_a[0],
|
|
11
|
+
originalProof.pi_a[1],
|
|
12
|
+
originalProof.pi_b[0][1],
|
|
13
|
+
originalProof.pi_b[0][0],
|
|
14
|
+
originalProof.pi_b[1][1],
|
|
15
|
+
originalProof.pi_b[1][0],
|
|
16
|
+
originalProof.pi_c[0],
|
|
17
|
+
originalProof.pi_c[1]
|
|
18
|
+
]
|
|
19
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type SnarkArtifacts = {
|
|
|
5
5
|
zkeyFilePath: string
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export type
|
|
8
|
+
export type SnarkJSProof = {
|
|
9
9
|
pi_a: BigNumberish[]
|
|
10
10
|
pi_b: BigNumberish[][]
|
|
11
11
|
pi_c: BigNumberish[]
|
|
@@ -14,18 +14,14 @@ export type Proof = {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export type FullProof = {
|
|
17
|
-
proof: Proof
|
|
18
|
-
publicSignals: PublicSignals
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export type PublicSignals = {
|
|
22
17
|
merkleTreeRoot: BigNumberish
|
|
18
|
+
signal: BigNumberish
|
|
23
19
|
nullifierHash: BigNumberish
|
|
24
|
-
signalHash: BigNumberish
|
|
25
20
|
externalNullifier: BigNumberish
|
|
21
|
+
proof: Proof
|
|
26
22
|
}
|
|
27
23
|
|
|
28
|
-
export type
|
|
24
|
+
export type Proof = [
|
|
29
25
|
BigNumberish,
|
|
30
26
|
BigNumberish,
|
|
31
27
|
BigNumberish,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SnarkJSProof, Proof } from "./types"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Unpacks a proof into its original form.
|
|
5
|
+
* @param proof The proof compatible with Semaphore.
|
|
6
|
+
* @returns The proof compatible with SnarkJS.
|
|
7
|
+
*/
|
|
8
|
+
export default function unpackProof(proof: Proof): SnarkJSProof {
|
|
9
|
+
return {
|
|
10
|
+
pi_a: [proof[0], proof[1]],
|
|
11
|
+
pi_b: [
|
|
12
|
+
[proof[3], proof[2]],
|
|
13
|
+
[proof[5], proof[4]]
|
|
14
|
+
],
|
|
15
|
+
pi_c: [proof[6], proof[7]],
|
|
16
|
+
protocol: "groth16",
|
|
17
|
+
curve: "bn128"
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/verifyProof.ts
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { groth16 } from "snarkjs"
|
|
2
|
+
import hash from "./hash"
|
|
2
3
|
import { FullProof } from "./types"
|
|
4
|
+
import unpackProof from "./unpackProof"
|
|
3
5
|
import verificationKeys from "./verificationKeys.json"
|
|
4
6
|
|
|
5
7
|
/**
|
|
6
|
-
* Verifies a
|
|
7
|
-
* @param fullProof The SnarkJS
|
|
8
|
+
* Verifies a Semaphore proof.
|
|
9
|
+
* @param fullProof The SnarkJS Semaphore proof.
|
|
8
10
|
* @param treeDepth The Merkle tree depth.
|
|
9
11
|
* @returns True if the proof is valid, false otherwise.
|
|
10
12
|
*/
|
|
11
|
-
export default function verifyProof(
|
|
13
|
+
export default function verifyProof(
|
|
14
|
+
{ merkleTreeRoot, nullifierHash, externalNullifier, signal, proof }: FullProof,
|
|
15
|
+
treeDepth: number
|
|
16
|
+
): Promise<boolean> {
|
|
12
17
|
if (treeDepth < 16 || treeDepth > 32) {
|
|
13
18
|
throw new TypeError("The tree depth must be a number between 16 and 32")
|
|
14
19
|
}
|
|
@@ -21,12 +26,7 @@ export default function verifyProof({ proof, publicSignals }: FullProof, treeDep
|
|
|
21
26
|
|
|
22
27
|
return groth16.verify(
|
|
23
28
|
verificationKey,
|
|
24
|
-
[
|
|
25
|
-
|
|
26
|
-
publicSignals.nullifierHash,
|
|
27
|
-
publicSignals.signalHash,
|
|
28
|
-
publicSignals.externalNullifier
|
|
29
|
-
],
|
|
30
|
-
proof
|
|
29
|
+
[merkleTreeRoot, nullifierHash, hash(signal), hash(externalNullifier)],
|
|
30
|
+
unpackProof(proof)
|
|
31
31
|
)
|
|
32
32
|
}
|
|
@@ -1,7 +0,0 @@
|
|
|
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,19 +0,0 @@
|
|
|
1
|
-
import { Proof, SolidityProof } from "./types"
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Makes a proof compatible with the Verifier.sol method inputs.
|
|
5
|
-
* @param proof The proof generated with SnarkJS.
|
|
6
|
-
* @returns The Solidity compatible proof.
|
|
7
|
-
*/
|
|
8
|
-
export default function packToSolidityProof(proof: Proof): SolidityProof {
|
|
9
|
-
return [
|
|
10
|
-
proof.pi_a[0],
|
|
11
|
-
proof.pi_a[1],
|
|
12
|
-
proof.pi_b[0][1],
|
|
13
|
-
proof.pi_b[0][0],
|
|
14
|
-
proof.pi_b[1][1],
|
|
15
|
-
proof.pi_b[1][0],
|
|
16
|
-
proof.pi_c[0],
|
|
17
|
-
proof.pi_c[1]
|
|
18
|
-
]
|
|
19
|
-
}
|