@waku/rln 0.0.2-09108d9.0 → 0.0.2-2380dac.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/index.js +2 -1
- package/bundle/packages/rln/dist/contract/abi.js +648 -0
- package/bundle/packages/rln/dist/contract/constants.js +25 -65
- package/bundle/packages/rln/dist/contract/rln_contract.js +370 -75
- package/bundle/packages/rln/dist/message.js +1 -1
- package/bundle/packages/rln/dist/rln.js +34 -20
- package/bundle/packages/rln/dist/zerokit.js +34 -14
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/abi.d.ts +46 -0
- package/dist/contract/abi.js +647 -0
- package/dist/contract/abi.js.map +1 -0
- package/dist/contract/constants.d.ts +63 -3
- package/dist/contract/constants.js +23 -64
- package/dist/contract/constants.js.map +1 -1
- package/dist/contract/rln_contract.d.ts +100 -17
- package/dist/contract/rln_contract.js +369 -73
- package/dist/contract/rln_contract.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/message.js +1 -1
- package/dist/message.js.map +1 -1
- package/dist/rln.d.ts +5 -1
- package/dist/rln.js +34 -19
- package/dist/rln.js.map +1 -1
- package/dist/zerokit.d.ts +10 -6
- package/dist/zerokit.js +34 -14
- package/dist/zerokit.js.map +1 -1
- package/package.json +1 -1
- package/src/contract/abi.ts +646 -0
- package/src/contract/constants.ts +26 -65
- package/src/contract/rln_contract.ts +549 -108
- package/src/index.ts +4 -9
- package/src/message.ts +1 -1
- package/src/rln.ts +54 -21
- 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
|
-
|
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
|
-
|
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<
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
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 =
|
@@ -128,7 +160,7 @@ export class RLNInstance {
|
|
128
160
|
try {
|
129
161
|
const { credentials, keystore } =
|
130
162
|
await RLNInstance.decryptCredentialsIfNeeded(options.credentials);
|
131
|
-
const { signer,
|
163
|
+
const { signer, address } = await this.determineStartOptions(
|
132
164
|
options,
|
133
165
|
credentials
|
134
166
|
);
|
@@ -140,8 +172,9 @@ export class RLNInstance {
|
|
140
172
|
this._credentials = credentials;
|
141
173
|
this._signer = signer!;
|
142
174
|
this._contract = await RLNContract.init(this, {
|
143
|
-
|
144
|
-
signer: signer
|
175
|
+
address: address!,
|
176
|
+
signer: signer!,
|
177
|
+
rateLimit: options.rateLimit ?? this.zerokit.getRateLimit
|
145
178
|
});
|
146
179
|
this.started = true;
|
147
180
|
} finally {
|
@@ -154,12 +187,12 @@ export class RLNInstance {
|
|
154
187
|
credentials: KeystoreEntity | undefined
|
155
188
|
): Promise<StartRLNOptions> {
|
156
189
|
let chainId = credentials?.membership.chainId;
|
157
|
-
const
|
190
|
+
const address =
|
158
191
|
credentials?.membership.address ||
|
159
|
-
options.
|
192
|
+
options.address ||
|
160
193
|
SEPOLIA_CONTRACT.address;
|
161
194
|
|
162
|
-
if (
|
195
|
+
if (address === SEPOLIA_CONTRACT.address) {
|
163
196
|
chainId = SEPOLIA_CONTRACT.chainId;
|
164
197
|
}
|
165
198
|
|
@@ -174,7 +207,7 @@ export class RLNInstance {
|
|
174
207
|
|
175
208
|
return {
|
176
209
|
signer,
|
177
|
-
|
210
|
+
address
|
178
211
|
};
|
179
212
|
}
|
180
213
|
|
@@ -270,7 +303,7 @@ export class RLNInstance {
|
|
270
303
|
}
|
271
304
|
|
272
305
|
const registryAddress = credentials.membership.address;
|
273
|
-
const currentRegistryAddress = this._contract.
|
306
|
+
const currentRegistryAddress = this._contract.address;
|
274
307
|
if (registryAddress !== currentRegistryAddress) {
|
275
308
|
throw Error(
|
276
309
|
`Failed to verify chain coordinates: credentials contract address=${registryAddress} is not equal to registryContract address=${currentRegistryAddress}`
|
@@ -278,7 +311,7 @@ export class RLNInstance {
|
|
278
311
|
}
|
279
312
|
|
280
313
|
const chainId = credentials.membership.chainId;
|
281
|
-
const network = await this._contract.
|
314
|
+
const network = await this._contract.provider.getNetwork();
|
282
315
|
const currentChainId = network.chainId;
|
283
316
|
if (chainId !== currentChainId) {
|
284
317
|
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(
|
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
|
-
);
|
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
|
-
|
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
|
}
|