@semaphore-protocol/group 4.0.0-beta → 4.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -98,7 +98,7 @@ const { commitment } = new Identity()
98
98
 
99
99
  group.addMember(commitment)
100
100
 
101
- // "12989101133047504182892154686643420754368236204022364847543591045056549053997"
101
+ // 12989101133047504182892154686643420754368236204022364847543591045056549053997n
102
102
  console.log(group.members[0])
103
103
  ```
104
104
 
@@ -121,11 +121,11 @@ group.addMembers([identity1.commitment, identity2.commitment])
121
121
  ```typescript
122
122
  import { Group } from "@semaphore-protocol/group"
123
123
 
124
- const group = new Group([1, 3])
124
+ const group = new Group([1n, 3n])
125
125
 
126
126
  group.updateMember(0, 2)
127
127
 
128
- console.log(group.members[0]) // "2"
128
+ console.log(group.members[0]) // "2n"
129
129
  ```
130
130
 
131
131
  \# **removeMember**(index: _number_)
@@ -133,11 +133,11 @@ console.log(group.members[0]) // "2"
133
133
  ```typescript
134
134
  import { Group } from "@semaphore-protocol/group"
135
135
 
136
- const group = new Group([1, 3])
136
+ const group = new Group([1n, 3n])
137
137
 
138
138
  group.removeMember(0)
139
139
 
140
- console.log(group.members[0]) // "0"
140
+ console.log(group.members[0]) // 0n
141
141
  ```
142
142
 
143
143
  \# **indexOf**(member: _BigNumberish_): _number_
@@ -145,7 +145,7 @@ console.log(group.members[0]) // "0"
145
145
  ```typescript
146
146
  import { Group } from "@semaphore-protocol/group"
147
147
 
148
- const group = new Group([1])
148
+ const group = new Group([1n])
149
149
 
150
150
  const index = group.indexOf(1)
151
151
 
@@ -157,7 +157,7 @@ console.log(index) // 0
157
157
  ```typescript
158
158
  import { Group } from "@semaphore-protocol/group"
159
159
 
160
- const group = new Group([1, 3])
160
+ const group = new Group([1n, 3n])
161
161
 
162
162
  const proof = group.generateMerkleProof(0)
163
163
 
@@ -177,7 +177,7 @@ console.log(proof)
177
177
  ```typescript
178
178
  import { Group } from "@semaphore-protocol/group"
179
179
 
180
- const group = new Group([1, 2, 3])
180
+ const group = new Group([1n, 2n, 3n])
181
181
 
182
182
  const exportedGroup = group.export()
183
183
 
