@waku/rln 0.0.2-c41b319.0 → 0.0.2-caeafce.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 +1 -1
- package/bundle/packages/interfaces/dist/protocols.js +40 -45
- package/bundle/packages/rln/dist/contract/abi.js +648 -0
- package/bundle/packages/rln/dist/contract/constants.js +8 -13
- package/bundle/packages/rln/dist/contract/rln_contract.js +14 -3
- package/bundle/packages/rln/dist/identity.js +0 -24
- package/bundle/packages/rln/dist/rln.js +39 -15
- package/bundle/packages/rln/dist/zerokit.js +22 -16
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/{abi/rlnv2.d.ts → abi.d.ts} +22 -18
- package/dist/contract/abi.js +647 -0
- package/dist/contract/abi.js.map +1 -0
- package/dist/contract/constants.d.ts +22 -23
- package/dist/contract/constants.js +7 -12
- package/dist/contract/constants.js.map +1 -1
- package/dist/contract/rln_contract.d.ts +8 -0
- package/dist/contract/rln_contract.js +14 -3
- package/dist/contract/rln_contract.js.map +1 -1
- package/dist/identity.d.ts +0 -1
- package/dist/identity.js +0 -24
- package/dist/identity.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/rln.js +39 -14
- package/dist/rln.js.map +1 -1
- package/dist/zerokit.d.ts +5 -1
- package/dist/zerokit.js +22 -16
- package/dist/zerokit.js.map +1 -1
- package/package.json +1 -1
- package/src/contract/abi.ts +646 -0
- package/src/contract/constants.ts +8 -14
- package/src/contract/rln_contract.ts +16 -3
- package/src/identity.ts +0 -42
- package/src/index.ts +2 -2
- package/src/rln.ts +54 -14
- package/src/zerokit.ts +45 -16
- package/bundle/node_modules/@iden3/js-crypto/dist/browser/esm/index.js +0 -7
- package/bundle/node_modules/@stablelib/binary/lib/binary.js +0 -22
- package/bundle/node_modules/@stablelib/chacha/lib/chacha.js +0 -245
- package/bundle/node_modules/@stablelib/wipe/lib/wipe.js +0 -26
- package/bundle/packages/rln/dist/contract/abi/rlnv2.js +0 -394
- package/dist/contract/abi/rlnv2.js +0 -393
- package/dist/contract/abi/rlnv2.js.map +0 -1
- package/src/contract/abi/rlnv2.ts +0 -392
@@ -5,7 +5,7 @@ import { hexToBytes } from '../../../utils/dist/bytes/index.js';
|
|
5
5
|
import { Logger } from '../../../utils/dist/logger/index.js';
|
6
6
|
import { MerkleRootTracker } from '../root_tracker.js';
|
7
7
|
import { zeroPadLE } from '../utils/bytes.js';
|
8
|
-
import {
|
8
|
+
import { RLN_ABI } from './abi.js';
|
9
9
|
import { RATE_LIMIT_PARAMS, DEFAULT_RATE_LIMIT } from './constants.js';
|
10
10
|
import { Contract } from '../../../../node_modules/@ethersproject/contracts/lib.esm/index.js';
|
11
11
|
import { BigNumber } from '../../../../node_modules/@ethersproject/bignumber/lib.esm/bignumber.js';
|
@@ -45,8 +45,7 @@ class RLNContract {
|
|
45
45
|
this.rateLimit = rateLimit;
|
46
46
|
const initialRoot = rlnInstance.zerokit.getMerkleRoot();
|
47
47
|
// Use the injected contract if provided; otherwise, instantiate a new one.
|
48
|
-
this.contract =
|
49
|
-
contract || new Contract(address, RLN_V2_ABI, signer);
|
48
|
+
this.contract = contract || new Contract(address, RLN_ABI, signer);
|
50
49
|
this.merkleRootTracker = new MerkleRootTracker(5, initialRoot);
|
51
50
|
// Initialize event filters for MembershipRegistered and MembershipRemoved
|
52
51
|
this._membersFilter = this.contract.filters.MembershipRegistered();
|
@@ -58,6 +57,18 @@ class RLNContract {
|
|
58
57
|
getRateLimit() {
|
59
58
|
return this.rateLimit;
|
60
59
|
}
|
60
|
+
/**
|
61
|
+
* Gets the contract address
|
62
|
+
*/
|
63
|
+
get address() {
|
64
|
+
return this.contract.address;
|
65
|
+
}
|
66
|
+
/**
|
67
|
+
* Gets the contract provider
|
68
|
+
*/
|
69
|
+
get provider() {
|
70
|
+
return this.contract.provider;
|
71
|
+
}
|
61
72
|
/**
|
62
73
|
* Gets the minimum allowed rate limit from the contract
|
63
74
|
* @returns Promise<number> The minimum rate limit in messages per epoch
|
@@ -1,7 +1,3 @@
|
|
1
|
-
import { arrayify } from '../../../node_modules/@ethersproject/bytes/lib.esm/index.js';
|
2
|
-
import { keccak256 } from '../../../node_modules/@ethersproject/keccak256/lib.esm/index.js';
|
3
|
-
import { Poseidon as m } from '../../../node_modules/@iden3/js-crypto/dist/browser/esm/index.js';
|
4
|
-
import { streamXOR } from '../../../node_modules/@stablelib/chacha/lib/chacha.js';
|
5
1
|
import { buildBigIntFromUint8Array } from './utils/bytes.js';
|
6
2
|
import './utils/epoch.js';
|
7
3
|
|
@@ -29,26 +25,6 @@ class IdentityCredential {
|
|
29
25
|
const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment, 32);
|
30
26
|
return new IdentityCredential(idTrapdoor, idNullifier, idSecretHash, idCommitment, idCommitmentBigInt);
|
31
27
|
}
|
32
|
-
static generateSeeded(signature) {
|
33
|
-
// Generate deterministic seed from signature
|
34
|
-
const seed = arrayify(keccak256(signature));
|
35
|
-
// Use ChaCha for deterministic randomness (as in Rust code)
|
36
|
-
const nonce = new Uint8Array(12);
|
37
|
-
const idSecretHash = new Uint8Array(32);
|
38
|
-
streamXOR(seed, nonce, idSecretHash, idSecretHash);
|
39
|
-
// Convert to bigint for Poseidon
|
40
|
-
const secretBigInt = BigInt("0x" + Buffer.from(idSecretHash).toString("hex"));
|
41
|
-
// Generate commitment using Poseidon
|
42
|
-
const idCommitmentBigInt = m.hash([secretBigInt]);
|
43
|
-
// Convert commitment back to Uint8Array
|
44
|
-
const idCommitment = arrayify("0x" + idCommitmentBigInt.toString(16).padStart(64, "0"));
|
45
|
-
// Generate deterministic trapdoor and nullifier from the secret hash
|
46
|
-
const idTrapdoor = new Uint8Array(32);
|
47
|
-
const idNullifier = new Uint8Array(32);
|
48
|
-
streamXOR(idSecretHash, nonce, idTrapdoor, idTrapdoor);
|
49
|
-
streamXOR(idTrapdoor, nonce, idNullifier, idNullifier);
|
50
|
-
return new IdentityCredential(idTrapdoor, idNullifier, idSecretHash, idCommitment, idCommitmentBigInt);
|
51
|
-
}
|
52
28
|
}
|
53
29
|
|
54
30
|
export { IdentityCredential };
|
@@ -21,27 +21,43 @@ import { Logger } from '../../utils/dist/logger/index.js';
|
|
21
21
|
import '../../core/dist/lib/metadata/metadata.js';
|
22
22
|
import __wbg_init, { init_panic_hook, newRLN } from '../../../node_modules/@waku/zerokit-rln-wasm/rln_wasm.js';
|
23
23
|
import { createRLNEncoder, createRLNDecoder } from './codec.js';
|
24
|
+
import { DEFAULT_RATE_LIMIT, SEPOLIA_CONTRACT } from './contract/constants.js';
|
24
25
|
import { RLNContract } from './contract/rln_contract.js';
|
25
|
-
import { SEPOLIA_CONTRACT } from './contract/constants.js';
|
26
|
-
import { IdentityCredential } from './identity.js';
|
27
26
|
import { Keystore } from './keystore/keystore.js';
|
28
27
|
import verificationKey from './resources/verification_key.js';
|
29
28
|
import { builder } from './resources/witness_calculator.js';
|
30
29
|
import { extractMetaMaskSigner } from './utils/metamask.js';
|
31
30
|
import './utils/epoch.js';
|
32
31
|
import { Zerokit } from './zerokit.js';
|
33
|
-
import { arrayify } from '../../../node_modules/@ethersproject/bytes/lib.esm/index.js';
|
34
32
|
|
35
33
|
const log = new Logger("waku:rln");
|
36
34
|
async function loadWitnessCalculator() {
|
37
|
-
|
38
|
-
|
39
|
-
|
35
|
+
try {
|
36
|
+
const url = new URL("./resources/rln.wasm", import.meta.url);
|
37
|
+
const response = await fetch(url);
|
38
|
+
if (!response.ok) {
|
39
|
+
throw new Error(`Failed to fetch witness calculator: ${response.status} ${response.statusText}`);
|
40
|
+
}
|
41
|
+
return await builder(new Uint8Array(await response.arrayBuffer()), false);
|
42
|
+
}
|
43
|
+
catch (error) {
|
44
|
+
log.error("Error loading witness calculator:", error);
|
45
|
+
throw new Error(`Failed to load witness calculator: ${error instanceof Error ? error.message : String(error)}`);
|
46
|
+
}
|
40
47
|
}
|
41
48
|
async function loadZkey() {
|
42
|
-
|
43
|
-
|
44
|
-
|
49
|
+
try {
|
50
|
+
const url = new URL("./resources/rln_final.zkey", import.meta.url);
|
51
|
+
const response = await fetch(url);
|
52
|
+
if (!response.ok) {
|
53
|
+
throw new Error(`Failed to fetch zkey: ${response.status} ${response.statusText}`);
|
54
|
+
}
|
55
|
+
return new Uint8Array(await response.arrayBuffer());
|
56
|
+
}
|
57
|
+
catch (error) {
|
58
|
+
log.error("Error loading zkey:", error);
|
59
|
+
throw new Error(`Failed to load zkey: ${error instanceof Error ? error.message : String(error)}`);
|
60
|
+
}
|
45
61
|
}
|
46
62
|
/**
|
47
63
|
* Create an instance of RLN
|
@@ -58,7 +74,7 @@ async function create() {
|
|
58
74
|
const vkey = stringEncoder.encode(JSON.stringify(verificationKey));
|
59
75
|
const DEPTH = 20;
|
60
76
|
const zkRLN = newRLN(DEPTH, zkey, vkey);
|
61
|
-
const zerokit = new Zerokit(zkRLN, witnessCalculator);
|
77
|
+
const zerokit = new Zerokit(zkRLN, witnessCalculator, DEFAULT_RATE_LIMIT);
|
62
78
|
return new RLNInstance(zerokit);
|
63
79
|
}
|
64
80
|
catch (error) {
|
@@ -84,6 +100,8 @@ class RLNInstance {
|
|
84
100
|
return this._signer;
|
85
101
|
}
|
86
102
|
async start(options = {}) {
|
103
|
+
// eslint-disable-next-line no-console
|
104
|
+
console.log("starting", options);
|
87
105
|
if (this.started || this.starting) {
|
88
106
|
return;
|
89
107
|
}
|
@@ -99,7 +117,7 @@ class RLNInstance {
|
|
99
117
|
this._contract = await RLNContract.init(this, {
|
100
118
|
address: address,
|
101
119
|
signer: signer,
|
102
|
-
rateLimit: options.rateLimit
|
120
|
+
rateLimit: options.rateLimit ?? this.zerokit.getRateLimit
|
103
121
|
});
|
104
122
|
this.started = true;
|
105
123
|
}
|
@@ -115,6 +133,12 @@ class RLNInstance {
|
|
115
133
|
if (address === SEPOLIA_CONTRACT.address) {
|
116
134
|
chainId = SEPOLIA_CONTRACT.chainId;
|
117
135
|
}
|
136
|
+
// eslint-disable-next-line no-console
|
137
|
+
console.log({
|
138
|
+
chainId,
|
139
|
+
address,
|
140
|
+
SEPOLIA_CONTRACT
|
141
|
+
});
|
118
142
|
const signer = options.signer || (await extractMetaMaskSigner());
|
119
143
|
const currentChainId = await signer.getChainId();
|
120
144
|
if (chainId && chainId !== currentChainId) {
|
@@ -146,9 +170,9 @@ class RLNInstance {
|
|
146
170
|
if (!this.contract) {
|
147
171
|
throw Error("RLN Contract is not initialized.");
|
148
172
|
}
|
149
|
-
let identity = "identity" in options
|
173
|
+
let identity = "identity" in options && options.identity;
|
150
174
|
if ("signature" in options) {
|
151
|
-
identity =
|
175
|
+
identity = this.zerokit.generateSeededIdentityCredential(options.signature);
|
152
176
|
}
|
153
177
|
if (!identity) {
|
154
178
|
throw Error("Missing signature or identity to register membership.");
|
@@ -182,12 +206,12 @@ class RLNInstance {
|
|
182
206
|
throw Error("Failed to verify chain coordinates: no contract initialized.");
|
183
207
|
}
|
184
208
|
const registryAddress = credentials.membership.address;
|
185
|
-
const currentRegistryAddress = this._contract.
|
209
|
+
const currentRegistryAddress = this._contract.address;
|
186
210
|
if (registryAddress !== currentRegistryAddress) {
|
187
211
|
throw Error(`Failed to verify chain coordinates: credentials contract address=${registryAddress} is not equal to registryContract address=${currentRegistryAddress}`);
|
188
212
|
}
|
189
213
|
const chainId = credentials.membership.chainId;
|
190
|
-
const network = await this._contract.
|
214
|
+
const network = await this._contract.provider.getNetwork();
|
191
215
|
const currentChainId = network.chainId;
|
192
216
|
if (chainId !== currentChainId) {
|
193
217
|
throw Error(`Failed to verify chain coordinates: credentials chainID=${chainId} is not equal to registryContract chainID=${currentChainId}`);
|
@@ -8,9 +8,20 @@ import { epochIntToBytes, dateToEpoch } from './utils/epoch.js';
|
|
8
8
|
class Zerokit {
|
9
9
|
zkRLN;
|
10
10
|
witnessCalculator;
|
11
|
-
|
11
|
+
rateLimit;
|
12
|
+
constructor(zkRLN, witnessCalculator, rateLimit = DEFAULT_RATE_LIMIT) {
|
12
13
|
this.zkRLN = zkRLN;
|
13
14
|
this.witnessCalculator = witnessCalculator;
|
15
|
+
this.rateLimit = rateLimit;
|
16
|
+
}
|
17
|
+
get getZkRLN() {
|
18
|
+
return this.zkRLN;
|
19
|
+
}
|
20
|
+
get getWitnessCalculator() {
|
21
|
+
return this.witnessCalculator;
|
22
|
+
}
|
23
|
+
get getRateLimit() {
|
24
|
+
return this.rateLimit;
|
14
25
|
}
|
15
26
|
generateIdentityCredentials() {
|
16
27
|
const memKeys = generateExtendedMembershipKey(this.zkRLN); // TODO: rename this function in zerokit rln-wasm
|
@@ -39,32 +50,33 @@ class Zerokit {
|
|
39
50
|
getMerkleRoot() {
|
40
51
|
return getRoot(this.zkRLN);
|
41
52
|
}
|
42
|
-
serializeMessage(uint8Msg, memIndex, epoch, idKey, rateLimit
|
53
|
+
serializeMessage(uint8Msg, memIndex, epoch, idKey, rateLimit) {
|
43
54
|
// calculate message length
|
44
55
|
const msgLen = writeUIntLE(new Uint8Array(8), uint8Msg.length, 0, 8);
|
45
56
|
const memIndexBytes = writeUIntLE(new Uint8Array(8), memIndex, 0, 8);
|
46
|
-
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit, 0, 8);
|
57
|
+
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit ?? this.rateLimit, 0, 8);
|
47
58
|
// [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> | rate_limit<8> ]
|
48
59
|
return concatenate(idKey, memIndexBytes, epoch, msgLen, uint8Msg, rateLimitBytes);
|
49
60
|
}
|
50
|
-
async generateRLNProof(msg, index, epoch, idSecretHash, rateLimit
|
61
|
+
async generateRLNProof(msg, index, epoch, idSecretHash, rateLimit) {
|
51
62
|
if (epoch === undefined) {
|
52
63
|
epoch = epochIntToBytes(dateToEpoch(new Date()));
|
53
64
|
}
|
54
65
|
else if (epoch instanceof Date) {
|
55
66
|
epoch = epochIntToBytes(dateToEpoch(epoch));
|
56
67
|
}
|
68
|
+
const effectiveRateLimit = rateLimit ?? this.rateLimit;
|
57
69
|
if (epoch.length !== 32)
|
58
70
|
throw new Error("invalid epoch");
|
59
71
|
if (idSecretHash.length !== 32)
|
60
72
|
throw new Error("invalid id secret hash");
|
61
73
|
if (index < 0)
|
62
74
|
throw new Error("index must be >= 0");
|
63
|
-
if (
|
64
|
-
|
75
|
+
if (effectiveRateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
|
76
|
+
effectiveRateLimit > RATE_LIMIT_PARAMS.MAX_RATE) {
|
65
77
|
throw new Error(`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`);
|
66
78
|
}
|
67
|
-
const serialized_msg = this.serializeMessage(msg, index, epoch, idSecretHash,
|
79
|
+
const serialized_msg = this.serializeMessage(msg, index, epoch, idSecretHash, effectiveRateLimit);
|
68
80
|
const rlnWitness = getSerializedRLNWitness(this.zkRLN, serialized_msg);
|
69
81
|
const inputs = RLNWitnessToJson(this.zkRLN, rlnWitness);
|
70
82
|
const calculatedWitness = await this.witnessCalculator.calculateWitness(inputs, false);
|
@@ -81,9 +93,7 @@ class Zerokit {
|
|
81
93
|
}
|
82
94
|
// calculate message length
|
83
95
|
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
84
|
-
const rateLimitBytes = rateLimit
|
85
|
-
? writeUIntLE(new Uint8Array(8), rateLimit, 0, 8)
|
86
|
-
: new Uint8Array(8); // Zero if not specified
|
96
|
+
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit ?? this.rateLimit, 0, 8);
|
87
97
|
return verifyRLNProof(this.zkRLN, concatenate(pBytes, msgLen, msg, rateLimitBytes));
|
88
98
|
}
|
89
99
|
verifyWithRoots(proof, msg, roots, rateLimit) {
|
@@ -96,9 +106,7 @@ class Zerokit {
|
|
96
106
|
}
|
97
107
|
// calculate message length
|
98
108
|
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
99
|
-
const rateLimitBytes = rateLimit
|
100
|
-
? writeUIntLE(new Uint8Array(8), rateLimit, 0, 8)
|
101
|
-
: new Uint8Array(8); // Zero if not specified
|
109
|
+
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit ?? this.rateLimit, 0, 8);
|
102
110
|
const rootsBytes = concatenate(...roots);
|
103
111
|
return verifyWithRoots(this.zkRLN, concatenate(pBytes, msgLen, msg, rateLimitBytes), rootsBytes);
|
104
112
|
}
|
@@ -112,9 +120,7 @@ class Zerokit {
|
|
112
120
|
}
|
113
121
|
// calculate message length
|
114
122
|
const msgLen = writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
|
115
|
-
const rateLimitBytes = rateLimit
|
116
|
-
? writeUIntLE(new Uint8Array(8), rateLimit, 0, 8)
|
117
|
-
: new Uint8Array(8); // Zero if not specified
|
123
|
+
const rateLimitBytes = writeUIntLE(new Uint8Array(8), rateLimit ?? this.rateLimit, 0, 8);
|
118
124
|
return verifyWithRoots(this.zkRLN, concatenate(pBytes, msgLen, msg, rateLimitBytes), new Uint8Array());
|
119
125
|
}
|
120
126
|
}
|