@waku/rln 0.0.2-09108d9.0 → 0.0.2-2eccb11.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.
Files changed (47) hide show
  1. package/bundle/_virtual/utils.js +2 -2
  2. package/bundle/_virtual/utils2.js +2 -2
  3. package/bundle/index.js +2 -1
  4. package/bundle/packages/rln/dist/contract/abi.js +648 -0
  5. package/bundle/packages/rln/dist/contract/constants.js +25 -65
  6. package/bundle/packages/rln/dist/contract/rln_contract.js +335 -74
  7. package/bundle/packages/rln/dist/message.js +1 -1
  8. package/bundle/packages/rln/dist/rln.js +42 -20
  9. package/bundle/packages/rln/dist/zerokit.js +34 -14
  10. package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +1 -1
  11. package/bundle/packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +2 -2
  12. package/bundle/packages/rln/node_modules/@noble/hashes/_sha2.js +1 -1
  13. package/bundle/packages/rln/node_modules/@noble/hashes/hmac.js +1 -1
  14. package/bundle/packages/rln/node_modules/@noble/hashes/pbkdf2.js +1 -1
  15. package/bundle/packages/rln/node_modules/@noble/hashes/scrypt.js +1 -1
  16. package/bundle/packages/rln/node_modules/@noble/hashes/sha256.js +1 -1
  17. package/bundle/packages/rln/node_modules/@noble/hashes/sha512.js +1 -1
  18. package/bundle/packages/rln/node_modules/@noble/hashes/utils.js +1 -1
  19. package/dist/.tsbuildinfo +1 -1
  20. package/dist/contract/abi.d.ts +46 -0
  21. package/dist/contract/abi.js +647 -0
  22. package/dist/contract/abi.js.map +1 -0
  23. package/dist/contract/constants.d.ts +63 -3
  24. package/dist/contract/constants.js +23 -64
  25. package/dist/contract/constants.js.map +1 -1
  26. package/dist/contract/rln_contract.d.ts +100 -17
  27. package/dist/contract/rln_contract.js +334 -72
  28. package/dist/contract/rln_contract.js.map +1 -1
  29. package/dist/index.d.ts +3 -3
  30. package/dist/index.js +3 -3
  31. package/dist/index.js.map +1 -1
  32. package/dist/message.js +1 -1
  33. package/dist/message.js.map +1 -1
  34. package/dist/rln.d.ts +5 -1
  35. package/dist/rln.js +42 -19
  36. package/dist/rln.js.map +1 -1
  37. package/dist/zerokit.d.ts +10 -6
  38. package/dist/zerokit.js +34 -14
  39. package/dist/zerokit.js.map +1 -1
  40. package/package.json +1 -1
  41. package/src/contract/abi.ts +646 -0
  42. package/src/contract/constants.ts +26 -65
  43. package/src/contract/rln_contract.ts +500 -108
  44. package/src/index.ts +4 -9
  45. package/src/message.ts +1 -1
  46. package/src/rln.ts +63 -21
  47. package/src/zerokit.ts +74 -15
package/src/index.ts CHANGED
@@ -1,10 +1,6 @@
1
1
  import { RLNDecoder, RLNEncoder } from "./codec.js";
2
- import {
3
- RLN_REGISTRY_ABI,
4
- RLN_STORAGE_ABI,
5
- SEPOLIA_CONTRACT
6
- } from "./contract/index.js";
7
- import { RLNContract } from "./contract/index.js";
2
+ import { RLN_ABI } from "./contract/abi.js";
3
+ import { RLNContract, SEPOLIA_CONTRACT } from "./contract/index.js";
8
4
  import { createRLN } from "./create.js";
9
5
  import { IdentityCredential } from "./identity.js";
10
6
  import { Keystore } from "./keystore/index.js";
@@ -23,8 +19,7 @@ export {
23
19
  RLNDecoder,
24
20
  MerkleRootTracker,
25
21
  RLNContract,
26
- RLN_STORAGE_ABI,
27
- RLN_REGISTRY_ABI,
28
22
  SEPOLIA_CONTRACT,
29
- extractMetaMaskSigner
23
+ extractMetaMaskSigner,
24
+ RLN_ABI
30
25
  };
