@waku/rln 0.1.1 → 0.1.2-6454446

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 (106) hide show
  1. package/README.md +26 -2
  2. package/bundle/assets/rln_wasm_bg-a503e304.wasm +0 -0
  3. package/bundle/index.js +58406 -10987
  4. package/dist/codec.d.ts +7 -4
  5. package/dist/codec.js +15 -5
  6. package/dist/codec.js.map +1 -1
  7. package/dist/{constants.d.ts → contract/constants.d.ts} +2 -2
  8. package/dist/contract/constants.js +67 -0
  9. package/dist/contract/constants.js.map +1 -0
  10. package/dist/contract/index.d.ts +2 -0
  11. package/dist/contract/index.js +3 -0
  12. package/dist/contract/index.js.map +1 -0
  13. package/dist/contract/rln_contract.d.ts +46 -0
  14. package/dist/contract/rln_contract.js +213 -0
  15. package/dist/contract/rln_contract.js.map +1 -0
  16. package/dist/create.d.ts +2 -0
  17. package/dist/create.js +8 -0
  18. package/dist/create.js.map +1 -0
  19. package/dist/identity.d.ts +9 -0
  20. package/dist/identity.js +24 -0
  21. package/dist/identity.js.map +1 -0
  22. package/dist/index.d.ts +9 -5
  23. package/dist/index.js +9 -12
  24. package/dist/index.js.map +1 -1
  25. package/dist/keystore/cipher.d.ts +4 -0
  26. package/dist/keystore/cipher.js +28 -0
  27. package/dist/keystore/cipher.js.map +1 -0
  28. package/dist/keystore/credential_validation_generated.d.ts +8 -0
  29. package/dist/keystore/credential_validation_generated.js +121 -0
  30. package/dist/keystore/credential_validation_generated.js.map +1 -0
  31. package/dist/keystore/index.d.ts +4 -0
  32. package/dist/keystore/index.js +3 -0
  33. package/dist/keystore/index.js.map +1 -0
  34. package/dist/keystore/keystore.d.ts +50 -0
  35. package/dist/keystore/keystore.js +205 -0
  36. package/dist/keystore/keystore.js.map +1 -0
  37. package/dist/keystore/keystore_validation_generated.d.ts +8 -0
  38. package/dist/keystore/keystore_validation_generated.js +75 -0
  39. package/dist/keystore/keystore_validation_generated.js.map +1 -0
  40. package/dist/keystore/schema_validator.d.ts +2 -0
  41. package/dist/keystore/schema_validator.js +18 -0
  42. package/dist/keystore/schema_validator.js.map +1 -0
  43. package/dist/keystore/types.d.ts +29 -0
  44. package/dist/keystore/types.js +2 -0
  45. package/dist/keystore/types.js.map +1 -0
  46. package/dist/message.d.ts +2 -1
  47. package/dist/message.js +10 -4
  48. package/dist/message.js.map +1 -1
  49. package/dist/proof.d.ts +21 -0
  50. package/dist/proof.js +49 -0
  51. package/dist/proof.js.map +1 -0
  52. package/dist/resources/verification_key.d.ts +9 -9
  53. package/dist/resources/witness_calculator.js.map +1 -0
  54. package/dist/rln.d.ts +55 -46
  55. package/dist/rln.js +136 -183
  56. package/dist/rln.js.map +1 -1
  57. package/dist/root_tracker.js +5 -2
  58. package/dist/root_tracker.js.map +1 -1
  59. package/dist/utils/bytes.d.ts +20 -0
  60. package/dist/utils/bytes.js +64 -0
  61. package/dist/utils/bytes.js.map +1 -0
  62. package/dist/utils/epoch.js.map +1 -0
  63. package/dist/utils/hash.d.ts +2 -0
  64. package/dist/utils/hash.js +13 -0
  65. package/dist/utils/hash.js.map +1 -0
  66. package/dist/utils/index.d.ts +4 -0
  67. package/dist/utils/index.js +5 -0
  68. package/dist/utils/index.js.map +1 -0
  69. package/dist/utils/metamask.d.ts +2 -0
  70. package/dist/utils/metamask.js +12 -0
  71. package/dist/utils/metamask.js.map +1 -0
  72. package/dist/zerokit.d.ts +19 -0
  73. package/dist/zerokit.js +105 -0
  74. package/dist/zerokit.js.map +1 -0
  75. package/package.json +38 -28
  76. package/src/codec.ts +18 -9
  77. package/src/create.ts +9 -0
  78. package/src/identity.ts +27 -0
  79. package/src/index.ts +16 -18
  80. package/src/message.ts +9 -5
  81. package/src/proof.ts +67 -0
  82. package/src/rln.ts +220 -270
  83. package/src/root_tracker.ts +4 -1
  84. package/src/zerokit.ts +181 -0
  85. package/bundle/assets/rln_wasm_bg-6f96f821.wasm +0 -0
  86. package/dist/.tsbuildinfo +0 -1
  87. package/dist/byte_utils.d.ts +0 -1
  88. package/dist/byte_utils.js +0 -24
  89. package/dist/byte_utils.js.map +0 -1
  90. package/dist/constants.js +0 -14
  91. package/dist/constants.js.map +0 -1
  92. package/dist/epoch.js.map +0 -1
  93. package/dist/rln_contract.d.ts +0 -34
  94. package/dist/rln_contract.js +0 -159
  95. package/dist/rln_contract.js.map +0 -1
  96. package/dist/witness_calculator.js.map +0 -1
  97. package/src/byte_utils.ts +0 -39
  98. package/src/constants.ts +0 -14
  99. package/src/epoch.ts +0 -30
  100. package/src/rln_contract.ts +0 -268
  101. package/src/witness_calculator.d.ts +0 -8
  102. package/src/witness_calculator.js +0 -335
  103. /package/dist/{witness_calculator.d.ts → resources/witness_calculator.d.ts} +0 -0
  104. /package/dist/{witness_calculator.js → resources/witness_calculator.js} +0 -0
  105. /package/dist/{epoch.d.ts → utils/epoch.d.ts} +0 -0
  106. /package/dist/{epoch.js → utils/epoch.js} +0 -0
