@waku/rln 0.0.2-2eccb11.0 → 0.0.2-3ab8023.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.
@@ -1,3 +1,4 @@
1
+ /* eslint-disable no-console */
1
2
  import { Logger } from "@waku/utils";
2
3
  import { hexToBytes } from "@waku/utils/bytes";
3
4
  import { ethers } from "ethers";
@@ -112,7 +113,7 @@ export class RLNContract {
112
113
  this.contract = contract || new ethers.Contract(address, RLN_ABI, signer);
113
114
  this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
114
115
 
115
- // Initialize event filters for all relevant events
116
+ // Initialize event filters
116
117
  this._membersFilter = this.contract.filters.MembershipRegistered();
117
118
  this._membersRemovedFilter = this.contract.filters.MembershipErased();
118
119
  this._membersExpiredFilter = this.contract.filters.MembershipExpired();
@@ -267,7 +268,6 @@ export class RLNContract {
267
268
  // Both MembershipErased and MembershipExpired events should remove members
268
269
  let index = evt.args.index;
269
270
 
270
- // Ensure index is an ethers.BigNumber
271
271
  if (!index) {
272
272
  return;
273
273
  }
@@ -293,7 +293,6 @@ export class RLNContract {
293
293
  eventsPerBlock.push(evt);
294
294
  toInsertTable.set(evt.blockNumber, eventsPerBlock);
295
295
  }
296
- // MembershipExtended events don't change the membership set, so we don't need to handle them here
297
296
  });
298
297
 
299
298
  this.removeMembers(rlnInstance, toRemoveTable);
