@waku/rln 0.0.2-8a6571f.0 → 0.0.2-a3e7f15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle/packages/rln/dist/contract/rln_contract.js +95 -25
- package/bundle/packages/rln/dist/rln.js +0 -8
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/rln_contract.d.ts +5 -3
- package/dist/contract/rln_contract.js +95 -25
- package/dist/contract/rln_contract.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/rln.js +0 -8
- package/dist/rln.js.map +1 -1
- package/package.json +1 -1
- package/src/contract/rln_contract.ts +129 -27
- package/src/index.ts +11 -0
- package/src/rln.ts +0 -9
@@ -25,7 +25,8 @@ class RLNContract {
|
|
25
25
|
rateLimit;
|
26
26
|
_members = new Map();
|
27
27
|
_membersFilter;
|
28
|
-
|
28
|
+
_membershipErasedFilter;
|
29
|
+
_membersExpiredFilter;
|
29
30
|
/**
|
30
31
|
* Asynchronous initializer for RLNContract.
|
31
32
|
* Allows injecting a mocked contract for testing purposes.
|
@@ -47,9 +48,10 @@ class RLNContract {
|
|
47
48
|
// Use the injected contract if provided; otherwise, instantiate a new one.
|
48
49
|
this.contract = contract || new Contract(address, RLN_ABI, signer);
|
49
50
|
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
50
|
-
// Initialize event filters
|
51
|
+
// Initialize event filters
|
51
52
|
this._membersFilter = this.contract.filters.MembershipRegistered();
|
52
|
-
this.
|
53
|
+
this._membershipErasedFilter = this.contract.filters.MembershipErased();
|
54
|
+
this._membersExpiredFilter = this.contract.filters.MembershipExpired();
|
53
55
|
}
|
54
56
|
/**
|
55
57
|
* Gets the current rate limit for this contract instance
|
@@ -110,7 +112,7 @@ class RLNContract {
|
|
110
112
|
this.contract.maxTotalRateLimit(),
|
111
113
|
this.contract.currentTotalRateLimit()
|
112
114
|
]);
|
113
|
-
return maxTotal
|
115
|
+
return Number(maxTotal) - Number(currentTotal);
|
114
116
|
}
|
115
117
|
/**
|
116
118
|
* Updates the rate limit for future registrations
|
@@ -129,11 +131,17 @@ class RLNContract {
|
|
129
131
|
}
|
130
132
|
return this._membersFilter;
|
131
133
|
}
|
132
|
-
get
|
133
|
-
if (!this.
|
134
|
-
throw Error("
|
134
|
+
get membershipErasedFilter() {
|
135
|
+
if (!this._membershipErasedFilter) {
|
136
|
+
throw Error("MembershipErased filter was not initialized.");
|
135
137
|
}
|
136
|
-
return this.
|
138
|
+
return this._membershipErasedFilter;
|
139
|
+
}
|
140
|
+
get membersExpiredFilter() {
|
141
|
+
if (!this._membersExpiredFilter) {
|
142
|
+
throw Error("MembersExpired filter was not initialized.");
|
143
|
+
}
|
144
|
+
return this._membersExpiredFilter;
|
137
145
|
}
|
138
146
|
async fetchMembers(rlnInstance, options = {}) {
|
139
147
|
const registeredMemberEvents = await queryFilter(this.contract, {
|
@@ -144,9 +152,18 @@ class RLNContract {
|
|
144
152
|
const removedMemberEvents = await queryFilter(this.contract, {
|
145
153
|
fromBlock: this.deployBlock,
|
146
154
|
...options,
|
147
|
-
membersFilter: this.
|
155
|
+
membersFilter: this.membershipErasedFilter
|
148
156
|
});
|
149
|
-
const
|
157
|
+
const expiredMemberEvents = await queryFilter(this.contract, {
|
158
|
+
fromBlock: this.deployBlock,
|
159
|
+
...options,
|
160
|
+
membersFilter: this.membersExpiredFilter
|
161
|
+
});
|
162
|
+
const events = [
|
163
|
+
...registeredMemberEvents,
|
164
|
+
...removedMemberEvents,
|
165
|
+
...expiredMemberEvents
|
166
|
+
];
|
150
167
|
this.processEvents(rlnInstance, events);
|
151
168
|
}
|
152
169
|
processEvents(rlnInstance, events) {
|
@@ -156,8 +173,15 @@ class RLNContract {
|
|
156
173
|
if (!evt.args) {
|
157
174
|
return;
|
158
175
|
}
|
159
|
-
if (evt.event === "MembershipErased"
|
160
|
-
|
176
|
+
if (evt.event === "MembershipErased" ||
|
177
|
+
evt.event === "MembershipExpired") {
|
178
|
+
let index = evt.args.index;
|
179
|
+
if (!index) {
|
180
|
+
return;
|
181
|
+
}
|
182
|
+
if (typeof index === "number" || typeof index === "string") {
|
183
|
+
index = BigNumber.from(index);
|
184
|
+
}
|
161
185
|
const toRemoveVal = toRemoveTable.get(evt.blockNumber);
|
162
186
|
if (toRemoveVal != undefined) {
|
163
187
|
toRemoveVal.push(index.toNumber());
|
@@ -185,13 +209,17 @@ class RLNContract {
|
|
185
209
|
if (!evt.args)
|
186
210
|
return;
|
187
211
|
const _idCommitment = evt.args.idCommitment;
|
188
|
-
|
212
|
+
let index = evt.args.index;
|
189
213
|
if (!_idCommitment || !index) {
|
190
214
|
return;
|
191
215
|
}
|
216
|
+
if (typeof index === "number" || typeof index === "string") {
|
217
|
+
index = BigNumber.from(index);
|
218
|
+
}
|
192
219
|
const idCommitment = zeroPadLE(hexToBytes(_idCommitment), 32);
|
193
220
|
rlnInstance.zerokit.insertMember(idCommitment);
|
194
|
-
|
221
|
+
const numericIndex = index.toNumber();
|
222
|
+
this._members.set(numericIndex, {
|
195
223
|
index,
|
196
224
|
idCommitment: _idCommitment
|
197
225
|
});
|
@@ -213,18 +241,36 @@ class RLNContract {
|
|
213
241
|
});
|
214
242
|
}
|
215
243
|
subscribeToMembers(rlnInstance) {
|
216
|
-
this.contract.on(this.membersFilter, (_idCommitment,
|
244
|
+
this.contract.on(this.membersFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
245
|
+
this.processEvents(rlnInstance, [event]);
|
246
|
+
});
|
247
|
+
this.contract.on(this.membershipErasedFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
217
248
|
this.processEvents(rlnInstance, [event]);
|
218
249
|
});
|
219
|
-
this.contract.on(this.
|
250
|
+
this.contract.on(this.membersExpiredFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
220
251
|
this.processEvents(rlnInstance, [event]);
|
221
252
|
});
|
222
253
|
}
|
223
254
|
async registerWithIdentity(identity) {
|
224
255
|
try {
|
225
256
|
log.info(`Registering identity with rate limit: ${this.rateLimit} messages/epoch`);
|
226
|
-
|
257
|
+
// Check if the ID commitment is already registered
|
258
|
+
const existingIndex = await this.getMemberIndex(identity.IDCommitmentBigInt.toString());
|
259
|
+
if (existingIndex) {
|
260
|
+
throw new Error(`ID commitment is already registered with index ${existingIndex}`);
|
261
|
+
}
|
262
|
+
// Check if there's enough remaining rate limit
|
263
|
+
const remainingRateLimit = await this.getRemainingTotalRateLimit();
|
264
|
+
if (remainingRateLimit < this.rateLimit) {
|
265
|
+
throw new Error(`Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`);
|
266
|
+
}
|
267
|
+
const estimatedGas = await this.contract.estimateGas.register(identity.IDCommitmentBigInt, this.rateLimit, []);
|
268
|
+
const gasLimit = estimatedGas.add(10000);
|
269
|
+
const txRegisterResponse = await this.contract.register(identity.IDCommitmentBigInt, this.rateLimit, [], { gasLimit });
|
227
270
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
271
|
+
if (txRegisterReceipt.status === 0) {
|
272
|
+
throw new Error("Transaction failed on-chain");
|
273
|
+
}
|
228
274
|
const memberRegistered = txRegisterReceipt.events?.find((event) => event.event === "MembershipRegistered");
|
229
275
|
if (!memberRegistered || !memberRegistered.args) {
|
230
276
|
log.error("Failed to register membership: No MembershipRegistered event found");
|
@@ -232,14 +278,14 @@ class RLNContract {
|
|
232
278
|
}
|
233
279
|
const decodedData = {
|
234
280
|
idCommitment: memberRegistered.args.idCommitment,
|
235
|
-
|
281
|
+
membershipRateLimit: memberRegistered.args.membershipRateLimit,
|
236
282
|
index: memberRegistered.args.index
|
237
283
|
};
|
238
284
|
log.info(`Successfully registered membership with index ${decodedData.index} ` +
|
239
|
-
`and rate limit ${decodedData.
|
285
|
+
`and rate limit ${decodedData.membershipRateLimit}`);
|
240
286
|
const network = await this.contract.provider.getNetwork();
|
241
287
|
const address = this.contract.address;
|
242
|
-
const membershipId = decodedData.index
|
288
|
+
const membershipId = Number(decodedData.index);
|
243
289
|
return {
|
244
290
|
identity,
|
245
291
|
membership: {
|
@@ -250,8 +296,32 @@ class RLNContract {
|
|
250
296
|
};
|
251
297
|
}
|
252
298
|
catch (error) {
|
253
|
-
|
254
|
-
|
299
|
+
if (error instanceof Error) {
|
300
|
+
const errorMessage = error.message;
|
301
|
+
log.error("registerWithIdentity - error message:", errorMessage);
|
302
|
+
log.error("registerWithIdentity - error stack:", error.stack);
|
303
|
+
// Try to extract more specific error information
|
304
|
+
if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) {
|
305
|
+
throw new Error("Registration failed: Cannot exceed maximum total rate limit");
|
306
|
+
}
|
307
|
+
else if (errorMessage.includes("InvalidIdCommitment")) {
|
308
|
+
throw new Error("Registration failed: Invalid ID commitment");
|
309
|
+
}
|
310
|
+
else if (errorMessage.includes("InvalidMembershipRateLimit")) {
|
311
|
+
throw new Error("Registration failed: Invalid membership rate limit");
|
312
|
+
}
|
313
|
+
else if (errorMessage.includes("execution reverted")) {
|
314
|
+
throw new Error("Contract execution reverted. Check contract requirements.");
|
315
|
+
}
|
316
|
+
else {
|
317
|
+
throw new Error(`Error in registerWithIdentity: ${errorMessage}`);
|
318
|
+
}
|
319
|
+
}
|
320
|
+
else {
|
321
|
+
throw new Error("Unknown error in registerWithIdentity", {
|
322
|
+
cause: error
|
323
|
+
});
|
324
|
+
}
|
255
325
|
}
|
256
326
|
}
|
257
327
|
/**
|
@@ -287,14 +357,14 @@ class RLNContract {
|
|
287
357
|
}
|
288
358
|
const decodedData = {
|
289
359
|
idCommitment: memberRegistered.args.idCommitment,
|
290
|
-
|
360
|
+
membershipRateLimit: memberRegistered.args.membershipRateLimit,
|
291
361
|
index: memberRegistered.args.index
|
292
362
|
};
|
293
363
|
log.info(`Successfully registered membership with permit. Index: ${decodedData.index}, ` +
|
294
|
-
`Rate limit: ${decodedData.
|
364
|
+
`Rate limit: ${decodedData.membershipRateLimit}, Erased ${idCommitmentsToErase.length} commitments`);
|
295
365
|
const network = await this.contract.provider.getNetwork();
|
296
366
|
const address = this.contract.address;
|
297
|
-
const membershipId = decodedData.index
|
367
|
+
const membershipId = Number(decodedData.index);
|
298
368
|
return {
|
299
369
|
identity,
|
300
370
|
membership: {
|
@@ -100,8 +100,6 @@ class RLNInstance {
|
|
100
100
|
return this._signer;
|
101
101
|
}
|
102
102
|
async start(options = {}) {
|
103
|
-
// eslint-disable-next-line no-console
|
104
|
-
console.log("starting", options);
|
105
103
|
if (this.started || this.starting) {
|
106
104
|
return;
|
107
105
|
}
|
@@ -133,12 +131,6 @@ class RLNInstance {
|
|
133
131
|
if (address === SEPOLIA_CONTRACT.address) {
|
134
132
|
chainId = SEPOLIA_CONTRACT.chainId;
|
135
133
|
}
|
136
|
-
// eslint-disable-next-line no-console
|
137
|
-
console.log({
|
138
|
-
chainId,
|
139
|
-
address,
|
140
|
-
SEPOLIA_CONTRACT
|
141
|
-
});
|
142
134
|
const signer = options.signer || (await extractMetaMaskSigner());
|
143
135
|
const currentChainId = await signer.getChainId();
|
144
136
|
if (chainId && chainId !== currentChainId) {
|