package/src/rln.ts CHANGED
@@ -1,44 +1,32 @@
1
- import type { IRateLimitProof } from "@waku/interfaces";
2
- import init, * as zerokitRLN from "@waku/zerokit-rln-wasm";
3
-
4
- import { writeUIntLE } from "./byte_utils.js";
5
- import { dateToEpoch, epochIntToBytes } from "./epoch.js";
1
+ import { createDecoder, createEncoder } from "@waku/core";
2
+ import type {
3
+ ContentTopic,
4
+ IDecodedMessage,
5
+ EncoderOptions as WakuEncoderOptions
6
+ } from "@waku/interfaces";
7
+ import init from "@waku/zerokit-rln-wasm";
8
+ import * as zerokitRLN from "@waku/zerokit-rln-wasm";
9
+ import { ethers } from "ethers";
10
+
11
+ import {
12
+ createRLNDecoder,
13
+ createRLNEncoder,
14
+ type RLNDecoder,
15
+ type RLNEncoder
16
+ } from "./codec.js";
17
+ import { RLNContract, SEPOLIA_CONTRACT } from "./contract/index.js";
18
+ import { IdentityCredential } from "./identity.js";
19
+ import { Keystore } from "./keystore/index.js";
20
+ import type {
21
+ DecryptedCredentials,
22
+ EncryptedCredentials
23
+ } from "./keystore/index.js";
24
+ import { KeystoreEntity, Password } from "./keystore/types.js";
6
25
  import verificationKey from "./resources/verification_key.js";
