@waku/rln 0.0.2-3ab8023.0 → 0.0.2-9094860.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/_virtual/utils.js +2 -2
- package/bundle/_virtual/utils2.js +2 -2
- package/bundle/index.js +2 -0
- package/bundle/packages/rln/dist/contract/rln_contract.js +30 -150
- package/bundle/packages/rln/dist/identity_generator.js +75 -0
- package/bundle/packages/rln/dist/rln.js +0 -2
- package/bundle/packages/rln/dist/rln_light.js +228 -0
- package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +1 -1
- package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +2 -2
- package/bundle/packages/rln/node_modules/@noble/hashes/_sha2.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/hmac.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/pbkdf2.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/scrypt.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/sha256.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/sha512.js +1 -1
- package/bundle/packages/rln/node_modules/@noble/hashes/utils.js +1 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/rln_contract.d.ts +4 -10
- package/dist/contract/rln_contract.js +30 -150
- package/dist/contract/rln_contract.js.map +1 -1
- package/dist/identity_generator.d.ts +19 -0
- package/dist/identity_generator.js +72 -0
- package/dist/identity_generator.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/rln.js +0 -2
- package/dist/rln.js.map +1 -1
- package/dist/rln_light.d.ts +95 -0
- package/dist/rln_light.js +210 -0
- package/dist/rln_light.js.map +1 -0
- package/package.json +1 -1
- package/src/contract/rln_contract.ts +36 -218
- package/src/identity_generator.ts +108 -0
- package/src/index.ts +15 -0
- package/src/rln.ts +0 -3
- package/src/rln_light.ts +304 -0
@@ -1,4 +1,3 @@
|
|
1
|
-
/* eslint-disable no-console */
|
2
1
|
import { Logger } from "@waku/utils";
|
3
2
|
import { hexToBytes } from "@waku/utils/bytes";
|
4
3
|
import { ethers } from "ethers";
|
@@ -66,7 +65,7 @@ export class RLNContract {
|
|
66
65
|
|
67
66
|
private _members: Map<number, Member> = new Map();
|
68
67
|
private _membersFilter: ethers.EventFilter;
|
69
|
-
private
|
68
|
+
private _membershipErasedFilter: ethers.EventFilter;
|
70
69
|
private _membersExpiredFilter: ethers.EventFilter;
|
71
70
|
|
72
71
|
/**
|
@@ -115,7 +114,7 @@ export class RLNContract {
|
|
115
114
|
|
116
115
|
// Initialize event filters
|
117
116
|
this._membersFilter = this.contract.filters.MembershipRegistered();
|
118
|
-
this.
|
117
|
+
this._membershipErasedFilter = this.contract.filters.MembershipErased();
|
119
118
|
this._membersExpiredFilter = this.contract.filters.MembershipExpired();
|
120
119
|
}
|
121
120
|
|
@@ -185,7 +184,7 @@ export class RLNContract {
|
|
185
184
|
this.contract.maxTotalRateLimit(),
|
186
185
|
this.contract.currentTotalRateLimit()
|
187
186
|
]);
|
188
|
-
return maxTotal
|
187
|
+
return Number(maxTotal) - Number(currentTotal);
|
189
188
|
}
|
190
189
|
|
191
190
|
/**
|
@@ -210,11 +209,11 @@ export class RLNContract {
|
|
210
209
|
return this._membersFilter;
|
211
210
|
}
|
212
211
|
|
213
|
-
private get
|
214
|
-
if (!this.
|
215
|
-
throw Error("
|
212
|
+
private get membershipErasedFilter(): ethers.EventFilter {
|
213
|
+
if (!this._membershipErasedFilter) {
|
214
|
+
throw Error("MembershipErased filter was not initialized.");
|
216
215
|
}
|
217
|
-
return this.
|
216
|
+
return this._membershipErasedFilter;
|
218
217
|
}
|
219
218
|
|
220
219
|
private get membersExpiredFilter(): ethers.EventFilter {
|
@@ -236,7 +235,7 @@ export class RLNContract {
|
|
236
235
|
const removedMemberEvents = await queryFilter(this.contract, {
|
237
236
|
fromBlock: this.deployBlock,
|
238
237
|
...options,
|
239
|
-
membersFilter: this.
|
238
|
+
membersFilter: this.membershipErasedFilter
|
240
239
|
});
|
241
240
|
const expiredMemberEvents = await queryFilter(this.contract, {
|
242
241
|
fromBlock: this.deployBlock,
|
@@ -265,14 +264,12 @@ export class RLNContract {
|
|
265
264
|
evt.event === "MembershipErased" ||
|
266
265
|
evt.event === "MembershipExpired"
|
267
266
|
) {
|
268
|
-
// Both MembershipErased and MembershipExpired events should remove members
|
269
267
|
let index = evt.args.index;
|
270
268
|
|
271
269
|
if (!index) {
|
272
270
|
return;
|
273
271
|
}
|
274
272
|
|
275
|
-
// Convert index to ethers.BigNumber if it's not already
|
276
273
|
if (typeof index === "number" || typeof index === "string") {
|
277
274
|
index = ethers.BigNumber.from(index);
|
278
275
|
}
|
@@ -310,12 +307,10 @@ export class RLNContract {
|
|
310
307
|
const _idCommitment = evt.args.idCommitment as string;
|
311
308
|
let index = evt.args.index;
|
312
309
|
|
313
|
-
// Ensure index is an ethers.BigNumber
|
314
310
|
if (!_idCommitment || !index) {
|
315
311
|
return;
|
316
312
|
}
|
317
313
|
|
318
|
-
// Convert index to ethers.BigNumber if it's not already
|
319
314
|
if (typeof index === "number" || typeof index === "string") {
|
320
315
|
index = ethers.BigNumber.from(index);
|
321
316
|
}
|
@@ -323,10 +318,9 @@ export class RLNContract {
|
|
323
318
|
const idCommitment = zeroPadLE(hexToBytes(_idCommitment), 32);
|
324
319
|
rlnInstance.zerokit.insertMember(idCommitment);
|
325
320
|
|
326
|
-
// Always store the numeric index as the key, but the BigNumber as the value
|
327
321
|
const numericIndex = index.toNumber();
|
328
322
|
this._members.set(numericIndex, {
|
329
|
-
index,
|
323
|
+
index,
|
330
324
|
idCommitment: _idCommitment
|
331
325
|
});
|
332
326
|
});
|
@@ -367,7 +361,7 @@ export class RLNContract {
|
|
367
361
|
);
|
368
362
|
|
369
363
|
this.contract.on(
|
370
|
-
this.
|
364
|
+
this.membershipErasedFilter,
|
371
365
|
(
|
372
366
|
_idCommitment: string,
|
373
367
|
_membershipRateLimit: ethers.BigNumber,
|
@@ -395,14 +389,6 @@ export class RLNContract {
|
|
395
389
|
identity: IdentityCredential
|
396
390
|
): Promise<DecryptedCredentials | undefined> {
|
397
391
|
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
|
-
|
406
392
|
log.info(
|
407
393
|
`Registering identity with rate limit: ${this.rateLimit} messages/epoch`
|
408
394
|
);
|
@@ -412,9 +398,6 @@ export class RLNContract {
|
|
412
398
|
identity.IDCommitmentBigInt.toString()
|
413
399
|
);
|
414
400
|
if (existingIndex) {
|
415
|
-
console.error(
|
416
|
-
`ID commitment is already registered with index ${existingIndex}`
|
417
|
-
);
|
418
401
|
throw new Error(
|
419
402
|
`ID commitment is already registered with index ${existingIndex}`
|
420
403
|
);
|
@@ -423,16 +406,11 @@ export class RLNContract {
|
|
423
406
|
// Check if there's enough remaining rate limit
|
424
407
|
const remainingRateLimit = await this.getRemainingTotalRateLimit();
|
425
408
|
if (remainingRateLimit < this.rateLimit) {
|
426
|
-
console.error(
|
427
|
-
`Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`
|
428
|
-
);
|
429
409
|
throw new Error(
|
430
410
|
`Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`
|
431
411
|
);
|
432
412
|
}
|
433
413
|
|
434
|
-
console.log("registerWithIdentity - calling contract.register");
|
435
|
-
// Estimate gas for the transaction
|
436
414
|
const estimatedGas = await this.contract.estimateGas.register(
|
437
415
|
identity.IDCommitmentBigInt,
|
438
416
|
this.rateLimit,
|
@@ -447,97 +425,40 @@ export class RLNContract {
|
|
447
425
|
[],
|
448
426
|
{ gasLimit }
|
449
427
|
);
|
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
428
|
|
459
429
|
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
430
|
|
477
|
-
// Check transaction status
|
478
431
|
if (txRegisterReceipt.status === 0) {
|
479
|
-
console.error("Transaction failed on-chain");
|
480
432
|
throw new Error("Transaction failed on-chain");
|
481
433
|
}
|
482
434
|
|
483
435
|
const memberRegistered = txRegisterReceipt.events?.find(
|
484
436
|
(event) => event.event === "MembershipRegistered"
|
485
437
|
);
|
486
|
-
console.log(
|
487
|
-
"registerWithIdentity - memberRegistered event:",
|
488
|
-
memberRegistered
|
489
|
-
);
|
490
438
|
|
491
439
|
if (!memberRegistered || !memberRegistered.args) {
|
492
|
-
|
493
|
-
"registerWithIdentity - ERROR: no memberRegistered event found"
|
494
|
-
);
|
495
|
-
console.log(
|
496
|
-
"registerWithIdentity - all events:",
|
497
|
-
txRegisterReceipt.events
|
498
|
-
);
|
499
|
-
console.error(
|
440
|
+
log.error(
|
500
441
|
"Failed to register membership: No MembershipRegistered event found"
|
501
442
|
);
|
502
443
|
return undefined;
|
503
444
|
}
|
504
445
|
|
505
|
-
console.log(
|
506
|
-
"registerWithIdentity - memberRegistered args:",
|
507
|
-
memberRegistered.args
|
508
|
-
);
|
509
446
|
const decodedData: MembershipRegisteredEvent = {
|
510
447
|
idCommitment: memberRegistered.args.idCommitment,
|
511
448
|
membershipRateLimit: memberRegistered.args.membershipRateLimit,
|
512
449
|
index: memberRegistered.args.index
|
513
450
|
};
|
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
|
-
);
|
523
451
|
|
524
452
|
log.info(
|
525
453
|
`Successfully registered membership with index ${decodedData.index} ` +
|
526
454
|
`and rate limit ${decodedData.membershipRateLimit}`
|
527
455
|
);
|
528
456
|
|
529
|
-
console.log("registerWithIdentity - getting network information");
|
530
457
|
const network = await this.contract.provider.getNetwork();
|
531
|
-
console.log("registerWithIdentity - network:", network);
|
532
|
-
console.log("registerWithIdentity - chainId:", network.chainId);
|
533
|
-
|
534
458
|
const address = this.contract.address;
|
535
|
-
|
536
|
-
|
537
|
-
const membershipId = decodedData.index.toNumber();
|
538
|
-
console.log("registerWithIdentity - membershipId:", membershipId);
|
459
|
+
const membershipId = Number(decodedData.index);
|
539
460
|
|
540
|
-
|
461
|
+
return {
|
541
462
|
identity,
|
542
463
|
membership: {
|
543
464
|
address,
|
@@ -545,41 +466,33 @@ export class RLNContract {
|
|
545
466
|
chainId: network.chainId
|
546
467
|
}
|
547
468
|
};
|
548
|
-
console.log("registerWithIdentity - returning result:", result);
|
549
|
-
|
550
|
-
return result;
|
551
469
|
} catch (error) {
|
552
|
-
console.log("registerWithIdentity - ERROR:", error);
|
553
|
-
|
554
|
-
// Improved error handling to decode contract errors
|
555
470
|
if (error instanceof Error) {
|
556
471
|
const errorMessage = error.message;
|
557
|
-
|
558
|
-
|
472
|
+
log.error("registerWithIdentity - error message:", errorMessage);
|
473
|
+
log.error("registerWithIdentity - error stack:", error.stack);
|
559
474
|
|
560
475
|
// Try to extract more specific error information
|
561
476
|
if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) {
|
562
|
-
|
477
|
+
throw new Error(
|
563
478
|
"Registration failed: Cannot exceed maximum total rate limit"
|
564
479
|
);
|
565
480
|
} else if (errorMessage.includes("InvalidIdCommitment")) {
|
566
|
-
|
481
|
+
throw new Error("Registration failed: Invalid ID commitment");
|
567
482
|
} else if (errorMessage.includes("InvalidMembershipRateLimit")) {
|
568
|
-
|
483
|
+
throw new Error("Registration failed: Invalid membership rate limit");
|
569
484
|
} else if (errorMessage.includes("execution reverted")) {
|
570
|
-
|
571
|
-
console.error(
|
485
|
+
throw new Error(
|
572
486
|
"Contract execution reverted. Check contract requirements."
|
573
487
|
);
|
574
488
|
} else {
|
575
|
-
|
489
|
+
throw new Error(`Error in registerWithIdentity: ${errorMessage}`);
|
576
490
|
}
|
577
491
|
} else {
|
578
|
-
|
492
|
+
throw new Error("Unknown error in registerWithIdentity", {
|
493
|
+
cause: error
|
494
|
+
});
|
579
495
|
}
|
580
|
-
|
581
|
-
// Re-throw the error to allow callers to handle it
|
582
|
-
throw error;
|
583
496
|
}
|
584
497
|
}
|
585
498
|
|
@@ -668,7 +581,7 @@ export class RLNContract {
|
|
668
581
|
|
669
582
|
const network = await this.contract.provider.getNetwork();
|
670
583
|
const address = this.contract.address;
|
671
|
-
const membershipId = decodedData.index
|
584
|
+
const membershipId = Number(decodedData.index);
|
672
585
|
|
673
586
|
return {
|
674
587
|
identity,
|
@@ -734,47 +647,33 @@ export class RLNContract {
|
|
734
647
|
|
735
648
|
public async extendMembership(
|
736
649
|
idCommitment: string
|
737
|
-
): Promise<ethers.
|
738
|
-
|
739
|
-
return await tx.wait();
|
650
|
+
): Promise<ethers.ContractTransaction> {
|
651
|
+
return this.contract.extendMemberships([idCommitment]);
|
740
652
|
}
|
741
653
|
|
742
654
|
public async eraseMembership(
|
743
655
|
idCommitment: string,
|
744
656
|
eraseFromMembershipSet: boolean = true
|
745
|
-
): Promise<ethers.
|
746
|
-
|
657
|
+
): Promise<ethers.ContractTransaction> {
|
658
|
+
return this.contract.eraseMemberships(
|
747
659
|
[idCommitment],
|
748
660
|
eraseFromMembershipSet
|
749
661
|
);
|
750
|
-
return await tx.wait();
|
751
662
|
}
|
752
663
|
|
753
664
|
public async registerMembership(
|
754
665
|
idCommitment: string,
|
755
666
|
rateLimit: number = DEFAULT_RATE_LIMIT
|
756
667
|
): Promise<ethers.ContractTransaction> {
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
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;
|
668
|
+
if (
|
669
|
+
rateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
|
670
|
+
rateLimit > RATE_LIMIT_PARAMS.MAX_RATE
|
671
|
+
) {
|
672
|
+
throw new Error(
|
673
|
+
`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`
|
674
|
+
);
|
777
675
|
}
|
676
|
+
return this.contract.register(idCommitment, rateLimit, []);
|
778
677
|
}
|
779
678
|
|
780
679
|
private async getMemberIndex(
|
@@ -793,87 +692,6 @@ export class RLNContract {
|
|
793
692
|
return undefined;
|
794
693
|
}
|
795
694
|
}
|
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
|
-
}
|
877
695
|
}
|
878
696
|
|
879
697
|
interface CustomQueryOptions extends FetchMembersOptions {
|
@@ -0,0 +1,108 @@
|
|
1
|
+
import { keccak256 } from "@ethersproject/keccak256";
|
2
|
+
import { toUtf8Bytes } from "@ethersproject/strings";
|
3
|
+
|
4
|
+
import { IdentityCredential } from "./identity.js";
|
5
|
+
import { buildBigIntFromUint8Array } from "./utils/index.js";
|
6
|
+
|
7
|
+
/**
|
8
|
+
* A standalone implementation of identity generation for RLN memberships
|
9
|
+
* without Zerokit dependency. Only supports identity creation and membership
|
10
|
+
* registration.
|
11
|
+
*/
|
12
|
+
export class IdentityGenerator {
|
13
|
+
/**
|
14
|
+
* Generate a new random identity credential
|
15
|
+
* @returns An IdentityCredential object
|
16
|
+
*/
|
17
|
+
public generateIdentityCredentials(): IdentityCredential {
|
18
|
+
// Generate random values for IDTrapdoor and IDNullifier
|
19
|
+
const idTrapdoor = crypto.getRandomValues(new Uint8Array(32));
|
20
|
+
const idNullifier = crypto.getRandomValues(new Uint8Array(32));
|
21
|
+
|
22
|
+
// Generate IDSecretHash by concatenating and hashing
|
23
|
+
const combined = new Uint8Array(64);
|
24
|
+
combined.set(idTrapdoor, 0);
|
25
|
+
combined.set(idNullifier, 32);
|
26
|
+
const idSecretHash = new Uint8Array(
|
27
|
+
keccak256(combined)
|
28
|
+
.substring(2)
|
29
|
+
.match(/.{1,2}/g)!
|
30
|
+
.map((byte) => parseInt(byte, 16))
|
31
|
+
);
|
32
|
+
|
33
|
+
// Generate IDCommitment by hashing IDSecretHash
|
34
|
+
const idCommitment = new Uint8Array(
|
35
|
+
keccak256(idSecretHash)
|
36
|
+
.substring(2)
|
37
|
+
.match(/.{1,2}/g)!
|
38
|
+
.map((byte) => parseInt(byte, 16))
|
39
|
+
);
|
40
|
+
|
41
|
+
// Generate BigInt from IDCommitment
|
42
|
+
const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment, 32);
|
43
|
+
|
44
|
+
return new IdentityCredential(
|
45
|
+
idTrapdoor,
|
46
|
+
idNullifier,
|
47
|
+
idSecretHash,
|
48
|
+
idCommitment,
|
49
|
+
idCommitmentBigInt
|
50
|
+
);
|
51
|
+
}
|
52
|
+
|
53
|
+
/**
|
54
|
+
* Generate an identity credential from a seed
|
55
|
+
* @param seed A string seed to generate a deterministic identity
|
56
|
+
* @returns An IdentityCredential object
|
57
|
+
*/
|
58
|
+
public generateSeededIdentityCredential(seed: string): IdentityCredential {
|
59
|
+
// Convert seed to bytes
|
60
|
+
const seedBytes = toUtf8Bytes(seed);
|
61
|
+
|
62
|
+
// Use the seed to derive IDTrapdoor and IDNullifier deterministically
|
63
|
+
const seedHash = keccak256(seedBytes);
|
64
|
+
const seedHashBytes = new Uint8Array(
|
65
|
+
seedHash
|
66
|
+
.substring(2)
|
67
|
+
.match(/.{1,2}/g)!
|
68
|
+
.map((byte) => parseInt(byte, 16))
|
69
|
+
);
|
70
|
+
|
71
|
+
// Use first half for IDTrapdoor, second half for IDNullifier
|
72
|
+
const idTrapdoor = seedHashBytes.slice(0, 32);
|
73
|
+
const idNullifier = keccak256(seedHashBytes).substring(2);
|
74
|
+
const idNullifierBytes = new Uint8Array(
|
75
|
+
idNullifier.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16))
|
76
|
+
).slice(0, 32);
|
77
|
+
|
78
|
+
// Generate IDSecretHash by concatenating and hashing
|
79
|
+
const combined = new Uint8Array(64);
|
80
|
+
combined.set(idTrapdoor, 0);
|
81
|
+
combined.set(idNullifierBytes, 32);
|
82
|
+
const idSecretHash = new Uint8Array(
|
83
|
+
keccak256(combined)
|
84
|
+
.substring(2)
|
85
|
+
.match(/.{1,2}/g)!
|
86
|
+
.map((byte) => parseInt(byte, 16))
|
87
|
+
);
|
88
|
+
|
89
|
+
// Generate IDCommitment by hashing IDSecretHash
|
90
|
+
const idCommitment = new Uint8Array(
|
91
|
+
keccak256(idSecretHash)
|
92
|
+
.substring(2)
|
93
|
+
.match(/.{1,2}/g)!
|
94
|
+
.map((byte) => parseInt(byte, 16))
|
95
|
+
);
|
96
|
+
|
97
|
+
// Generate BigInt from IDCommitment
|
98
|
+
const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment, 32);
|
99
|
+
|
100
|
+
return new IdentityCredential(
|
101
|
+
idTrapdoor,
|
102
|
+
idNullifierBytes,
|
103
|
+
idSecretHash,
|
104
|
+
idCommitment,
|
105
|
+
idCommitmentBigInt
|
106
|
+
);
|
107
|
+
}
|
108
|
+
}
|
package/src/index.ts
CHANGED
@@ -3,9 +3,11 @@ import { RLN_ABI } from "./contract/abi.js";
|
|
3
3
|
import { RLNContract, SEPOLIA_CONTRACT } from "./contract/index.js";
|
4
4
|
import { createRLN } from "./create.js";
|
5
5
|
import { IdentityCredential } from "./identity.js";
|
6
|
+
import { IdentityGenerator } from "./identity_generator.js";
|
6
7
|
import { Keystore } from "./keystore/index.js";
|
7
8
|
import { Proof } from "./proof.js";
|
8
9
|
import { RLNInstance } from "./rln.js";
|
10
|
+
import { RLNLight } from "./rln_light.js";
|
9
11
|
import { MerkleRootTracker } from "./root_tracker.js";
|
10
12
|
import { extractMetaMaskSigner } from "./utils/index.js";
|
11
13
|
|
@@ -13,6 +15,8 @@ export {
|
|
13
15
|
createRLN,
|
14
16
|
Keystore,
|
15
17
|
RLNInstance,
|
18
|
+
RLNLight,
|
19
|
+
IdentityGenerator,
|
16
20
|
IdentityCredential,
|
17
21
|
Proof,
|
18
22
|
RLNEncoder,
|
@@ -23,3 +27,14 @@ export {
|
|
23
27
|
extractMetaMaskSigner,
|
24
28
|
RLN_ABI
|
25
29
|
};
|
30
|
+
|
31
|
+
export type {
|
32
|
+
DecryptedCredentials,
|
33
|
+
EncryptedCredentials,
|
34
|
+
Keccak256Hash,
|
35
|
+
KeystoreEntity,
|
36
|
+
MembershipHash,
|
37
|
+
MembershipInfo,
|
38
|
+
Password,
|
39
|
+
Sha256Hash
|
40
|
+
} from "./keystore/types.js";
|
package/src/rln.ts
CHANGED