@@ -192,7 +192,7 @@ console.log(exportedGroup)
192
192
  ```typescript
193
193
  import { Group } from "@semaphore-protocol/group"
194
194
 
195
- const group1 = new Group([1, 2, 3])
195
+ const group1 = new Group([1n, 2n, 3n])
196
196
 
197
197
  const exportedGroup = group.export()
198
198
 
package/dist/index.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/group
3
- * @version 4.0.0-beta
3
+ * @version 4.0.0-beta.10
4
4
  * @file A library to create and manage Semaphore groups.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
@@ -121,121 +121,117 @@ function poseidon2(inputs) {
121
121
  * This class supports operations such as member addition, update, removal and Merkle proof
122
122
  * generation and verification. Groups can also be exported or imported.
123
123
  */
124
- var Group = /** @class */ (function () {
124
+ class Group {
125
125
  /**
126
126
  * Creates a new instance of the Group. Optionally, a list of identity commitments can
127
127
  * be passed as a parameter. Adding members in chunks is more efficient than adding
128
128
  * them one by one with the `addMember` function.
129
129
  * @param members A list of identity commitments.
130
130
  */
131
- function Group(members) {
132
- if (members === void 0) { members = []; }
133
- this.leanIMT = new imt.LeanIMT(function (a, b) { return poseidon2_2([a, b]); }, members.map(BigInt));
134
- }
135
- Object.defineProperty(Group.prototype, "root", {
136
- /**
137
- * Returns the root hash of the tree.
138
- * @returns The root hash as a string.
139
- */
140
- get: function () {
141
- return this.leanIMT.root ? this.leanIMT.root.toString() : "0";
142
- },
143
- enumerable: false,
144
- configurable: true
145
- });
146
- Object.defineProperty(Group.prototype, "depth", {
147
- /**
148
- * Returns the depth of the tree.
149
- * @returns The tree depth as a number.
150
- */
151
- get: function () {
152
- return this.leanIMT.depth;
153
- },
154
- enumerable: false,
155
- configurable: true
156
- });
157
- Object.defineProperty(Group.prototype, "size", {
158
- /**
159
- * Returns the size of the tree (i.e. number of leaves).
160
- * @returns The tree size as a number.
161
- */
162
- get: function () {
163
- return this.leanIMT.size;
164
- },
165
- enumerable: false,
166
- configurable: true
167
- });
168
- Object.defineProperty(Group.prototype, "members", {
169
- /**
170
- * Returns the members (i.e. identity commitments) of the group.
171
- * @returns The list of members of the group.
172
- */
173
- get: function () {
174
- return this.leanIMT.leaves.map(String);
175
- },
176
- enumerable: false,
177
- configurable: true
178
- });
131
+ constructor(members = []) {
132
+ for (const member of members) {
133
+ if (member === 0n || member === "0") {
134
+ throw new Error("Failed to add member: value cannot be 0");
135
+ }
136
+ }
137
+ this.leanIMT = new imt.LeanIMT((a, b) => poseidon2_2([a, b]), members.map(BigInt));
138
+ }
139
+ /**
140
+ * Returns the root hash of the tree.
141
+ * @returns The root hash as a string.
142
+ */
143
+ get root() {
144
+ return this.leanIMT.root ? this.leanIMT.root : 0n;
145
+ }
146
+ /**
147
+ * Returns the depth of the tree.
148
+ * @returns The tree depth as a number.
149
+ */
150
+ get depth() {
151
+ return this.leanIMT.depth;
152
+ }
153
+ /**
154
+ * Returns the size of the tree (i.e. number of leaves).
155
+ * @returns The tree size as a number.
156
+ */
157
+ get size() {
158
+ return this.leanIMT.size;
159
+ }
160
+ /**
161
+ * Returns the members (i.e. identity commitments) of the group.
162
+ * @returns The list of members of the group.
163
+ */
164
+ get members() {
165
+ return this.leanIMT.leaves;
166
+ }
179
167
  /**
180
168
  * Returns the index of a member. If the member does not exist it returns -1.
181
169
  * @param member A member of the group.
182
170
  * @returns The index of the member, or -1 if it does not exist.
183
171
  */
184
- Group.prototype.indexOf = function (member) {
172
+ indexOf(member) {
185
173
  return this.leanIMT.indexOf(BigInt(member));
186
- };
174
+ }
187
175
  /**
188
176
  * Adds a new member to the group.
189
177
  * @param member The new member to be added.
190
178
  */
191
- Group.prototype.addMember = function (member) {
179
+ addMember(member) {
180
+ if (member === 0n || member === "0") {
181
+ throw new Error("Failed to add member: value cannot be 0");
182
+ }
192
183
  this.leanIMT.insert(BigInt(member));
193
- };
184
+ }
194
185
  /**
195
186
  * Adds new members to the group.
196
187
  * @param members New members.
197
188
  */
198
- Group.prototype.addMembers = function (members) {
189
+ addMembers(members) {
190
+ for (const member of members) {
191
+ if (member === 0n || member === "0") {
192
+ throw new Error("Failed to add member: value cannot be 0");
193
+ }
194
+ }
199
195
  this.leanIMT.insertMany(members.map(BigInt));
200
- };
196
+ }
201
197
  /**
202
198
  * Updates a member in the group.
203
199
  * @param index Index of the member to be updated.
204
200
  * @param member New member value.
205
201
  */
206
- Group.prototype.updateMember = function (index, member) {
202
+ updateMember(index, member) {
203
+ if (this.members[index] === 0n) {
204
+ throw new Error("Failed to update member: it has been removed");
205
+ }
207
206
  this.leanIMT.update(index, BigInt(member));
208
- };
207
+ }
209
208
  /**
210
209
  * Removes a member from the group.
211
210
  * @param index The index of the member to be removed.
212
211
  */
213
- Group.prototype.removeMember = function (index) {
214
- this.leanIMT.update(index, BigInt(0));
215
- };
212
+ removeMember(index) {
213
+ if (this.members[index] === 0n) {
214
+ throw new Error("Failed to remove member: it has already been removed");
215
+ }
216
+ this.leanIMT.update(index, 0n);
217
+ }
216
218
  /**
217
219
  * Creates a proof of membership for a member of the group.
218
220
  * @param index The index of the member.
219
221
  * @returns The {@link MerkleProof} object.
220
222
  */
221
- Group.prototype.generateMerkleProof = function (_index) {
222
- var _a = this.leanIMT.generateProof(_index), index = _a.index, leaf = _a.leaf, root = _a.root, siblings = _a.siblings;
223
- return {
224
- index: index,
225
- leaf: leaf.toString(),
226
- root: root.toString(),
227
- siblings: siblings.map(String)
228
- };
229
- };
223
+ generateMerkleProof(index) {
224
+ return this.leanIMT.generateProof(index);
225
+ }
230
226
  /**
231
227
  * Enables the conversion of the group into a JSON string that
232
228
  * can be re-used for future imports. This approach is beneficial for
233
229
  * large groups, as it avoids re-calculating the tree hashes.
234
230
  * @returns The stringified JSON of the group.
235
231
  */
236
- Group.prototype.export = function () {
232
+ export() {
237
233
  return this.leanIMT.export();
238
- };
234
+ }
239
235
  /**
240
236
  * Imports an entire group by initializing the tree without calculating
241
237
  * any hashes. Note that it is crucial to ensure the integrity of the
@@ -243,12 +239,11 @@ var Group = /** @class */ (function () {
243
239
  * @param nodes The stringified JSON of the group.
244
240
  * @returns The {@link Group} instance.
245
241
  */
246
- Group.import = function (exportedGroup) {
247
- var group = new Group();
248
- group.leanIMT.import(exportedGroup);
242
+ static import(nodes) {
243
+ const group = new Group();
244
+ group.leanIMT.import(nodes);
249
245
  return group;
250
- };
251
- return Group;
252
- }());
246
+ }
247
+ }
253
248
 
254
249
  exports.Group = Group;
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @module @semaphore-protocol/group
3
- * @version 4.0.0-beta
3
+ * @version 4.0.0-beta.10
4
4
  * @file A library to create and manage Semaphore groups.
5
5
  * @copyright Ethereum Foundation 2024
6
6
  * @license MIT
@@ -119,121 +119,117 @@ function poseidon2(inputs) {
119
119
  * This class supports operations such as member addition, update, removal and Merkle proof
120
120
  * generation and verification. Groups can also be exported or imported.
121
121
  */
122
- var Group = /** @class */ (function () {
122
+ class Group {
123
123
  /**
124
124
  * Creates a new instance of the Group. Optionally, a list of identity commitments can
125
125
  * be passed as a parameter. Adding members in chunks is more efficient than adding
126
126
  * them one by one with the `addMember` function.
127
127
  * @param members A list of identity commitments.
128
128
  */
129
- function Group(members) {
130
- if (members === void 0) { members = []; }
131
- this.leanIMT = new LeanIMT(function (a, b) { return poseidon2_2([a, b]); }, members.map(BigInt));
132
- }
133
- Object.defineProperty(Group.prototype, "root", {
134
- /**
135
- * Returns the root hash of the tree.
136
- * @returns The root hash as a string.
137
- */
138
- get: function () {
139
- return this.leanIMT.root ? this.leanIMT.root.toString() : "0";
140
- },
141
- enumerable: false,
142
- configurable: true
143
- });
144
- Object.defineProperty(Group.prototype, "depth", {
145
- /**
146
- * Returns the depth of the tree.
147
- * @returns The tree depth as a number.
148
- */
149
- get: function () {
150
- return this.leanIMT.depth;
151
- },
152
- enumerable: false,
153
- configurable: true
154
- });
155
- Object.defineProperty(Group.prototype, "size", {
156
- /**
157
- * Returns the size of the tree (i.e. number of leaves).
158
- * @returns The tree size as a number.
159
- */
160
- get: function () {
161
- return this.leanIMT.size;
162
- },
163
- enumerable: false,
164
- configurable: true
165
- });
166
- Object.defineProperty(Group.prototype, "members", {
167
- /**
168
- * Returns the members (i.e. identity commitments) of the group.
169
- * @returns The list of members of the group.
170
- */
171
- get: function () {
172
- return this.leanIMT.leaves.map(String);
173
- },
174
- enumerable: false,
175
- configurable: true
176
- });
129
+ constructor(members = []) {
130
+ for (const member of members) {
131
+ if (member === 0n || member === "0") {
132
+ throw new Error("Failed to add member: value cannot be 0");
133
+ }
134
+ }
135
+ this.leanIMT = new LeanIMT((a, b) => poseidon2_2([a, b]), members.map(BigInt));
136
+ }
137
+ /**
138
+ * Returns the root hash of the tree.
139
+ * @returns The root hash as a string.
140
+ */
141
+ get root() {
142
+ return this.leanIMT.root ? this.leanIMT.root : 0n;
143
+ }
144
+ /**
145
+ * Returns the depth of the tree.
146
+ * @returns The tree depth as a number.
147
+ */
148
+ get depth() {
149
+ return this.leanIMT.depth;
150
+ }
151
+ /**
152
+ * Returns the size of the tree (i.e. number of leaves).
153
+ * @returns The tree size as a number.
154
+ */
155
+ get size() {
156
+ return this.leanIMT.size;
157
+ }
158
+ /**
159
+ * Returns the members (i.e. identity commitments) of the group.
160
+ * @returns The list of members of the group.
161
+ */
162
+ get members() {
163
+ return this.leanIMT.leaves;
164
+ }
177
165
  /**
178
166
  * Returns the index of a member. If the member does not exist it returns -1.
179
167
  * @param member A member of the group.
180
168
  * @returns The index of the member, or -1 if it does not exist.
181
169
  */
182
- Group.prototype.indexOf = function (member) {
170
+ indexOf(member) {
183
171
  return this.leanIMT.indexOf(BigInt(member));
184
- };
172
+ }
185
173
  /**
186
174
  * Adds a new member to the group.
187
175
  * @param member The new member to be added.
188
176
  */
189
- Group.prototype.addMember = function (member) {
177
+ addMember(member) {
178
+ if (member === 0n || member === "0") {
179
+ throw new Error("Failed to add member: value cannot be 0");
180
+ }
190
181
  this.leanIMT.insert(BigInt(member));
191
- };
182
+ }
192
183
  /**
193
184
  * Adds new members to the group.
194
185
  * @param members New members.
195
186
  */
196
- Group.prototype.addMembers = function (members) {
187
+ addMembers(members) {
188
+ for (const member of members) {
189
+ if (member === 0n || member === "0") {
190
+ throw new Error("Failed to add member: value cannot be 0");
191
+ }
192
+ }
197
193
  this.leanIMT.insertMany(members.map(BigInt));
198
- };
194
+ }
199
195
  /**
200
196
  * Updates a member in the group.
201
197
  * @param index Index of the member to be updated.
202
198
  * @param member New member value.
203
199
  */
204
- Group.prototype.updateMember = function (index, member) {
200
+ updateMember(index, member) {
201
+ if (this.members[index] === 0n) {
202
+ throw new Error("Failed to update member: it has been removed");
203
+ }
205
204
  this.leanIMT.update(index, BigInt(member));
206
- };
205
+ }
207
206
  /**
208
207
  * Removes a member from the group.
209
208
  * @param index The index of the member to be removed.
210
209
  */
211
- Group.prototype.removeMember = function (index) {
212
- this.leanIMT.update(index, BigInt(0));
213
- };
210
+ removeMember(index) {
211
+ if (this.members[index] === 0n) {
212
+ throw new Error("Failed to remove member: it has already been removed");
213
+ }
214
+ this.leanIMT.update(index, 0n);
215
+ }
214
216
  /**
215
217
  * Creates a proof of membership for a member of the group.
216
218
  * @param index The index of the member.
217
219
  * @returns The {@link MerkleProof} object.
218
220
  */
219
- Group.prototype.generateMerkleProof = function (_index) {
220
- var _a = this.leanIMT.generateProof(_index), index = _a.index, leaf = _a.leaf, root = _a.root, siblings = _a.siblings;
221
- return {
222
- index: index,
223
- leaf: leaf.toString(),
224
- root: root.toString(),
225
- siblings: siblings.map(String)
226
- };
227
- };
221
+ generateMerkleProof(index) {
222
+ return this.leanIMT.generateProof(index);
223
+ }
228
224
  /**
229
225
  * Enables the conversion of the group into a JSON string that
230
226
  * can be re-used for future imports. This approach is beneficial for
231
227
  * large groups, as it avoids re-calculating the tree hashes.
232
228
  * @returns The stringified JSON of the group.
233
229
  */
234
- Group.prototype.export = function () {
230
+ export() {
235
231
  return this.leanIMT.export();
236
- };
232
+ }
237
233
  /**
238
234
  * Imports an entire group by initializing the tree without calculating
239
235
  * any hashes. Note that it is crucial to ensure the integrity of the
@@ -241,12 +237,11 @@ var Group = /** @class */ (function () {
241
237
  * @param nodes The stringified JSON of the group.
242
238
  * @returns The {@link Group} instance.
243
239
  */
244
- Group.import = function (exportedGroup) {
245
- var group = new Group();
246
- group.leanIMT.import(exportedGroup);
240
+ static import(nodes) {
241
+ const group = new Group();
242
+ group.leanIMT.import(nodes);
247
243
  return group;
248
- };
249
- return Group;
250
- }());
244
+ }
245
+ }
251
246
 
252
247
  export { Group };
@@ -1,3 +1,91 @@
1
- import Group from "./group";
2
- export { Group };
3
- export * from "./types";
1
+ import { LeanIMT, LeanIMTMerkleProof } from "@zk-kit/imt";
2
+ import type { BigNumber } from "@zk-kit/utils";
3
+ /**
4
+ * The Semaphore group is a {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT}
5
+ * (Lean Incremental Merkle Tree), i.e. an optimized version of the incremental binary Merkle tree
6
+ * used by Semaphore V3. The new tree does not use zero hashes, and its depth is dynamic.
7
+ * The members of a Semaphore group, or the leaves of a tree, are the identity commitments.
8
+ * Thanks to the properties of Merkle trees, it can be efficiently demonstrated that a group
9
+ * member belongs to the group.
10
+ * This class supports operations such as member addition, update, removal and Merkle proof
11
+ * generation and verification. Groups can also be exported or imported.
12
+ */
13
+ export declare class Group {
14
+ leanIMT: LeanIMT;
15
+ /**
16
+ * Creates a new instance of the Group. Optionally, a list of identity commitments can
17
+ * be passed as a parameter. Adding members in chunks is more efficient than adding
18
+ * them one by one with the `addMember` function.
19
+ * @param members A list of identity commitments.
20
+ */
21
+ constructor(members?: BigNumber[]);
22
+ /**
23
+ * Returns the root hash of the tree.
24
+ * @returns The root hash as a string.
25
+ */
26
+ get root(): bigint;
27
+ /**
28
+ * Returns the depth of the tree.
29
+ * @returns The tree depth as a number.
30
+ */
31
+ get depth(): number;
32
+ /**
33
+ * Returns the size of the tree (i.e. number of leaves).
34
+ * @returns The tree size as a number.
35
+ */
36
+ get size(): number;
37
+ /**
38
+ * Returns the members (i.e. identity commitments) of the group.
39
+ * @returns The list of members of the group.
40
+ */
41
+ get members(): bigint[];
42
+ /**
43
+ * Returns the index of a member. If the member does not exist it returns -1.
44
+ * @param member A member of the group.
45
+ * @returns The index of the member, or -1 if it does not exist.
46
+ */
47
+ indexOf(member: BigNumber): number;
48
+ /**
49
+ * Adds a new member to the group.
50
+ * @param member The new member to be added.
51
+ */
52
+ addMember(member: BigNumber): void;
53
+ /**
54
+ * Adds new members to the group.
55
+ * @param members New members.
56
+ */
57
+ addMembers(members: BigNumber[]): void;
58
+ /**
59
+ * Updates a member in the group.
60
+ * @param index Index of the member to be updated.
61
+ * @param member New member value.
62
+ */
63
+ updateMember(index: number, member: BigNumber): void;
64
+ /**
65
+ * Removes a member from the group.
66
+ * @param index The index of the member to be removed.
67
+ */
68
+ removeMember(index: number): void;
69
+ /**
70
+ * Creates a proof of membership for a member of the group.
71
+ * @param index The index of the member.
72
+ * @returns The {@link MerkleProof} object.
73
+ */
74
+ generateMerkleProof(index: number): LeanIMTMerkleProof;
75
+ /**
76
+ * Enables the conversion of the group into a JSON string that
77
+ * can be re-used for future imports. This approach is beneficial for
78
+ * large groups, as it avoids re-calculating the tree hashes.
79
+ * @returns The stringified JSON of the group.
80
+ */
81
+ export(): string;
82
+ /**
83
+ * Imports an entire group by initializing the tree without calculating
84
+ * any hashes. Note that it is crucial to ensure the integrity of the
85
+ * exported group.
86
+ * @param nodes The stringified JSON of the group.
87
+ * @returns The {@link Group} instance.
88
+ */
89
+ static import(nodes: string): Group;
90
+ }
91
+ export { LeanIMTMerkleProof as MerkleProof };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semaphore-protocol/group",
3
- "version": "4.0.0-beta",
3
+ "version": "4.0.0-beta.10",
4
4
  "description": "A library to create and manage Semaphore groups.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -32,11 +32,14 @@
32
32
  "devDependencies": {
33
33
  "@rollup/plugin-commonjs": "^25.0.7",
34
34
  "@rollup/plugin-node-resolve": "^15.2.3",
35
+ "@rollup/plugin-typescript": "^11.1.6",
35
36
  "poseidon-lite": "^0.2.0",
36
- "rollup-plugin-cleanup": "^3.2.1",
37
- "rollup-plugin-typescript2": "^0.36.0"
37
+ "rimraf": "^5.0.5",
38
+ "rollup": "^4.12.0",
39
+ "rollup-plugin-cleanup": "^3.2.1"
38
40
  },
39
41
  "dependencies": {
40
- "@zk-kit/imt": "^2.0.0-beta.1"
42
+ "@zk-kit/imt": "2.0.0-beta.4",
43
+ "@zk-kit/utils": "1.0.0-beta.4"
41
44
  }
42
45
  }
package/src/index.ts CHANGED
@@ -1,4 +1,162 @@
1
- import Group from "./group"
1
+ import { LeanIMT, LeanIMTMerkleProof } from "@zk-kit/imt"
2
+ import type { BigNumber } from "@zk-kit/utils"
3
+ import { poseidon2 } from "poseidon-lite/poseidon2"
2
4
 
3
- export { Group }
4
- export * from "./types"
5
+ /**
6
+ * The Semaphore group is a {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT}
7
+ * (Lean Incremental Merkle Tree), i.e. an optimized version of the incremental binary Merkle tree
8
+ * used by Semaphore V3. The new tree does not use zero hashes, and its depth is dynamic.
9
+ * The members of a Semaphore group, or the leaves of a tree, are the identity commitments.
10
+ * Thanks to the properties of Merkle trees, it can be efficiently demonstrated that a group
11
+ * member belongs to the group.
12
+ * This class supports operations such as member addition, update, removal and Merkle proof
13
+ * generation and verification. Groups can also be exported or imported.
14
+ */
15
+ export class Group {
16
+ // The {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT} instance.
17
+ public leanIMT: LeanIMT
18
+
19
+ /**
20
+ * Creates a new instance of the Group. Optionally, a list of identity commitments can
21
+ * be passed as a parameter. Adding members in chunks is more efficient than adding
22
+ * them one by one with the `addMember` function.
23
+ * @param members A list of identity commitments.
24
+ */
25
+ constructor(members: BigNumber[] = []) {
26
+ for (const member of members) {
27
+ if (member === 0n || member === "0") {
28
+ throw new Error("Failed to add member: value cannot be 0")
29
+ }
30
+ }
31
+
32
+ this.leanIMT = new LeanIMT((a, b) => poseidon2([a, b]), members.map(BigInt))
33
+ }
34
+
35
+ /**
36
+ * Returns the root hash of the tree.
37
+ * @returns The root hash as a string.
38
+ */
39
+ public get root(): bigint {
40
+ return this.leanIMT.root ? this.leanIMT.root : 0n
41
+ }
42
+
43
+ /**
44
+ * Returns the depth of the tree.
45
+ * @returns The tree depth as a number.
46
+ */
47
+ public get depth(): number {
48
+ return this.leanIMT.depth
49
+ }
50
+
51
+ /**
52
+ * Returns the size of the tree (i.e. number of leaves).
53
+ * @returns The tree size as a number.
54
+ */
55
+ public get size(): number {
56
+ return this.leanIMT.size
57
+ }
58
+
59
+ /**
60
+ * Returns the members (i.e. identity commitments) of the group.
61
+ * @returns The list of members of the group.
62
+ */
63
+ public get members(): bigint[] {
64
+ return this.leanIMT.leaves
65
+ }
66
+
67
+ /**
68
+ * Returns the index of a member. If the member does not exist it returns -1.
69
+ * @param member A member of the group.
70
+ * @returns The index of the member, or -1 if it does not exist.
71
+ */
72
+ public indexOf(member: BigNumber): number {
73
+ return this.leanIMT.indexOf(BigInt(member))
74
+ }
75
+
76
+ /**
77
+ * Adds a new member to the group.
78
+ * @param member The new member to be added.
79
+ */
80
+ public addMember(member: BigNumber) {
81
+ if (member === 0n || member === "0") {
82
+ throw new Error("Failed to add member: value cannot be 0")
83
+ }
84
+
85
+ this.leanIMT.insert(BigInt(member))
86
+ }
87
+
88
+ /**
89
+ * Adds new members to the group.
90
+ * @param members New members.
91
+ */
92
+ public addMembers(members: BigNumber[]) {
93
+ for (const member of members) {
94
+ if (member === 0n || member === "0") {
95
+ throw new Error("Failed to add member: value cannot be 0")
96
+ }
97
+ }
98
+
99
+ this.leanIMT.insertMany(members.map(BigInt))
100
+ }
101
+
102
+ /**
103
+ * Updates a member in the group.
104
+ * @param index Index of the member to be updated.
105
+ * @param member New member value.
106
+ */
107
+ public updateMember(index: number, member: BigNumber) {
108
+ if (this.members[index] === 0n) {
109
+ throw new Error("Failed to update member: it has been removed")
110
+ }
111
+
112
+ this.leanIMT.update(index, BigInt(member))
113
+ }
114
+
115
+ /**
116
+ * Removes a member from the group.
117
+ * @param index The index of the member to be removed.
118
+ */
119
+ public removeMember(index: number) {
120
+ if (this.members[index] === 0n) {
121
+ throw new Error("Failed to remove member: it has already been removed")
122
+ }
123
+
124
+ this.leanIMT.update(index, 0n)
125
+ }
126
+
127
+ /**
128
+ * Creates a proof of membership for a member of the group.
129
+ * @param index The index of the member.
130
+ * @returns The {@link MerkleProof} object.
131
+ */
132
+ public generateMerkleProof(index: number): LeanIMTMerkleProof {
133
+ return this.leanIMT.generateProof(index)
134
+ }
135
+
136
+ /**
137
+ * Enables the conversion of the group into a JSON string that
138
+ * can be re-used for future imports. This approach is beneficial for
139
+ * large groups, as it avoids re-calculating the tree hashes.
140
+ * @returns The stringified JSON of the group.
141
+ */
142
+ public export(): string {
143
+ return this.leanIMT.export()
144
+ }
145
+
146
+ /**
147
+ * Imports an entire group by initializing the tree without calculating
148
+ * any hashes. Note that it is crucial to ensure the integrity of the
149
+ * exported group.
150
+ * @param nodes The stringified JSON of the group.
151
+ * @returns The {@link Group} instance.
152
+ */
153
+ static import(nodes: string): Group {
154
+ const group = new Group()
155
+
156
+ group.leanIMT.import(nodes)
157
+
158
+ return group
159
+ }
160
+ }
161
+
162
+ export { LeanIMTMerkleProof as MerkleProof }
@@ -1,90 +0,0 @@
1
- import { LeanIMT } from "@zk-kit/imt";
2
- import { BigNumberish, MerkleProof } from "./types";
3
- /**
4
- * The Semaphore group is a {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT}
5
- * (Lean Incremental Merkle Tree), i.e. an optimized version of the incremental binary Merkle tree
6
- * used by Semaphore V3. The new tree does not use zero hashes, and its depth is dynamic.
7
- * The members of a Semaphore group, or the leaves of a tree, are the identity commitments.
8
- * Thanks to the properties of Merkle trees, it can be efficiently demonstrated that a group
9
- * member belongs to the group.
10
- * This class supports operations such as member addition, update, removal and Merkle proof
11
- * generation and verification. Groups can also be exported or imported.
12
- */
13
- export default class Group {
14
- leanIMT: LeanIMT;
15
- /**
16
- * Creates a new instance of the Group. Optionally, a list of identity commitments can
17
- * be passed as a parameter. Adding members in chunks is more efficient than adding
18
- * them one by one with the `addMember` function.
19
- * @param members A list of identity commitments.
20
- */
21
- constructor(members?: BigNumberish[]);
22
- /**
23
- * Returns the root hash of the tree.
24
- * @returns The root hash as a string.
25
- */
26
- get root(): string;
27
- /**
28
- * Returns the depth of the tree.
29
- * @returns The tree depth as a number.
30
- */
31
- get depth(): number;
32
- /**
33
- * Returns the size of the tree (i.e. number of leaves).
34
- * @returns The tree size as a number.
35
- */
36
- get size(): number;
37
- /**
38
- * Returns the members (i.e. identity commitments) of the group.
39
- * @returns The list of members of the group.
40
- */
41
- get members(): string[];
42
- /**
43
- * Returns the index of a member. If the member does not exist it returns -1.
44
- * @param member A member of the group.
45
- * @returns The index of the member, or -1 if it does not exist.
46
- */
47
- indexOf(member: BigNumberish): number;
48
- /**
49
- * Adds a new member to the group.
50
- * @param member The new member to be added.
51
- */
52
- addMember(member: BigNumberish): void;
53
- /**
54
- * Adds new members to the group.
55
- * @param members New members.
56
- */
57
- addMembers(members: BigNumberish[]): void;
58
- /**
59
- * Updates a member in the group.
60
- * @param index Index of the member to be updated.
61
- * @param member New member value.
62
- */
63
- updateMember(index: number, member: BigNumberish): void;
64
- /**
65
- * Removes a member from the group.
66
- * @param index The index of the member to be removed.
67
- */
68
- removeMember(index: number): void;
69
- /**
70
- * Creates a proof of membership for a member of the group.
71
- * @param index The index of the member.
72
- * @returns The {@link MerkleProof} object.
73
- */
74
- generateMerkleProof(_index: number): MerkleProof;
75
- /**
76
- * Enables the conversion of the group into a JSON string that
77
- * can be re-used for future imports. This approach is beneficial for
78
- * large groups, as it avoids re-calculating the tree hashes.
79
- * @returns The stringified JSON of the group.
80
- */
81
- export(): string;
82
- /**
83
- * Imports an entire group by initializing the tree without calculating
84
- * any hashes. Note that it is crucial to ensure the integrity of the
85
- * exported group.
86
- * @param nodes The stringified JSON of the group.
87
- * @returns The {@link Group} instance.
88
- */
89
- static import(exportedGroup: string): Group;
90
- }
@@ -1,3 +0,0 @@
1
- import { LeanIMTMerkleProof } from "@zk-kit/imt";
2
- export type BigNumberish = string | number | bigint;
3
- export type MerkleProof = LeanIMTMerkleProof<string>;
package/src/group.ts DELETED
@@ -1,143 +0,0 @@
1
- import { LeanIMT } from "@zk-kit/imt"
2
- import { poseidon2 } from "poseidon-lite/poseidon2"
3
- import { BigNumberish, MerkleProof } from "./types"
4
-
5
- /**
6
- * The Semaphore group is a {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT}
7
- * (Lean Incremental Merkle Tree), i.e. an optimized version of the incremental binary Merkle tree
8
- * used by Semaphore V3. The new tree does not use zero hashes, and its depth is dynamic.
9
- * The members of a Semaphore group, or the leaves of a tree, are the identity commitments.
10
- * Thanks to the properties of Merkle trees, it can be efficiently demonstrated that a group
11
- * member belongs to the group.
12
- * This class supports operations such as member addition, update, removal and Merkle proof
13
- * generation and verification. Groups can also be exported or imported.
14
- */
15
- export default class Group {
16
- // The {@link https://zkkit.pse.dev/classes/_zk_kit_imt.LeanIMT.html | LeanIMT} instance.
17
- public leanIMT: LeanIMT
18
-
19
- /**
20
- * Creates a new instance of the Group. Optionally, a list of identity commitments can
21
- * be passed as a parameter. Adding members in chunks is more efficient than adding
22
- * them one by one with the `addMember` function.
23
- * @param members A list of identity commitments.
24
- */
25
- constructor(members: BigNumberish[] = []) {
26
- this.leanIMT = new LeanIMT((a, b) => poseidon2([a, b]), members.map(BigInt))
27
- }
28
-
29
- /**
30
- * Returns the root hash of the tree.
31
- * @returns The root hash as a string.
32
- */
33
- public get root(): string {
34
- return this.leanIMT.root ? this.leanIMT.root.toString() : "0"
35
- }
36
-
37
- /**
38
- * Returns the depth of the tree.
39
- * @returns The tree depth as a number.
40
- */
41
- public get depth(): number {
42
- return this.leanIMT.depth
43
- }
44
-
45
- /**
46
- * Returns the size of the tree (i.e. number of leaves).
47
- * @returns The tree size as a number.
48
- */
49
- public get size(): number {
50
- return this.leanIMT.size
51
- }
52
-
53
- /**
54
- * Returns the members (i.e. identity commitments) of the group.
55
- * @returns The list of members of the group.
56
- */
57
- public get members(): string[] {
58
- return this.leanIMT.leaves.map(String)
59
- }
60
-
61
- /**
62
- * Returns the index of a member. If the member does not exist it returns -1.
63
- * @param member A member of the group.
64
- * @returns The index of the member, or -1 if it does not exist.
65
- */
66
- public indexOf(member: BigNumberish): number {
67
- return this.leanIMT.indexOf(BigInt(member))
68
- }
69
-
70
- /**
71
- * Adds a new member to the group.
72
- * @param member The new member to be added.
73
- */
74
- public addMember(member: BigNumberish) {
75
- this.leanIMT.insert(BigInt(member))
76
- }
77
-
78
- /**
79
- * Adds new members to the group.
80
- * @param members New members.
81
- */
82
- public addMembers(members: BigNumberish[]) {
83
- this.leanIMT.insertMany(members.map(BigInt))
84
- }
85
-
86
- /**
87
- * Updates a member in the group.
88
- * @param index Index of the member to be updated.
89
- * @param member New member value.
90
- */
91
- public updateMember(index: number, member: BigNumberish) {
92
- this.leanIMT.update(index, BigInt(member))
93
- }
94
-
95
- /**
96
- * Removes a member from the group.
97
- * @param index The index of the member to be removed.
98
- */
99
- public removeMember(index: number) {
100
- this.leanIMT.update(index, BigInt(0))
101
- }
102
-
103
- /**
104
- * Creates a proof of membership for a member of the group.
105
- * @param index The index of the member.
106
- * @returns The {@link MerkleProof} object.
107
- */
108
- public generateMerkleProof(_index: number): MerkleProof {
109
- const { index, leaf, root, siblings } = this.leanIMT.generateProof(_index)
110
-
111
- return {
112
- index,
113
- leaf: leaf.toString(),
114
- root: root.toString(),
115
- siblings: siblings.map(String)
116
- }
117
- }
118
-
119
- /**
120
- * Enables the conversion of the group into a JSON string that
121
- * can be re-used for future imports. This approach is beneficial for
122
- * large groups, as it avoids re-calculating the tree hashes.
123
- * @returns The stringified JSON of the group.
124
- */
125
- public export(): string {
126
- return this.leanIMT.export()
127
- }
128
-
129
- /**
130
- * Imports an entire group by initializing the tree without calculating
131
- * any hashes. Note that it is crucial to ensure the integrity of the
132
- * exported group.
133
- * @param nodes The stringified JSON of the group.
134
- * @returns The {@link Group} instance.
135
- */
136
- static import(exportedGroup: string): Group {
137
- const group = new Group()
138
-
139
- group.leanIMT.import(exportedGroup)
140
-
141
- return group
142
- }
143
- }
@@ -1,4 +0,0 @@
1
- import { LeanIMTMerkleProof } from "@zk-kit/imt"
2
-
3
- export type BigNumberish = string | number | bigint
4
- export type MerkleProof = LeanIMTMerkleProof<string>