@@ -396,46 +395,149 @@ export class RLNContract {
396
395
  identity: IdentityCredential
397
396
  ): Promise<DecryptedCredentials | undefined> {
398
397
  try {
398
+ console.log("registerWithIdentity - starting registration process");
399
+ console.log("registerWithIdentity - identity:", identity);
400
+ console.log(
401
+ "registerWithIdentity - IDCommitmentBigInt:",
402
+ identity.IDCommitmentBigInt.toString()
403
+ );
404
+ console.log("registerWithIdentity - rate limit:", this.rateLimit);
405
+
399
406
  log.info(
400
407
  `Registering identity with rate limit: ${this.rateLimit} messages/epoch`
401
408
  );
402
409
 
410
+ // Check if the ID commitment is already registered
411
+ const existingIndex = await this.getMemberIndex(
412
+ identity.IDCommitmentBigInt.toString()
413
+ );
414
+ if (existingIndex) {
415
+ console.error(
416
+ `ID commitment is already registered with index ${existingIndex}`
417
+ );
418
+ throw new Error(
419
+ `ID commitment is already registered with index ${existingIndex}`
420
+ );
421
+ }
422
+
423
+ // Check if there's enough remaining rate limit
424
+ const remainingRateLimit = await this.getRemainingTotalRateLimit();
425
+ if (remainingRateLimit < this.rateLimit) {
426
+ console.error(
427
+ `Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`
428
+ );
429
+ throw new Error(
430
+ `Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`
431
+ );
432
+ }
433
+
434
+ console.log("registerWithIdentity - calling contract.register");
435
+ // Estimate gas for the transaction
436
+ const estimatedGas = await this.contract.estimateGas.register(
437
+ identity.IDCommitmentBigInt,
438
+ this.rateLimit,
439
+ []
440
+ );
441
+ const gasLimit = estimatedGas.add(10000);
442
+
403
443
  const txRegisterResponse: ethers.ContractTransaction =
404
444
  await this.contract.register(
405
445
  identity.IDCommitmentBigInt,
406
446
  this.rateLimit,
407
447
  [],
408
- { gasLimit: 300000 }
448
+ { gasLimit }
409
449
  );
450
+ console.log(
451
+ "registerWithIdentity - txRegisterResponse:",
452
+ txRegisterResponse
453
+ );
454
+ console.log("registerWithIdentity - hash:", txRegisterResponse.hash);
455
+ console.log(
456
+ "registerWithIdentity - waiting for transaction confirmation..."
457
+ );
458
+
410
459
  const txRegisterReceipt = await txRegisterResponse.wait();
460
+ console.log(
461
+ "registerWithIdentity - txRegisterReceipt:",
462
+ txRegisterReceipt
463
+ );
464
+ console.log(
465
+ "registerWithIdentity - transaction status:",
466
+ txRegisterReceipt.status
467
+ );
468
+ console.log(
469
+ "registerWithIdentity - block number:",
470
+ txRegisterReceipt.blockNumber
471
+ );
472
+ console.log(
473
+ "registerWithIdentity - gas used:",
474
+ txRegisterReceipt.gasUsed.toString()
475
+ );
476
+
477
+ // Check transaction status
478
+ if (txRegisterReceipt.status === 0) {
479
+ console.error("Transaction failed on-chain");
480
+ throw new Error("Transaction failed on-chain");
481
+ }
411
482
 
412
483
  const memberRegistered = txRegisterReceipt.events?.find(
413
484
  (event) => event.event === "MembershipRegistered"
414
485
  );
486
+ console.log(
487
+ "registerWithIdentity - memberRegistered event:",
488
+ memberRegistered
489
+ );
415
490
 
416
491
  if (!memberRegistered || !memberRegistered.args) {
417
- log.error(
492
+ console.log(
493
+ "registerWithIdentity - ERROR: no memberRegistered event found"
494
+ );
495
+ console.log(
496
+ "registerWithIdentity - all events:",
497
+ txRegisterReceipt.events
498
+ );
499
+ console.error(
418
500
  "Failed to register membership: No MembershipRegistered event found"
419
501
  );
420
502
  return undefined;
421
503
  }
422
504
 
505
+ console.log(
506
+ "registerWithIdentity - memberRegistered args:",
507
+ memberRegistered.args
508
+ );
423
509
  const decodedData: MembershipRegisteredEvent = {
424
510
  idCommitment: memberRegistered.args.idCommitment,
425
511
  membershipRateLimit: memberRegistered.args.membershipRateLimit,
426
512
  index: memberRegistered.args.index
427
513
  };
514
+ console.log("registerWithIdentity - decodedData:", decodedData);
515
+ console.log(
516
+ "registerWithIdentity - index:",
517
+ decodedData.index.toString()
518
+ );
519
+ console.log(
520
+ "registerWithIdentity - membershipRateLimit:",
521
+ decodedData.membershipRateLimit.toString()
522
+ );
428
523
 
429
524
  log.info(
430
525
  `Successfully registered membership with index ${decodedData.index} ` +
431
526
  `and rate limit ${decodedData.membershipRateLimit}`
432
527
  );
433
528
 
529
+ console.log("registerWithIdentity - getting network information");
434
530
  const network = await this.contract.provider.getNetwork();
531
+ console.log("registerWithIdentity - network:", network);
532
+ console.log("registerWithIdentity - chainId:", network.chainId);
533
+
435
534
  const address = this.contract.address;
535
+ console.log("registerWithIdentity - contract address:", address);
536
+
436
537
  const membershipId = decodedData.index.toNumber();
538
+ console.log("registerWithIdentity - membershipId:", membershipId);
437
539
 
438
- return {
540
+ const result = {
439
541
  identity,
440
542
  membership: {
441
543
  address,
@@ -443,9 +545,41 @@ export class RLNContract {
443
545
  chainId: network.chainId
444
546
  }
445
547
  };
548
+ console.log("registerWithIdentity - returning result:", result);
549
+
550
+ return result;
446
551
  } catch (error) {
447
- log.error(`Error in registerWithIdentity: ${(error as Error).message}`);
448
- return undefined;
552
+ console.log("registerWithIdentity - ERROR:", error);
553
+
554
+ // Improved error handling to decode contract errors
555
+ if (error instanceof Error) {
556
+ const errorMessage = error.message;
557
+ console.log("registerWithIdentity - error message:", errorMessage);
558
+ console.log("registerWithIdentity - error stack:", error.stack);
559
+
560
+ // Try to extract more specific error information
561
+ if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) {
562
+ console.error(
563
+ "Registration failed: Cannot exceed maximum total rate limit"
564
+ );
565
+ } else if (errorMessage.includes("InvalidIdCommitment")) {
566
+ console.error("Registration failed: Invalid ID commitment");
567
+ } else if (errorMessage.includes("InvalidMembershipRateLimit")) {
568
+ console.error("Registration failed: Invalid membership rate limit");
569
+ } else if (errorMessage.includes("execution reverted")) {
570
+ // Generic revert
571
+ console.error(
572
+ "Contract execution reverted. Check contract requirements."
573
+ );
574
+ } else {
575
+ console.error(`Error in registerWithIdentity: ${errorMessage}`);
576
+ }
577
+ } else {
578
+ console.error("Unknown error in registerWithIdentity");
579
+ }
580
+
581
+ // Re-throw the error to allow callers to handle it
582
+ throw error;
449
583
  }
450
584
  }
451
585
 
@@ -619,17 +753,28 @@ export class RLNContract {
619
753
  public async registerMembership(
620
754
  idCommitment: string,
621
755
  rateLimit: number = DEFAULT_RATE_LIMIT
622
- ): Promise<ethers.ContractReceipt> {
623
- if (
624
- rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
625
- rateLimit > RATE_LIMIT_PARAMS.MAX_RATE
626
- ) {
627
- throw new Error(
628
- `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`
629
- );
756
+ ): Promise<ethers.ContractTransaction> {
757
+ try {
758
+ if (
759
+ rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
760
+ rateLimit > RATE_LIMIT_PARAMS.MAX_RATE
761
+ ) {
762
+ throw new Error(
763
+ `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`
764
+ );
765
+ }
766
+
767
+ // Try to register
768
+ return this.contract.register(idCommitment, rateLimit, []);
769
+ } catch (error) {
770
+ console.error("Error in registerMembership:", error);
771
+
772
+ // Run debug to help diagnose the issue
773
+ await this.debugRegistration(idCommitment, rateLimit);
774
+
775
+ // Re-throw the error
776
+ throw error;
630
777
  }
631
- const tx = await this.contract.register(idCommitment, rateLimit, []);
632
- return await tx.wait();
633
778
  }
634
779
 
635
780
  private async getMemberIndex(
@@ -648,6 +793,87 @@ export class RLNContract {
648
793
  return undefined;
649
794
  }
650
795
  }
796
+
797
+ /**
798
+ * Debug function to check why a registration might fail
799
+ * @param idCommitment The ID commitment to check
800
+ * @param rateLimit The rate limit to check
801
+ */
802
+ public async debugRegistration(
803
+ idCommitment: string,
804
+ rateLimit: number
805
+ ): Promise<void> {
806
+ console.log("=== DEBUG REGISTRATION ===");
807
+ console.log(`ID Commitment: ${idCommitment}`);
808
+ console.log(`Rate Limit: ${rateLimit}`);
809
+
810
+ // Check if ID commitment is already registered
811
+ try {
812
+ const existingIndex = await this.getMemberIndex(idCommitment);
813
+ if (existingIndex) {
814
+ console.error(
815
+ `ERROR: ID commitment is already registered with index ${existingIndex}`
816
+ );
817
+ } else {
818
+ console.log("ID commitment is not yet registered ✓");
819
+ }
820
+ } catch (error) {
821
+ console.error("Error checking if ID commitment is registered:", error);
822
+ }
823
+
824
+ // Check rate limit constraints
825
+ try {
826
+ const minRateLimit = await this.getMinRateLimit();
827
+ const maxRateLimit = await this.getMaxRateLimit();
828
+ const maxTotalRateLimit = await this.getMaxTotalRateLimit();
829
+ const currentTotalRateLimit = await this.getCurrentTotalRateLimit();
830
+ const remainingRateLimit = await this.getRemainingTotalRateLimit();
831
+
832
+ console.log(`Min Rate Limit: ${minRateLimit}`);
833
+ console.log(`Max Rate Limit: ${maxRateLimit}`);
834
+ console.log(`Max Total Rate Limit: ${maxTotalRateLimit}`);
835
+ console.log(`Current Total Rate Limit: ${currentTotalRateLimit}`);
836
+ console.log(`Remaining Rate Limit: ${remainingRateLimit}`);
837
+
838
+ if (rateLimit < minRateLimit) {
839
+ console.error(
840
+ `ERROR: Rate limit ${rateLimit} is below minimum ${minRateLimit}`
841
+ );
842
+ }
843
+ if (rateLimit > maxRateLimit) {
844
+ console.error(
845
+ `ERROR: Rate limit ${rateLimit} exceeds maximum ${maxRateLimit}`
846
+ );
847
+ }
848
+ if (rateLimit > remainingRateLimit) {
849
+ console.error(
850
+ `ERROR: Rate limit ${rateLimit} exceeds remaining capacity ${remainingRateLimit}`
851
+ );
852
+ }
853
+ } catch (error) {
854
+ console.error("Error checking rate limit constraints:", error);
855
+ }
856
+
857
+ // Try to estimate gas for the transaction to see if it would revert
858
+ try {
859
+ await this.contract.estimateGas.register(idCommitment, rateLimit, []);
860
+ console.log("Transaction gas estimation succeeded ✓");
861
+ } catch (error) {
862
+ console.error("Transaction would revert with error:", error);
863
+
864
+ // Try to extract more specific error information
865
+ const errorMessage = (error as Error).message;
866
+ if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) {
867
+ console.error("Cannot exceed maximum total rate limit");
868
+ } else if (errorMessage.includes("InvalidIdCommitment")) {
869
+ console.error("Invalid ID commitment format");
870
+ } else if (errorMessage.includes("InvalidMembershipRateLimit")) {
871
+ console.error("Invalid membership rate limit");
872
+ }
873
+ }
874
+
875
+ console.log("=== END DEBUG ===");
876
+ }
651
877
  }
652
878
 
653
879
  interface CustomQueryOptions extends FetchMembersOptions {
package/src/rln.ts CHANGED
@@ -151,8 +151,6 @@ export class RLNInstance {
151
151
  }
152
152
 
153
153
  public async start(options: StartRLNOptions = {}): Promise<void> {
154
- // eslint-disable-next-line no-console
155
- console.log("starting", options);
156
154
  if (this.started || this.starting) {
157
155
  return;
158
156
  }
@@ -198,13 +196,6 @@ export class RLNInstance {
198
196
  chainId = SEPOLIA_CONTRACT.chainId;
199
197
  }
200
198
 
201
- // eslint-disable-next-line no-console
202
- console.log({
203
- chainId,
204
- address,
205
- SEPOLIA_CONTRACT
206
- });
207
-
208
199
  const signer = options.signer || (await extractMetaMaskSigner());
209
200
  const currentChainId = await signer.getChainId();
210
201
 
@@ -263,6 +254,9 @@ export class RLNInstance {
263
254
  );
264
255
  }
265
256
 
257
+ // eslint-disable-next-line no-console
258
+ console.log("registering membership", identity);
259
+
266
260
  if (!identity) {
267
261
  throw Error("Missing signature or identity to register membership.");
268
262
  }