7
- import * as wc from "./witness_calculator.js";
8
- import { WitnessCalculator } from "./witness_calculator.js";
9
-
10
- /**
11
- * Concatenate Uint8Arrays
12
- * @param input
13
- * @returns concatenation of all Uint8Array received as input
14
- */
15
- function concatenate(...input: Uint8Array[]): Uint8Array {
16
- let totalLength = 0;
17
- for (const arr of input) {
18
- totalLength += arr.length;
19
- }
20
- const result = new Uint8Array(totalLength);
21
- let offset = 0;
22
- for (const arr of input) {
23
- result.set(arr, offset);
24
- offset += arr.length;
25
- }
26
- return result;
27
- }
28
-
29
- /**
30
- * Transforms Uint8Array into BigInt
31
- * @param array: Uint8Array
32
- * @returns BigInt
33
- */
34
- function buildBigIntFromUint8Array(array: Uint8Array): bigint {
35
- const dataView = new DataView(array.buffer);
36
- return dataView.getBigUint64(0, true);
37
- }
38
-
39
- const stringEncoder = new TextEncoder();
40
-
41
- const DEPTH = 20;
26
+ import * as wc from "./resources/witness_calculator.js";
27
+ import { WitnessCalculator } from "./resources/witness_calculator.js";
28
+ import { extractMetaMaskSigner } from "./utils/index.js";
29
+ import { Zerokit } from "./zerokit.js";
42
30
 