package/src/message.ts CHANGED
@@ -27,7 +27,7 @@ export class RlnMessage<T extends IDecodedMessage> implements IDecodedMessage {
27
27
  ? this.rlnInstance.zerokit.verifyWithRoots(
28
28
  this.rateLimitProof,
29
29
  toRLNSignal(this.msg.contentTopic, this.msg),
30
- ...roots
30
+ roots
31
31
  ) // this.rlnInstance.verifyRLNProof once issue status-im/nwaku#1248 is fixed
32
32
  : undefined;
33
33
  }
package/src/rln.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  type RLNDecoder,
16
16
  type RLNEncoder
17
17
  } from "./codec.js";
18
+ import { DEFAULT_RATE_LIMIT } from "./contract/constants.js";
18
19
  import { RLNContract, SEPOLIA_CONTRACT } from "./contract/index.js";
19
20
  import { IdentityCredential } from "./identity.js";
20
21
  import { Keystore } from "./keystore/index.js";
@@ -25,26 +26,53 @@ import type {
25
26
  import { KeystoreEntity, Password } from "./keystore/types.js";
26
27
  import verificationKey from "./resources/verification_key";
27
28
  import * as wc from "./resources/witness_calculator";
29
+ import { WitnessCalculator } from "./resources/witness_calculator";
28
30
  import { extractMetaMaskSigner } from "./utils/index.js";
29
31
  import { Zerokit } from "./zerokit.js";
30
32
 
31
33
  const log = new Logger("waku:rln");
32
34
 
33
- async function loadWitnessCalculator(): Promise<wc.WitnessCalculator> {
34
- const res = await fetch("/base/rln.wasm");
35
- if (!res.ok) {
36
- throw new Error(`Failed to fetch rln.wasm: ${res.statusText}`);
35
+ async function loadWitnessCalculator(): Promise<WitnessCalculator> {
36
+ try {
37
+ const url = new URL("./resources/rln.wasm", import.meta.url);
38
+ const response = await fetch(url);
39
+
40
+ if (!response.ok) {
41
+ throw new Error(
42
+ `Failed to fetch witness calculator: ${response.status} ${response.statusText}`
43
+ );
44
+ }
45
+
46
+ return await wc.builder(
47
+ new Uint8Array(await response.arrayBuffer()),
48
+ false
49
+ );
50
+ } catch (error) {
51
+ log.error("Error loading witness calculator:", error);
52
+ throw new Error(
53
+ `Failed to load witness calculator: ${error instanceof Error ? error.message : String(error)}`
54
+ );
37
55
  }
38
- const witnessBuffer = await res.arrayBuffer();
39
- return wc.builder(new Uint8Array(witnessBuffer), false);
40
56
  }
41
57
 
42
58
  async function loadZkey(): Promise<Uint8Array> {
43
- const res = await fetch("/base/rln_final.zkey");
44
- if (!res.ok) {
45
- throw new Error(`Failed to fetch rln_final.zkey: ${res.statusText}`);
59
+ try {
60
+ const url = new URL("./resources/rln_final.zkey", import.meta.url);
61
+ const response = await fetch(url);
62
+
63
+ if (!response.ok) {
64
+ throw new Error(
65
+ `Failed to fetch zkey: ${response.status} ${response.statusText}`
66
+ );
67
+ }
68
+
69
+ return new Uint8Array(await response.arrayBuffer());
70
+ } catch (error) {
71
+ log.error("Error loading zkey:", error);
72
+ throw new Error(
73
+ `Failed to load zkey: ${error instanceof Error ? error.message : String(error)}`
74
+ );
46
75
  }
47
- return new Uint8Array(await res.arrayBuffer());
48
76
  }
49
77
 
50
78
  /**
@@ -65,7 +93,7 @@ export async function create(): Promise<RLNInstance> {
65
93
 
66
94
  const DEPTH = 20;
67
95
  const zkRLN = zerokitRLN.newRLN(DEPTH, zkey, vkey);
68
- const zerokit = new Zerokit(zkRLN, witnessCalculator);
96
+ const zerokit = new Zerokit(zkRLN, witnessCalculator, DEFAULT_RATE_LIMIT);
69
97
 
70
98
  return new RLNInstance(zerokit);
71
99
  } catch (error) {
@@ -82,12 +110,16 @@ type StartRLNOptions = {
82
110
  /**
83
111
  * If not set - will use default SEPOLIA_CONTRACT address.
84
112
  */
85
- registryAddress?: string;
113
+ address?: string;
86
114
  /**
87
115
  * Credentials to use for generating proofs and connecting to the contract and network.
88
116
  * If provided used for validating the network chainId and connecting to registry contract.
89
117
  */
90
118
  credentials?: EncryptedCredentials | DecryptedCredentials;
119
+ /**
120
+ * Rate limit for the member.
121
+ */
122
+ rateLimit?: number;
91
123
  };
92
124
 
93
125
  type RegisterMembershipOptions =
@@ -119,6 +151,8 @@ export class RLNInstance {
119
151
  }
120
152
 
121
153
  public async start(options: StartRLNOptions = {}): Promise<void> {
154
+ // eslint-disable-next-line no-console
155
+ console.log("starting", options);
122
156
  if (this.started || this.starting) {
123
157
  return;
124
158
  }
@@ -128,7 +162,7 @@ export class RLNInstance {
128
162
  try {
129
163
  const { credentials, keystore } =
130
164
  await RLNInstance.decryptCredentialsIfNeeded(options.credentials);
131
- const { signer, registryAddress } = await this.determineStartOptions(
165
+ const { signer, address } = await this.determineStartOptions(
132
166
  options,
133
167
  credentials
134
168
  );
@@ -140,8 +174,9 @@ export class RLNInstance {
140
174
  this._credentials = credentials;
141
175
  this._signer = signer!;
142
176
  this._contract = await RLNContract.init(this, {
143
- registryAddress: registryAddress!,
144
- signer: signer!
177
+ address: address!,
178
+ signer: signer!,
179
+ rateLimit: options.rateLimit ?? this.zerokit.getRateLimit
145
180
  });
146
181
  this.started = true;
147
182
  } finally {
@@ -154,15 +189,22 @@ export class RLNInstance {
154
189
  credentials: KeystoreEntity | undefined
155
190
  ): Promise<StartRLNOptions> {
156
191
  let chainId = credentials?.membership.chainId;
157
- const registryAddress =
192
+ const address =
158
193
  credentials?.membership.address ||
159
- options.registryAddress ||
194
+ options.address ||
160
195
  SEPOLIA_CONTRACT.address;
161
196
 
162
- if (registryAddress === SEPOLIA_CONTRACT.address) {
197
+ if (address === SEPOLIA_CONTRACT.address) {
163
198
  chainId = SEPOLIA_CONTRACT.chainId;
164
199
  }
165
200
 
201
+ // eslint-disable-next-line no-console
202
+ console.log({
203
+ chainId,
204
+ address,
205
+ SEPOLIA_CONTRACT
206
+ });
207
+
166
208
  const signer = options.signer || (await extractMetaMaskSigner());
167
209
  const currentChainId = await signer.getChainId();
168
210
 
@@ -174,7 +216,7 @@ export class RLNInstance {
174
216
 
175
217
  return {
176
218
  signer,
177
- registryAddress
219
+ address
178
220
  };
179
221
  }
180
222
 
@@ -270,7 +312,7 @@ export class RLNInstance {
270
312
  }
271
313
 
272
314
  const registryAddress = credentials.membership.address;
273
- const currentRegistryAddress = this._contract.registry.address;
315
+ const currentRegistryAddress = this._contract.address;
274
316
  if (registryAddress !== currentRegistryAddress) {
275
317
  throw Error(
276
318
  `Failed to verify chain coordinates: credentials contract address=${registryAddress} is not equal to registryContract address=${currentRegistryAddress}`
@@ -278,7 +320,7 @@ export class RLNInstance {
278
320
  }
279
321
 
280
322
  const chainId = credentials.membership.chainId;
281
- const network = await this._contract.registry.provider.getNetwork();
323
+ const network = await this._contract.provider.getNetwork();
282
324
  const currentChainId = network.chainId;
283
325
  if (chainId !== currentChainId) {
284
326
  throw Error(
package/src/zerokit.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { IRateLimitProof } from "@waku/interfaces";
2
2
  import * as zerokitRLN from "@waku/zerokit-rln-wasm";
3
3
 
4
+ import { DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS } from "./contract/constants.js";
4
5
  import { IdentityCredential } from "./identity.js";
5
6
  import { Proof, proofToBytes } from "./proof.js";
6
7
  import { WitnessCalculator } from "./resources/witness_calculator";
@@ -14,9 +15,22 @@ import {
14
15
  export class Zerokit {
15
16
  public constructor(
16
17
  private readonly zkRLN: number,
17
- private readonly witnessCalculator: WitnessCalculator
18
+ private readonly witnessCalculator: WitnessCalculator,
19
+ private readonly rateLimit: number = DEFAULT_RATE_LIMIT
18
20
  ) {}
19
21
 
22
+ public get getZkRLN(): number {
23
+ return this.zkRLN;
24
+ }
25
+
26
+ public get getWitnessCalculator(): WitnessCalculator {
27
+ return this.witnessCalculator;
28
+ }
29
+
30
+ public get getRateLimit(): number {
31
+ return this.rateLimit;
32
+ }
33
+
20
34
  public generateIdentityCredentials(): IdentityCredential {
21
35
  const memKeys = zerokitRLN.generateExtendedMembershipKey(this.zkRLN); // TODO: rename this function in zerokit rln-wasm
22
36
  return IdentityCredential.fromBytes(memKeys);
@@ -65,23 +79,36 @@ export class Zerokit {
65
79
  uint8Msg: Uint8Array,
66
80
  memIndex: number,
67
81
  epoch: Uint8Array,
68
- idKey: Uint8Array
82
+ idKey: Uint8Array,
83
+ rateLimit?: number
69
84
  ): Uint8Array {
70
85
  // calculate message length
71
86
  const msgLen = writeUIntLE(new Uint8Array(8), uint8Msg.length, 0, 8);
72
-
73
- // Converting index to LE bytes
74
87
  const memIndexBytes = writeUIntLE(new Uint8Array(8), memIndex, 0, 8);
88
+ const rateLimitBytes = writeUIntLE(
89
+ new Uint8Array(8),
90
+ rateLimit ?? this.rateLimit,
91
+ 0,
92
+ 8
93
+ );
75
94
 
76
- // [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]
77
- return concatenate(idKey, memIndexBytes, epoch, msgLen, uint8Msg);
95
+ // [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> | rate_limit<8> ]
96
+ return concatenate(
97
+ idKey,
98
+ memIndexBytes,
99
+ epoch,
100
+ msgLen,
101
+ uint8Msg,
102
+ rateLimitBytes
103
+ );
78
104
  }
79
105
 
80
106
  public async generateRLNProof(
81
107
  msg: Uint8Array,
82
108
  index: number,
83
109
  epoch: Uint8Array | Date | undefined,
84
- idSecretHash: Uint8Array
110
+ idSecretHash: Uint8Array,
111
+ rateLimit?: number
85
112
  ): Promise<IRateLimitProof> {
86
113
  if (epoch === undefined) {
87
114
  epoch = epochIntToBytes(dateToEpoch(new Date()));
@@ -89,15 +116,26 @@ export class Zerokit {
89
116
  epoch = epochIntToBytes(dateToEpoch(epoch));
90
117
  }
91
118
 
119
+ const effectiveRateLimit = rateLimit ?? this.rateLimit;
120
+
92
121
  if (epoch.length !== 32) throw new Error("invalid epoch");
93
122
  if (idSecretHash.length !== 32) throw new Error("invalid id secret hash");
94
123
  if (index < 0) throw new Error("index must be >= 0");
124
+ if (
125
+ effectiveRateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
126
+ effectiveRateLimit > RATE_LIMIT_PARAMS.MAX_RATE
127
+ ) {
128
+ throw new Error(
129
+ `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`
130
+ );
131
+ }
95
132
 
96
133
  const serialized_msg = this.serializeMessage(
97
134
  msg,
98
135
  index,
99
136
  epoch,
100
- idSecretHash
137
+ idSecretHash,
138
+ effectiveRateLimit
101
139
  );
102
140
  const rlnWitness = zerokitRLN.getSerializedRLNWitness(
103
141
  this.zkRLN,
@@ -107,7 +145,7 @@ export class Zerokit {
107
145
  const calculatedWitness = await this.witnessCalculator.calculateWitness(
108
146
  inputs,
109
147
  false
110
- ); // no sanity check being used in zerokit
148
+ );
111
149
 
112
150
  const proofBytes = zerokitRLN.generate_rln_proof_with_witness(
113
151
  this.zkRLN,
@@ -120,7 +158,8 @@ export class Zerokit {
120
158
 
121
159
  public verifyRLNProof(
122
160
  proof: IRateLimitProof | Uint8Array,
123
- msg: Uint8Array
161
+ msg: Uint8Array,
162
+ rateLimit?: number
124
163
  ): boolean {
125
164
  let pBytes: Uint8Array;
126
165
  if (proof instanceof Uint8Array) {
@@ -131,17 +170,24 @@ export class Zerokit {
131
170
 
132
171
  // calculate message length
133
172
  const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
173
+ const rateLimitBytes = writeUIntLE(
174
+ new Uint8Array(8),
175
+ rateLimit ?? this.rateLimit,
176
+ 0,
177
+ 8
178
+ );
134
179
 
135
180
  return zerokitRLN.verifyRLNProof(
136
181
  this.zkRLN,
137
- concatenate(pBytes, msgLen, msg)
182
+ concatenate(pBytes, msgLen, msg, rateLimitBytes)
138
183
  );
139
184
  }
140
185
 
141
186
  public verifyWithRoots(
142
187
  proof: IRateLimitProof | Uint8Array,
143
188
  msg: Uint8Array,
144
- ...roots: Array<Uint8Array>
189
+ roots: Array<Uint8Array>,
190
+ rateLimit?: number
145
191
  ): boolean {
146
192
  let pBytes: Uint8Array;
147
193
  if (proof instanceof Uint8Array) {
@@ -151,19 +197,26 @@ export class Zerokit {
151
197
  }
152
198
  // calculate message length
153
199
  const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
200
+ const rateLimitBytes = writeUIntLE(
201
+ new Uint8Array(8),
202
+ rateLimit ?? this.rateLimit,
203
+ 0,
204
+ 8
205
+ );
154
206
 
155
207
  const rootsBytes = concatenate(...roots);
156
208
 
157
209
  return zerokitRLN.verifyWithRoots(
158
210
  this.zkRLN,
159
- concatenate(pBytes, msgLen, msg),
211
+ concatenate(pBytes, msgLen, msg, rateLimitBytes),
160
212
  rootsBytes
161
213
  );
162
214
  }
163
215
 
164
216
  public verifyWithNoRoot(
165
217
  proof: IRateLimitProof | Uint8Array,
166
- msg: Uint8Array
218
+ msg: Uint8Array,
219
+ rateLimit?: number
167
220
  ): boolean {
168
221
  let pBytes: Uint8Array;
169
222
  if (proof instanceof Uint8Array) {
@@ -174,10 +227,16 @@ export class Zerokit {
174
227
 
175
228
  // calculate message length
176
229
  const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
230
+ const rateLimitBytes = writeUIntLE(
231
+ new Uint8Array(8),
232
+ rateLimit ?? this.rateLimit,
233
+ 0,
234
+ 8
235
+ );
177
236
 
178
237
  return zerokitRLN.verifyWithRoots(
179
238
  this.zkRLN,
180
- concatenate(pBytes, msgLen, msg),
239
+ concatenate(pBytes, msgLen, msg, rateLimitBytes),
181
240
  new Uint8Array()
182
241
  );
183
242
  }