@waku/rln 0.0.2-950aefb.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 +34 -155
- package/bundle/packages/rln/dist/rln.js +0 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/rln_contract.d.ts +4 -10
- package/dist/contract/rln_contract.js +34 -155
- package/dist/contract/rln_contract.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/rln.js +0 -2
- package/dist/rln.js.map +1 -1
- package/package.json +1 -1
- package/src/contract/rln_contract.ts +40 -223
- package/src/index.ts +11 -0
- package/src/rln.ts +0 -3
@@ -10,7 +10,6 @@ import { RATE_LIMIT_PARAMS, DEFAULT_RATE_LIMIT } from './constants.js';
|
|
10
10
|
import { Contract } from '../../../../node_modules/@ethersproject/contracts/lib.esm/index.js';
|
11
11
|
import { BigNumber } from '../../../../node_modules/@ethersproject/bignumber/lib.esm/bignumber.js';
|
12
12
|
|
13
|
-
/* eslint-disable no-console */
|
14
13
|
const log = new Logger("waku:rln:contract");
|
15
14
|
var MembershipState;
|
16
15
|
(function (MembershipState) {
|
@@ -26,7 +25,7 @@ class RLNContract {
|
|
26
25
|
rateLimit;
|
27
26
|
_members = new Map();
|
28
27
|
_membersFilter;
|
29
|
-
|
28
|
+
_membershipErasedFilter;
|
30
29
|
_membersExpiredFilter;
|
31
30
|
/**
|
32
31
|
* Asynchronous initializer for RLNContract.
|
@@ -51,7 +50,7 @@ class RLNContract {
|
|
51
50
|
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
52
51
|
// Initialize event filters
|
53
52
|
this._membersFilter = this.contract.filters.MembershipRegistered();
|
54
|
-
this.
|
53
|
+
this._membershipErasedFilter = this.contract.filters.MembershipErased();
|
55
54
|
this._membersExpiredFilter = this.contract.filters.MembershipExpired();
|
56
55
|
}
|
57
56
|
/**
|
@@ -109,12 +108,11 @@ class RLNContract {
|
|
109
108
|
* @returns Promise<number> The remaining rate limit that can be allocated
|
110
109
|
*/
|
111
110
|
async getRemainingTotalRateLimit() {
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
return 10_000;
|
111
|
+
const [maxTotal, currentTotal] = await Promise.all([
|
112
|
+
this.contract.maxTotalRateLimit(),
|
113
|
+
this.contract.currentTotalRateLimit()
|
114
|
+
]);
|
115
|
+
return Number(maxTotal) - Number(currentTotal);
|
118
116
|
}
|
119
117
|
/**
|
120
118
|
* Updates the rate limit for future registrations
|
@@ -133,11 +131,11 @@ class RLNContract {
|
|
133
131
|
}
|
134
132
|
return this._membersFilter;
|
135
133
|
}
|
136
|
-
get
|
137
|
-
if (!this.
|
138
|
-
throw Error("
|
134
|
+
get membershipErasedFilter() {
|
135
|
+
if (!this._membershipErasedFilter) {
|
136
|
+
throw Error("MembershipErased filter was not initialized.");
|
139
137
|
}
|
140
|
-
return this.
|
138
|
+
return this._membershipErasedFilter;
|
141
139
|
}
|
142
140
|
get membersExpiredFilter() {
|
143
141
|
if (!this._membersExpiredFilter) {
|
@@ -154,7 +152,7 @@ class RLNContract {
|
|
154
152
|
const removedMemberEvents = await queryFilter(this.contract, {
|
155
153
|
fromBlock: this.deployBlock,
|
156
154
|
...options,
|
157
|
-
membersFilter: this.
|
155
|
+
membersFilter: this.membershipErasedFilter
|
158
156
|
});
|
159
157
|
const expiredMemberEvents = await queryFilter(this.contract, {
|
160
158
|
fromBlock: this.deployBlock,
|
@@ -177,12 +175,10 @@ class RLNContract {
|
|
177
175
|
}
|
178
176
|
if (evt.event === "MembershipErased" ||
|
179
177
|
evt.event === "MembershipExpired") {
|
180
|
-
// Both MembershipErased and MembershipExpired events should remove members
|
181
178
|
let index = evt.args.index;
|
182
179
|
if (!index) {
|
183
180
|
return;
|
184
181
|
}
|
185
|
-
// Convert index to ethers.BigNumber if it's not already
|
186
182
|
if (typeof index === "number" || typeof index === "string") {
|
187
183
|
index = BigNumber.from(index);
|
188
184
|
}
|
@@ -214,20 +210,17 @@ class RLNContract {
|
|
214
210
|
return;
|
215
211
|
const _idCommitment = evt.args.idCommitment;
|
216
212
|
let index = evt.args.index;
|
217
|
-
// Ensure index is an ethers.BigNumber
|
218
213
|
if (!_idCommitment || !index) {
|
219
214
|
return;
|
220
215
|
}
|
221
|
-
// Convert index to ethers.BigNumber if it's not already
|
222
216
|
if (typeof index === "number" || typeof index === "string") {
|
223
217
|
index = BigNumber.from(index);
|
224
218
|
}
|
225
219
|
const idCommitment = zeroPadLE(hexToBytes(_idCommitment), 32);
|
226
220
|
rlnInstance.zerokit.insertMember(idCommitment);
|
227
|
-
// Always store the numeric index as the key, but the BigNumber as the value
|
228
221
|
const numericIndex = index.toNumber();
|
229
222
|
this._members.set(numericIndex, {
|
230
|
-
index,
|
223
|
+
index,
|
231
224
|
idCommitment: _idCommitment
|
232
225
|
});
|
233
226
|
});
|
@@ -251,7 +244,7 @@ class RLNContract {
|
|
251
244
|
this.contract.on(this.membersFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
252
245
|
this.processEvents(rlnInstance, [event]);
|
253
246
|
});
|
254
|
-
this.contract.on(this.
|
247
|
+
this.contract.on(this.membershipErasedFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
255
248
|
this.processEvents(rlnInstance, [event]);
|
256
249
|
});
|
257
250
|
this.contract.on(this.membersExpiredFilter, (_idCommitment, _membershipRateLimit, _index, event) => {
|
@@ -260,69 +253,40 @@ class RLNContract {
|
|
260
253
|
}
|
261
254
|
async registerWithIdentity(identity) {
|
262
255
|
try {
|
263
|
-
console.log("registerWithIdentity - starting registration process");
|
264
|
-
console.log("registerWithIdentity - identity:", identity);
|
265
|
-
console.log("registerWithIdentity - IDCommitmentBigInt:", identity.IDCommitmentBigInt.toString());
|
266
|
-
console.log("registerWithIdentity - rate limit:", this.rateLimit);
|
267
256
|
log.info(`Registering identity with rate limit: ${this.rateLimit} messages/epoch`);
|
268
257
|
// Check if the ID commitment is already registered
|
269
258
|
const existingIndex = await this.getMemberIndex(identity.IDCommitmentBigInt.toString());
|
270
259
|
if (existingIndex) {
|
271
|
-
console.error(`ID commitment is already registered with index ${existingIndex}`);
|
272
260
|
throw new Error(`ID commitment is already registered with index ${existingIndex}`);
|
273
261
|
}
|
274
262
|
// Check if there's enough remaining rate limit
|
275
263
|
const remainingRateLimit = await this.getRemainingTotalRateLimit();
|
276
264
|
if (remainingRateLimit < this.rateLimit) {
|
277
|
-
console.error(`Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`);
|
278
265
|
throw new Error(`Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`);
|
279
266
|
}
|
280
|
-
console.log("registerWithIdentity - calling contract.register");
|
281
|
-
// Estimate gas for the transaction
|
282
267
|
const estimatedGas = await this.contract.estimateGas.register(identity.IDCommitmentBigInt, this.rateLimit, []);
|
283
268
|
const gasLimit = estimatedGas.add(10000);
|
284
269
|
const txRegisterResponse = await this.contract.register(identity.IDCommitmentBigInt, this.rateLimit, [], { gasLimit });
|
285
|
-
console.log("registerWithIdentity - txRegisterResponse:", txRegisterResponse);
|
286
|
-
console.log("registerWithIdentity - hash:", txRegisterResponse.hash);
|
287
|
-
console.log("registerWithIdentity - waiting for transaction confirmation...");
|
288
270
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
289
|
-
console.log("registerWithIdentity - txRegisterReceipt:", txRegisterReceipt);
|
290
|
-
console.log("registerWithIdentity - transaction status:", txRegisterReceipt.status);
|
291
|
-
console.log("registerWithIdentity - block number:", txRegisterReceipt.blockNumber);
|
292
|
-
console.log("registerWithIdentity - gas used:", txRegisterReceipt.gasUsed.toString());
|
293
|
-
// Check transaction status
|
294
271
|
if (txRegisterReceipt.status === 0) {
|
295
|
-
console.error("Transaction failed on-chain");
|
296
272
|
throw new Error("Transaction failed on-chain");
|
297
273
|
}
|
298
274
|
const memberRegistered = txRegisterReceipt.events?.find((event) => event.event === "MembershipRegistered");
|
299
|
-
console.log("registerWithIdentity - memberRegistered event:", memberRegistered);
|
300
275
|
if (!memberRegistered || !memberRegistered.args) {
|
301
|
-
|
302
|
-
console.log("registerWithIdentity - all events:", txRegisterReceipt.events);
|
303
|
-
console.error("Failed to register membership: No MembershipRegistered event found");
|
276
|
+
log.error("Failed to register membership: No MembershipRegistered event found");
|
304
277
|
return undefined;
|
305
278
|
}
|
306
|
-
console.log("registerWithIdentity - memberRegistered args:", memberRegistered.args);
|
307
279
|
const decodedData = {
|
308
280
|
idCommitment: memberRegistered.args.idCommitment,
|
309
281
|
membershipRateLimit: memberRegistered.args.membershipRateLimit,
|
310
282
|
index: memberRegistered.args.index
|
311
283
|
};
|
312
|
-
console.log("registerWithIdentity - decodedData:", decodedData);
|
313
|
-
console.log("registerWithIdentity - index:", decodedData.index.toString());
|
314
|
-
console.log("registerWithIdentity - membershipRateLimit:", decodedData.membershipRateLimit.toString());
|
315
284
|
log.info(`Successfully registered membership with index ${decodedData.index} ` +
|
316
285
|
`and rate limit ${decodedData.membershipRateLimit}`);
|
317
|
-
console.log("registerWithIdentity - getting network information");
|
318
286
|
const network = await this.contract.provider.getNetwork();
|
319
|
-
console.log("registerWithIdentity - network:", network);
|
320
|
-
console.log("registerWithIdentity - chainId:", network.chainId);
|
321
287
|
const address = this.contract.address;
|
322
|
-
|
323
|
-
|
324
|
-
console.log("registerWithIdentity - membershipId:", membershipId);
|
325
|
-
const result = {
|
288
|
+
const membershipId = Number(decodedData.index);
|
289
|
+
return {
|
326
290
|
identity,
|
327
291
|
membership: {
|
328
292
|
address,
|
@@ -330,39 +294,34 @@ class RLNContract {
|
|
330
294
|
chainId: network.chainId
|
331
295
|
}
|
332
296
|
};
|
333
|
-
console.log("registerWithIdentity - returning result:", result);
|
334
|
-
return result;
|
335
297
|
}
|
336
298
|
catch (error) {
|
337
|
-
console.log("registerWithIdentity - ERROR:", error);
|
338
|
-
// Improved error handling to decode contract errors
|
339
299
|
if (error instanceof Error) {
|
340
300
|
const errorMessage = error.message;
|
341
|
-
|
342
|
-
|
301
|
+
log.error("registerWithIdentity - error message:", errorMessage);
|
302
|
+
log.error("registerWithIdentity - error stack:", error.stack);
|
343
303
|
// Try to extract more specific error information
|
344
304
|
if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) {
|
345
|
-
|
305
|
+
throw new Error("Registration failed: Cannot exceed maximum total rate limit");
|
346
306
|
}
|
347
307
|
else if (errorMessage.includes("InvalidIdCommitment")) {
|
348
|
-
|
308
|
+
throw new Error("Registration failed: Invalid ID commitment");
|
349
309
|
}
|
350
310
|
else if (errorMessage.includes("InvalidMembershipRateLimit")) {
|
351
|
-
|
311
|
+
throw new Error("Registration failed: Invalid membership rate limit");
|
352
312
|
}
|
353
313
|
else if (errorMessage.includes("execution reverted")) {
|
354
|
-
|
355
|
-
console.error("Contract execution reverted. Check contract requirements.");
|
314
|
+
throw new Error("Contract execution reverted. Check contract requirements.");
|
356
315
|
}
|
357
316
|
else {
|
358
|
-
|
317
|
+
throw new Error(`Error in registerWithIdentity: ${errorMessage}`);
|
359
318
|
}
|
360
319
|
}
|
361
320
|
else {
|
362
|
-
|
321
|
+
throw new Error("Unknown error in registerWithIdentity", {
|
322
|
+
cause: error
|
323
|
+
});
|
363
324
|
}
|
364
|
-
// Re-throw the error to allow callers to handle it
|
365
|
-
throw error;
|
366
325
|
}
|
367
326
|
}
|
368
327
|
/**
|
@@ -405,7 +364,7 @@ class RLNContract {
|
|
405
364
|
`Rate limit: ${decodedData.membershipRateLimit}, Erased ${idCommitmentsToErase.length} commitments`);
|
406
365
|
const network = await this.contract.provider.getNetwork();
|
407
366
|
const address = this.contract.address;
|
408
|
-
const membershipId = decodedData.index
|
367
|
+
const membershipId = Number(decodedData.index);
|
409
368
|
return {
|
410
369
|
identity,
|
411
370
|
membership: {
|
@@ -463,29 +422,17 @@ class RLNContract {
|
|
463
422
|
}
|
464
423
|
}
|
465
424
|
async extendMembership(idCommitment) {
|
466
|
-
|
467
|
-
return await tx.wait();
|
425
|
+
return this.contract.extendMemberships([idCommitment]);
|
468
426
|
}
|
469
427
|
async eraseMembership(idCommitment, eraseFromMembershipSet = true) {
|
470
|
-
|
471
|
-
return await tx.wait();
|
428
|
+
return this.contract.eraseMemberships([idCommitment], eraseFromMembershipSet);
|
472
429
|
}
|
473
430
|
async registerMembership(idCommitment, rateLimit = DEFAULT_RATE_LIMIT) {
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
throw new Error(`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`);
|
478
|
-
}
|
479
|
-
// Try to register
|
480
|
-
return this.contract.register(idCommitment, rateLimit, []);
|
481
|
-
}
|
482
|
-
catch (error) {
|
483
|
-
console.error("Error in registerMembership:", error);
|
484
|
-
// Run debug to help diagnose the issue
|
485
|
-
await this.debugRegistration(idCommitment, rateLimit);
|
486
|
-
// Re-throw the error
|
487
|
-
throw error;
|
431
|
+
if (rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
|
432
|
+
rateLimit > RATE_LIMIT_PARAMS.MAX_RATE) {
|
433
|
+
throw new Error(`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`);
|
488
434
|
}
|
435
|
+
return this.contract.register(idCommitment, rateLimit, []);
|
489
436
|
}
|
490
437
|
async getMemberIndex(idCommitment) {
|
491
438
|
try {
|
@@ -500,74 +447,6 @@ class RLNContract {
|
|
500
447
|
return undefined;
|
501
448
|
}
|
502
449
|
}
|
503
|
-
/**
|
504
|
-
* Debug function to check why a registration might fail
|
505
|
-
* @param idCommitment The ID commitment to check
|
506
|
-
* @param rateLimit The rate limit to check
|
507
|
-
*/
|
508
|
-
async debugRegistration(idCommitment, rateLimit) {
|
509
|
-
console.log("=== DEBUG REGISTRATION ===");
|
510
|
-
console.log(`ID Commitment: ${idCommitment}`);
|
511
|
-
console.log(`Rate Limit: ${rateLimit}`);
|
512
|
-
// Check if ID commitment is already registered
|
513
|
-
try {
|
514
|
-
const existingIndex = await this.getMemberIndex(idCommitment);
|
515
|
-
if (existingIndex) {
|
516
|
-
console.error(`ERROR: ID commitment is already registered with index ${existingIndex}`);
|
517
|
-
}
|
518
|
-
else {
|
519
|
-
console.log("ID commitment is not yet registered ✓");
|
520
|
-
}
|
521
|
-
}
|
522
|
-
catch (error) {
|
523
|
-
console.error("Error checking if ID commitment is registered:", error);
|
524
|
-
}
|
525
|
-
// Check rate limit constraints
|
526
|
-
try {
|
527
|
-
const minRateLimit = await this.getMinRateLimit();
|
528
|
-
const maxRateLimit = await this.getMaxRateLimit();
|
529
|
-
const maxTotalRateLimit = await this.getMaxTotalRateLimit();
|
530
|
-
const currentTotalRateLimit = await this.getCurrentTotalRateLimit();
|
531
|
-
const remainingRateLimit = await this.getRemainingTotalRateLimit();
|
532
|
-
console.log(`Min Rate Limit: ${minRateLimit}`);
|
533
|
-
console.log(`Max Rate Limit: ${maxRateLimit}`);
|
534
|
-
console.log(`Max Total Rate Limit: ${maxTotalRateLimit}`);
|
535
|
-
console.log(`Current Total Rate Limit: ${currentTotalRateLimit}`);
|
536
|
-
console.log(`Remaining Rate Limit: ${remainingRateLimit}`);
|
537
|
-
if (rateLimit < minRateLimit) {
|
538
|
-
console.error(`ERROR: Rate limit ${rateLimit} is below minimum ${minRateLimit}`);
|
539
|
-
}
|
540
|
-
if (rateLimit > maxRateLimit) {
|
541
|
-
console.error(`ERROR: Rate limit ${rateLimit} exceeds maximum ${maxRateLimit}`);
|
542
|
-
}
|
543
|
-
if (rateLimit > remainingRateLimit) {
|
544
|
-
console.error(`ERROR: Rate limit ${rateLimit} exceeds remaining capacity ${remainingRateLimit}`);
|
545
|
-
}
|
546
|
-
}
|
547
|
-
catch (error) {
|
548
|
-
console.error("Error checking rate limit constraints:", error);
|
549
|
-
}
|
550
|
-
// Try to estimate gas for the transaction to see if it would revert
|
551
|
-
try {
|
552
|
-
await this.contract.estimateGas.register(idCommitment, rateLimit, []);
|
553
|
-
console.log("Transaction gas estimation succeeded ✓");
|
554
|
-
}
|
555
|
-
catch (error) {
|
556
|
-
console.error("Transaction would revert with error:", error);
|
557
|
-
// Try to extract more specific error information
|
558
|
-
const errorMessage = error.message;
|
559
|
-
if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) {
|
560
|
-
console.error("Cannot exceed maximum total rate limit");
|
561
|
-
}
|
562
|
-
else if (errorMessage.includes("InvalidIdCommitment")) {
|
563
|
-
console.error("Invalid ID commitment format");
|
564
|
-
}
|
565
|
-
else if (errorMessage.includes("InvalidMembershipRateLimit")) {
|
566
|
-
console.error("Invalid membership rate limit");
|
567
|
-
}
|
568
|
-
}
|
569
|
-
console.log("=== END DEBUG ===");
|
570
|
-
}
|
571
450
|
}
|
572
451
|
// These values should be tested on other networks
|
573
452
|
const FETCH_CHUNK = 5;
|
@@ -166,8 +166,6 @@ class RLNInstance {
|
|
166
166
|
if ("signature" in options) {
|
167
167
|
identity = this.zerokit.generateSeededIdentityCredential(options.signature);
|
168
168
|
}
|
169
|
-
// eslint-disable-next-line no-console
|
170
|
-
console.log("registering membership", identity);
|
171
169
|
if (!identity) {
|
172
170
|
throw Error("Missing signature or identity to register membership.");
|
173
171
|
}
|