43
31
  async function loadWitnessCalculator(): Promise<WitnessCalculator> {
44
32
  const url = new URL("./resources/rln.wasm", import.meta.url);
@@ -57,280 +45,242 @@ async function loadZkey(): Promise<Uint8Array> {
57
45
  * @returns RLNInstance
58
46
  */
59
47
  export async function create(): Promise<RLNInstance> {
60
- await init();
48
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
49
+ await (init as any)?.();
61
50
  zerokitRLN.init_panic_hook();
51
+
62
52
  const witnessCalculator = await loadWitnessCalculator();
63
53
  const zkey = await loadZkey();
54
+
55
+ const stringEncoder = new TextEncoder();
64
56
  const vkey = stringEncoder.encode(JSON.stringify(verificationKey));
57
+
58
+ const DEPTH = 20;
65
59
  const zkRLN = zerokitRLN.newRLN(DEPTH, zkey, vkey);
66
- return new RLNInstance(zkRLN, witnessCalculator);
67
- }
60
+ const zerokit = new Zerokit(zkRLN, witnessCalculator);
68
61
 
69
- export class IdentityCredential {
70
- constructor(
71
- public readonly IDTrapdoor: Uint8Array,
72
- public readonly IDNullifier: Uint8Array,
73
- public readonly IDSecretHash: Uint8Array,
74
- public readonly IDCommitment: Uint8Array,
75
- public readonly IDCommitmentBigInt: bigint
76
- ) {}
77
-
78
- static fromBytes(memKeys: Uint8Array): IdentityCredential {
79
- const idTrapdoor = memKeys.subarray(0, 32);
80
- const idNullifier = memKeys.subarray(32, 64);
81
- const idSecretHash = memKeys.subarray(64, 96);
82
- const idCommitment = memKeys.subarray(96);
83
- const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment);
84
-
85
- return new IdentityCredential(
86
- idTrapdoor,
87
- idNullifier,
88
- idSecretHash,
89
- idCommitment,
90
- idCommitmentBigInt
91
- );
92
- }
62
+ return new RLNInstance(zerokit);
93
63
  }
94
64
 
95
- const proofOffset = 128;
96
- const rootOffset = proofOffset + 32;
97
- const epochOffset = rootOffset + 32;
98
- const shareXOffset = epochOffset + 32;
99
- const shareYOffset = shareXOffset + 32;
100
- const nullifierOffset = shareYOffset + 32;
101
- const rlnIdentifierOffset = nullifierOffset + 32;
102
-
103
- export class ProofMetadata {
104
- constructor(
105
- public readonly nullifier: Uint8Array,
106
- public readonly shareX: Uint8Array,
107
- public readonly shareY: Uint8Array,
108
- public readonly externalNullifier: Uint8Array
109
- ) {}
110
- }
111
- export class Proof implements IRateLimitProof {
112
- readonly proof: Uint8Array;
113
- readonly merkleRoot: Uint8Array;
114
- readonly epoch: Uint8Array;
115
- readonly shareX: Uint8Array;
116
- readonly shareY: Uint8Array;
117
- readonly nullifier: Uint8Array;
118
- readonly rlnIdentifier: Uint8Array;
119
-
120
- constructor(proofBytes: Uint8Array) {
121
- if (proofBytes.length < rlnIdentifierOffset) throw "invalid proof";
122
- // parse the proof as proof<128> | share_y<32> | nullifier<32> | root<32> | epoch<32> | share_x<32> | rln_identifier<32>
123
- this.proof = proofBytes.subarray(0, proofOffset);
124
- this.merkleRoot = proofBytes.subarray(proofOffset, rootOffset);
125
- this.epoch = proofBytes.subarray(rootOffset, epochOffset);
126
- this.shareX = proofBytes.subarray(epochOffset, shareXOffset);
127
- this.shareY = proofBytes.subarray(shareXOffset, shareYOffset);
128
- this.nullifier = proofBytes.subarray(shareYOffset, nullifierOffset);
129
- this.rlnIdentifier = proofBytes.subarray(
130
- nullifierOffset,
131
- rlnIdentifierOffset
132
- );
133
- }
65
+ type StartRLNOptions = {
66
+ /**
67
+ * If not set - will extract MetaMask account and get signer from it.
68
+ */
69
+ signer?: ethers.Signer;
70
+ /**
71
+ * If not set - will use default SEPOLIA_CONTRACT address.
72
+ */
73
+ registryAddress?: string;
74
+ /**
75
+ * Credentials to use for generating proofs and connecting to the contract and network.
76
+ * If provided used for validating the network chainId and connecting to registry contract.
77
+ */
78
+ credentials?: EncryptedCredentials | DecryptedCredentials;
79
+ };
80
+
81
+ type RegisterMembershipOptions =
82
+ | { signature: string }
83
+ | { identity: IdentityCredential };
84
+
85
+ type WakuRLNEncoderOptions = WakuEncoderOptions & {
86
+ credentials: EncryptedCredentials | DecryptedCredentials;
87
+ };
134
88
 
135
- extractMetadata(): ProofMetadata {
136
- const externalNullifier = poseidonHash(this.epoch, this.rlnIdentifier);
137
- return new ProofMetadata(
138
- this.nullifier,
139
- this.shareX,
140
- this.shareY,
141
- externalNullifier
142
- );
143
- }
144
- }
89
+ export class RLNInstance {
90
+ private started = false;
91
+ private starting = false;
145
92
 
146
- export function proofToBytes(p: IRateLimitProof): Uint8Array {
147
- return concatenate(
148
- p.proof,
149
- p.merkleRoot,
150
- p.epoch,
151
- p.shareX,
152
- p.shareY,
153
- p.nullifier,
154
- p.rlnIdentifier
155
- );
156
- }
93
+ private _contract: undefined | RLNContract;
94
+ private _signer: undefined | ethers.Signer;
157
95
 
158
- export function poseidonHash(...input: Array<Uint8Array>): Uint8Array {
159
- const inputLen = writeUIntLE(new Uint8Array(8), input.length, 0, 8);
160
- const lenPrefixedData = concatenate(inputLen, ...input);
161
- return zerokitRLN.poseidonHash(lenPrefixedData);
162
- }
96
+ private keystore = Keystore.create();
97
+ private _credentials: undefined | DecryptedCredentials;
163
98
 
164
- export function sha256(input: Uint8Array): Uint8Array {
165
- const inputLen = writeUIntLE(new Uint8Array(8), input.length, 0, 8);
166
- const lenPrefixedData = concatenate(inputLen, input);
167
- return zerokitRLN.hash(lenPrefixedData);
168
- }
99
+ constructor(public zerokit: Zerokit) {}
169
100
 
170
- export class RLNInstance {
171
- constructor(
172
- private zkRLN: number,
173
- private witnessCalculator: WitnessCalculator
174
- ) {}
175
-
176
- generateIdentityCredentials(): IdentityCredential {
177
- const memKeys = zerokitRLN.generateExtendedMembershipKey(this.zkRLN); // TODO: rename this function in zerokit rln-wasm
178
- return IdentityCredential.fromBytes(memKeys);
101
+ public get contract(): undefined | RLNContract {
102
+ return this._contract;
179
103
  }
180
104
 
181
- generateSeededIdentityCredential(seed: string): IdentityCredential {
182
- const seedBytes = stringEncoder.encode(seed);
183
- // TODO: rename this function in zerokit rln-wasm
184
- const memKeys = zerokitRLN.generateSeededExtendedMembershipKey(
185
- this.zkRLN,
186
- seedBytes
187
- );
188
- return IdentityCredential.fromBytes(memKeys);
189
- }
190
-
191
- insertMember(idCommitment: Uint8Array): void {
192
- zerokitRLN.insertMember(this.zkRLN, idCommitment);
105
+ public get signer(): undefined | ethers.Signer {
106
+ return this._signer;
193
107
  }
194
108
 
195
- insertMembers(index: number, ...idCommitments: Array<Uint8Array>): void {
196
- // serializes a seq of IDCommitments to a byte seq
197
- // the order of serialization is |id_commitment_len<8>|id_commitment<var>|
198
- const idCommitmentLen = writeUIntLE(
199
- new Uint8Array(8),
200
- idCommitments.length,
201
- 0,
202
- 8
203
- );
204
- const idCommitmentBytes = concatenate(idCommitmentLen, ...idCommitments);
205
- zerokitRLN.setLeavesFrom(this.zkRLN, index, idCommitmentBytes);
206
- }
109
+ public async start(options: StartRLNOptions = {}): Promise<void> {
110
+ if (this.started || this.starting) {
111
+ return;
112
+ }
207
113
 
208
- deleteMember(index: number): void {
209
- zerokitRLN.deleteLeaf(this.zkRLN, index);
114
+ this.starting = true;
115
+
116
+ try {
117
+ const { credentials, keystore } =
118
+ await RLNInstance.decryptCredentialsIfNeeded(options.credentials);
119
+ const { signer, registryAddress } = await this.determineStartOptions(
120
+ options,
121
+ credentials
122
+ );
123
+
124
+ if (keystore) {
125
+ this.keystore = keystore;
126
+ }
127
+
128
+ this._credentials = credentials;
129
+ this._signer = signer!;
130
+ this._contract = await RLNContract.init(this, {
131
+ registryAddress: registryAddress!,
132
+ signer: signer!
133
+ });
134
+ this.started = true;
135
+ } finally {
136
+ this.starting = false;
137
+ }
210
138
  }
211
139
 
212
- getMerkleRoot(): Uint8Array {
213
- return zerokitRLN.getRoot(this.zkRLN);
214
- }
140
+ private async determineStartOptions(
141
+ options: StartRLNOptions,
142
+ credentials: KeystoreEntity | undefined
143
+ ): Promise<StartRLNOptions> {
144
+ let chainId = credentials?.membership.chainId;
145
+ const registryAddress =
146
+ credentials?.membership.address ||
147
+ options.registryAddress ||
148
+ SEPOLIA_CONTRACT.address;
149
+
150
+ if (registryAddress === SEPOLIA_CONTRACT.address) {
151
+ chainId = SEPOLIA_CONTRACT.chainId;
152
+ }
215
153
 
216
- serializeMessage(
217
- uint8Msg: Uint8Array,
218
- memIndex: number,
219
- epoch: Uint8Array,
220
- idKey: Uint8Array
221
- ): Uint8Array {
222
- // calculate message length
223
- const msgLen = writeUIntLE(new Uint8Array(8), uint8Msg.length, 0, 8);
154
+ const signer = options.signer || (await extractMetaMaskSigner());
155
+ const currentChainId = await signer.getChainId();
224
156
 
225
- // Converting index to LE bytes
226
- const memIndexBytes = writeUIntLE(new Uint8Array(8), memIndex, 0, 8);
157
+ if (chainId && chainId !== currentChainId) {
158
+ throw Error(
159
+ `Failed to start RLN contract, chain ID of contract is different from current one: contract-${chainId}, current network-${currentChainId}`
160
+ );
161
+ }
227
162
 
228
- // [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> ]
229
- return concatenate(idKey, memIndexBytes, epoch, msgLen, uint8Msg);
163
+ return {
164
+ signer,
165
+ registryAddress
166
+ };
230
167
  }
231
168
 
232
- async generateRLNProof(
233
- msg: Uint8Array,
234
- index: number,
235
- epoch: Uint8Array | Date | undefined,
236
- idSecretHash: Uint8Array
237
- ): Promise<IRateLimitProof> {
238
- if (epoch == undefined) {
239
- epoch = epochIntToBytes(dateToEpoch(new Date()));
240
- } else if (epoch instanceof Date) {
241
- epoch = epochIntToBytes(dateToEpoch(epoch));
169
+ private static async decryptCredentialsIfNeeded(
170
+ credentials?: EncryptedCredentials | DecryptedCredentials
171
+ ): Promise<{ credentials?: DecryptedCredentials; keystore?: Keystore }> {
172
+ if (!credentials) {
173
+ return {};
242
174
  }
243
175
 
244
- if (epoch.length != 32) throw "invalid epoch";
245
- if (idSecretHash.length != 32) throw "invalid id secret hash";
246
- if (index < 0) throw "index must be >= 0";
176
+ if ("identity" in credentials) {
177
+ return { credentials };
178
+ }
247
179
 
248
- const serialized_msg = this.serializeMessage(
249
- msg,
250
- index,
251
- epoch,
252
- idSecretHash
253
- );
254
- const rlnWitness = zerokitRLN.getSerializedRLNWitness(
255
- this.zkRLN,
256
- serialized_msg
257
- );
258
- const inputs = zerokitRLN.RLNWitnessToJson(this.zkRLN, rlnWitness);
259
- const calculatedWitness = await this.witnessCalculator.calculateWitness(
260
- inputs,
261
- false
262
- ); // no sanity check being used in zerokit
263
-
264
- const proofBytes = zerokitRLN.generate_rln_proof_with_witness(
265
- this.zkRLN,
266
- calculatedWitness,
267
- rlnWitness
180
+ const keystore = Keystore.fromString(credentials.keystore);
181
+
182
+ if (!keystore) {
183
+ return {};
184
+ }
185
+
186
+ const decryptedCredentials = await keystore.readCredential(
187
+ credentials.id,
188
+ credentials.password
268
189
  );
269
190
 
270
- return new Proof(proofBytes);
191
+ return {
192
+ keystore,
193
+ credentials: decryptedCredentials
194
+ };
271
195
  }
272
196
 
273
- verifyRLNProof(
274
- proof: IRateLimitProof | Uint8Array,
275
- msg: Uint8Array
276
- ): boolean {
277
- let pBytes: Uint8Array;
278
- if (proof instanceof Uint8Array) {
279
- pBytes = proof;
280
- } else {
281
- pBytes = proofToBytes(proof);
197
+ public async registerMembership(
198
+ options: RegisterMembershipOptions
199
+ ): Promise<undefined | DecryptedCredentials> {
200
+ if (!this.contract) {
201
+ throw Error("RLN Contract is not initialized.");
282
202
  }
283
203
 
284
- // calculate message length
285
- const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
204
+ let identity = "identity" in options && options.identity;
286
205
 
287
- return zerokitRLN.verifyRLNProof(
288
- this.zkRLN,
289
- concatenate(pBytes, msgLen, msg)
290
- );
206
+ if ("signature" in options) {
207
+ identity = this.zerokit.generateSeededIdentityCredential(
208
+ options.signature
209
+ );
210
+ }
211
+
212
+ if (!identity) {
213
+ throw Error("Missing signature or identity to register membership.");
214
+ }
215
+
216
+ return this.contract.registerWithIdentity(identity);
217
+ }
218
+
219
+ /**
220
+ * Changes credentials in use by relying on provided Keystore earlier in rln.start
221
+ * @param id: string, hash of credentials to select from Keystore
222
+ * @param password: string or bytes to use to decrypt credentials from Keystore
223
+ */
224
+ public async useCredentials(id: string, password: Password): Promise<void> {
225
+ this._credentials = await this.keystore?.readCredential(id, password);
291
226
  }
292
227
 
293
- verifyWithRoots(
294
- proof: IRateLimitProof | Uint8Array,
295
- msg: Uint8Array,
296
- ...roots: Array<Uint8Array>
297
- ): boolean {
298
- let pBytes: Uint8Array;
299
- if (proof instanceof Uint8Array) {
300
- pBytes = proof;
301
- } else {
302
- pBytes = proofToBytes(proof);
228
+ public async createEncoder(
229
+ options: WakuRLNEncoderOptions
230
+ ): Promise<RLNEncoder> {
231
+ const { credentials: decryptedCredentials } =
232
+ await RLNInstance.decryptCredentialsIfNeeded(options.credentials);
233
+ const credentials = decryptedCredentials || this._credentials;
234
+
235
+ if (!credentials) {
236
+ throw Error(
237
+ "Failed to create Encoder: missing RLN credentials. Use createRLNEncoder directly."
238
+ );
303
239
  }
304
- // calculate message length
305
- const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
306
240
 
307
- const rootsBytes = concatenate(...roots);
241
+ await this.verifyCredentialsAgainstContract(credentials);
308
242
 
309
- return zerokitRLN.verifyWithRoots(
310
- this.zkRLN,
311
- concatenate(pBytes, msgLen, msg),
312
- rootsBytes
313
- );
243
+ return createRLNEncoder({
244
+ encoder: createEncoder(options),
245
+ rlnInstance: this,
246
+ index: credentials.membership.treeIndex,
247
+ credential: credentials.identity
248
+ });
314
249
  }
315
250
 
316
- verifyWithNoRoot(
317
- proof: IRateLimitProof | Uint8Array,
318
- msg: Uint8Array
319
- ): boolean {
320
- let pBytes: Uint8Array;
321
- if (proof instanceof Uint8Array) {
322
- pBytes = proof;
323
- } else {
324
- pBytes = proofToBytes(proof);
251
+ private async verifyCredentialsAgainstContract(
252
+ credentials: KeystoreEntity
253
+ ): Promise<void> {
254
+ if (!this._contract) {
255
+ throw Error(
256
+ "Failed to verify chain coordinates: no contract initialized."
257
+ );
325
258
  }
326
259
 
327
- // calculate message length
328
- const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
260
+ const registryAddress = credentials.membership.address;
261
+ const currentRegistryAddress = this._contract.registry.address;
262
+ if (registryAddress !== currentRegistryAddress) {
263
+ throw Error(
264
+ `Failed to verify chain coordinates: credentials contract address=${registryAddress} is not equal to registryContract address=${currentRegistryAddress}`
265
+ );
266
+ }
329
267
 
330
- return zerokitRLN.verifyWithRoots(
331
- this.zkRLN,
332
- concatenate(pBytes, msgLen, msg),
333
- new Uint8Array()
334
- );
268
+ const chainId = credentials.membership.chainId;
269
+ const network = await this._contract.registry.provider.getNetwork();
270
+ const currentChainId = network.chainId;
271
+ if (chainId !== currentChainId) {
272
+ throw Error(
273
+ `Failed to verify chain coordinates: credentials chainID=${chainId} is not equal to registryContract chainID=${currentChainId}`
274
+ );
275
+ }
276
+ }
277
+
278
+ public createDecoder(
279
+ contentTopic: ContentTopic
280
+ ): RLNDecoder<IDecodedMessage> {
281
+ return createRLNDecoder({
282
+ rlnInstance: this,
283
+ decoder: createDecoder(contentTopic)
284
+ });
335
285
  }
336
286
  }
@@ -1,5 +1,8 @@
1
1
  class RootPerBlock {
2
- constructor(public root: Uint8Array, public blockNumber: number) {}
2
+ constructor(
3
+ public root: Uint8Array,
4
+ public blockNumber: number
5
+ ) {}
3
6
  }
4
7
 
5
8
  const maxBufferSize = 20;