@waku/rln 0.1.6-383e0b2.0 → 0.1.6-4997440.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/index2.js +1 -1
- package/bundle/_virtual/utils.js +2 -2
- package/bundle/_virtual/utils2.js +2 -2
- package/bundle/index.js +2 -1
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/checksum.js +3 -3
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/cipher.js +4 -4
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/class.js +7 -7
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/functional.js +7 -7
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/index.js +6 -6
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/kdf.js +5 -5
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/password.js +1 -1
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/schema-validation-generated.js +1 -1
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/schema-validation.js +2 -2
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/lib/types.js +1 -1
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/_assert.js +1 -1
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/_sha2.js +3 -3
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/_u64.js +1 -1
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/cryptoBrowser.js +1 -1
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/hmac.js +3 -3
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/pbkdf2.js +4 -4
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/scrypt.js +5 -5
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/sha256.js +3 -3
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/sha512.js +4 -4
- package/bundle/{packages/rln → node_modules/@chainsafe/bls-keystore}/node_modules/@noble/hashes/utils.js +2 -2
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/aes.js +3 -3
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/pbkdf2.js +7 -7
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +3 -3
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/scrypt.js +3 -3
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/sha256.js +3 -3
- package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +7 -7
- package/bundle/node_modules/@ethersproject/keccak256/lib.esm/index.js +1 -1
- package/bundle/node_modules/@noble/hashes/esm/_assert.js +6 -32
- package/bundle/node_modules/@noble/hashes/esm/_md.js +22 -11
- package/bundle/node_modules/@noble/hashes/esm/_u64.js +4 -3
- package/bundle/{packages/rln/node_modules → node_modules}/@noble/hashes/esm/hmac.js +19 -10
- package/bundle/{packages/rln/node_modules/@noble/hashes/esm/sha256.js → node_modules/@noble/hashes/esm/sha2.js} +36 -50
- package/bundle/node_modules/@noble/hashes/esm/sha256.js +5 -102
- package/bundle/node_modules/@noble/hashes/esm/sha3.js +30 -24
- package/bundle/node_modules/@noble/hashes/esm/utils.js +69 -18
- package/bundle/node_modules/bn.js/lib/bn.js +1 -0
- package/bundle/node_modules/ethereum-cryptography/esm/sha256.js +1 -1
- package/bundle/node_modules/{@ethersproject/keccak256/node_modules/js-sha3 → js-sha3}/src/sha3.js +2 -2
- package/bundle/packages/core/dist/lib/message/version_0.js +1 -4
- package/bundle/packages/rln/dist/contract/constants.js +1 -0
- package/bundle/packages/rln/dist/contract/rln_base_contract.js +127 -71
- package/bundle/packages/rln/dist/credentials_manager.js +3 -3
- package/bundle/packages/rln/dist/keystore/cipher.js +3 -3
- package/bundle/packages/rln/dist/keystore/keystore.js +1 -1
- package/bundle/packages/rln/dist/message.js +11 -0
- package/dist/.tsbuildinfo +1 -1
- package/dist/contract/index.d.ts +1 -0
- package/dist/contract/index.js +1 -0
- package/dist/contract/index.js.map +1 -1
- package/dist/contract/rln_base_contract.d.ts +32 -22
- package/dist/contract/rln_base_contract.js +127 -71
- package/dist/contract/rln_base_contract.js.map +1 -1
- package/dist/contract/types.d.ts +5 -0
- package/dist/contract/types.js.map +1 -1
- package/dist/credentials_manager.js +1 -1
- package/dist/credentials_manager.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/keystore/keystore.js.map +1 -1
- package/dist/keystore/types.d.ts +2 -2
- package/dist/message.d.ts +5 -4
- package/dist/message.js +2 -0
- package/dist/message.js.map +1 -1
- package/package.json +1 -1
- package/src/contract/index.ts +1 -0
- package/src/contract/rln_base_contract.ts +166 -102
- package/src/contract/types.ts +5 -0
- package/src/credentials_manager.ts +1 -1
- package/src/index.ts +3 -1
- package/src/keystore/keystore.ts +4 -2
- package/src/keystore/types.ts +2 -2
- package/src/message.ts +7 -4
- package/bundle/packages/rln/node_modules/@noble/hashes/esm/_assert.js +0 -43
- package/bundle/packages/rln/node_modules/@noble/hashes/esm/_sha2.js +0 -116
- package/bundle/packages/rln/node_modules/@noble/hashes/esm/utils.js +0 -43
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/index.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/md5.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/nil.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/parse.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/regex.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/rng.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/sha1.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/stringify.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v1.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v3.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v35.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v4.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/v5.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/validate.js +0 -0
- /package/bundle/{packages/rln/node_modules → node_modules}/@chainsafe/bls-keystore/node_modules/uuid/dist/esm-browser/version.js +0 -0
package/dist/message.js
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
import { message } from "@waku/core";
|
1
2
|
import * as utils from "@waku/utils/bytes";
|
2
3
|
import { epochBytesToInt } from "./utils/index.js";
|
3
4
|
export function toRLNSignal(contentTopic, msg) {
|
@@ -9,6 +10,7 @@ export class RlnMessage {
|
|
9
10
|
msg;
|
10
11
|
rateLimitProof;
|
11
12
|
pubsubTopic = "";
|
13
|
+
version = message.version_0.Version;
|
12
14
|
constructor(rlnInstance, msg, rateLimitProof) {
|
13
15
|
this.rlnInstance = rlnInstance;
|
14
16
|
this.msg = msg;
|
package/dist/message.js.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"message.js","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAOrC,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,UAAU,WAAW,CAAC,YAAoB,EAAE,GAAa;IAC7D,MAAM,iBAAiB,GAAG,KAAK,CAAC,WAAW,CAAC,YAAY,IAAI,EAAE,CAAC,CAAC;IAChE,OAAO,IAAI,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,EAAE,GAAG,iBAAiB,CAAC,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,OAAO,UAAU;IAKX;IACA;IACD;IANF,WAAW,GAAG,EAAE,CAAC;IACjB,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;IAE3C,YACU,WAAwB,EACxB,GAAM,EACP,cAA2C;QAF1C,gBAAW,GAAX,WAAW,CAAa;QACxB,QAAG,GAAH,GAAG,CAAG;QACP,mBAAc,GAAd,cAAc,CAA6B;IACjD,CAAC;IAEG,MAAM,CAAC,KAAmB;QAC/B,OAAO,IAAI,CAAC,cAAc;YACxB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,CACtC,IAAI,CAAC,cAAc,EACnB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,EAC5C,KAAK,CACN,CAAC,2EAA2E;YAC/E,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAEM,YAAY;QACjB,OAAO,IAAI,CAAC,cAAc;YACxB,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,CACvC,IAAI,CAAC,cAAc,EACnB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAC7C,CAAC,2EAA2E;YAC/E,CAAC,CAAC,SAAS,CAAC;IAChB,CAAC;IAED,IAAW,OAAO;QAChB,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;IAC1B,CAAC;IAED,IAAW,YAAY;QACrB,OAAO,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC;IAC/B,CAAC;IAED,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;IAC5B,CAAC;IAED,IAAW,SAAS;QAClB,OAAO,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;IAC5B,CAAC;IAED,IAAW,IAAI;QACb,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;IACvB,CAAC;IAED,IAAW,KAAK;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,EAAE,KAAK,CAAC;QACzC,IAAI,CAAC,KAAK;YAAE,OAAO,SAAS,CAAC;QAE7B,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;CACF"}
|
package/package.json
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"name":"@waku/rln","version":"0.1.6-
|
1
|
+
{"name":"@waku/rln","version":"0.1.6-4997440.0","description":"RLN (Rate Limiting Nullifier) implementation for Waku","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"type":"module","homepage":"https://github.com/waku-org/js-waku/tree/master/packages/rln#readme","repository":{"type":"git","url":"https://github.com/waku-org/js-waku.git"},"bugs":{"url":"https://github.com/waku-org/js-waku/issues"},"license":"MIT OR Apache-2.0","keywords":["waku","rln","rate-limiting","privacy","web3"],"scripts":{"build":"run-s build:**","build:copy":"mkdir -p dist/resources && cp -r src/resources/* dist/resources/","build:esm":"tsc","build:bundle":"rollup --config rollup.config.js","fix":"run-s fix:*","fix:lint":"eslint src *.js --fix","check":"run-s check:*","check:tsc":"tsc -p tsconfig.dev.json","check:lint":"eslint \"src/!(resources)/**/*.{ts,js}\" *.js","check:spelling":"cspell \"{README.md,src/**/*.ts}\"","test":"NODE_ENV=test run-s test:*","test:browser":"karma start karma.conf.cjs","watch:build":"tsc -p tsconfig.json -w","watch:test":"mocha --watch","prepublish":"npm run build","reset-hard":"git clean -dfx -e .idea && git reset --hard && npm i && npm run build"},"engines":{"node":">=20"},"devDependencies":{"@rollup/plugin-commonjs":"^25.0.7","@rollup/plugin-json":"^6.0.0","@rollup/plugin-node-resolve":"^15.2.3","@types/chai":"^5.0.1","@types/chai-spies":"^1.0.6","@waku/interfaces":"0.0.31-4997440.0","@types/deep-equal-in-any-order":"^1.0.4","@types/lodash":"^4.17.15","@types/sinon":"^17.0.3","@waku/build-utils":"^1.0.0","@waku/message-encryption":"0.0.34-4997440.0","deep-equal-in-any-order":"^2.0.6","fast-check":"^3.23.2","rollup-plugin-copy":"^3.5.0"},"files":["dist","bundle","src/**/*.ts","!**/*.spec.*","!**/*.json","CHANGELOG.md","LICENSE","README.md"],"dependencies":{"@chainsafe/bls-keystore":"3.0.0","@waku/core":"0.0.36-4997440.0","@waku/utils":"0.0.24-4997440.0","@noble/hashes":"^1.2.0","@waku/zerokit-rln-wasm":"^0.0.13","ethereum-cryptography":"^3.1.0","ethers":"^5.7.2","lodash":"^4.17.21","uuid":"^11.0.5","chai":"^5.1.2","chai-as-promised":"^8.0.1","chai-spies":"^1.1.0","chai-subset":"^1.6.0","sinon":"^19.0.2"}}
|
package/src/contract/index.ts
CHANGED
@@ -22,6 +22,8 @@ export class RLNBaseContract {
|
|
22
22
|
public contract: ethers.Contract;
|
23
23
|
private deployBlock: undefined | number;
|
24
24
|
private rateLimit: number;
|
25
|
+
private minRateLimit?: number;
|
26
|
+
private maxRateLimit?: number;
|
25
27
|
|
26
28
|
protected _members: Map<number, Member> = new Map();
|
27
29
|
private _membersFilter: ethers.EventFilter;
|
@@ -29,19 +31,9 @@ export class RLNBaseContract {
|
|
29
31
|
private _membersExpiredFilter: ethers.EventFilter;
|
30
32
|
|
31
33
|
/**
|
32
|
-
*
|
33
|
-
* Allows injecting a mocked contract for testing purposes.
|
34
|
+
* Private constructor for RLNBaseContract. Use static create() instead.
|
34
35
|
*/
|
35
|
-
|
36
|
-
// Initialize members and subscriptions
|
37
|
-
this.fetchMembers()
|
38
|
-
.then(() => {
|
39
|
-
this.subscribeToMembers();
|
40
|
-
})
|
41
|
-
.catch((error) => {
|
42
|
-
log.error("Failed to initialize members", { error });
|
43
|
-
});
|
44
|
-
|
36
|
+
protected constructor(options: RLNContractInitOptions) {
|
45
37
|
const {
|
46
38
|
address,
|
47
39
|
signer,
|
@@ -49,15 +41,51 @@ export class RLNBaseContract {
|
|
49
41
|
contract
|
50
42
|
} = options;
|
51
43
|
|
52
|
-
|
44
|
+
log.info("Initializing RLNBaseContract", { address, rateLimit });
|
53
45
|
|
54
46
|
this.contract = contract || new ethers.Contract(address, RLN_ABI, signer);
|
55
47
|
this.rateLimit = rateLimit;
|
56
48
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
49
|
+
try {
|
50
|
+
log.info("Setting up event filters");
|
51
|
+
// Initialize event filters
|
52
|
+
this._membersFilter = this.contract.filters.MembershipRegistered();
|
53
|
+
this._membershipErasedFilter = this.contract.filters.MembershipErased();
|
54
|
+
this._membersExpiredFilter = this.contract.filters.MembershipExpired();
|
55
|
+
log.info("Event filters initialized successfully");
|
56
|
+
} catch (error) {
|
57
|
+
log.error("Failed to initialize event filters", { error });
|
58
|
+
throw new Error(
|
59
|
+
"Failed to initialize event filters: " + (error as Error).message
|
60
|
+
);
|
61
|
+
}
|
62
|
+
|
63
|
+
// Initialize members and subscriptions
|
64
|
+
this.fetchMembers()
|
65
|
+
.then(() => {
|
66
|
+
this.subscribeToMembers();
|
67
|
+
})
|
68
|
+
.catch((error) => {
|
69
|
+
log.error("Failed to initialize members", { error });
|
70
|
+
});
|
71
|
+
}
|
72
|
+
|
73
|
+
/**
|
74
|
+
* Static async factory to create and initialize RLNBaseContract
|
75
|
+
*/
|
76
|
+
public static async create(
|
77
|
+
options: RLNContractInitOptions
|
78
|
+
): Promise<RLNBaseContract> {
|
79
|
+
const instance = new RLNBaseContract(options);
|
80
|
+
const [min, max] = await Promise.all([
|
81
|
+
instance.contract.minMembershipRateLimit(),
|
82
|
+
instance.contract.maxMembershipRateLimit()
|
83
|
+
]);
|
84
|
+
instance.minRateLimit = ethers.BigNumber.from(min).toNumber();
|
85
|
+
instance.maxRateLimit = ethers.BigNumber.from(max).toNumber();
|
86
|
+
|
87
|
+
instance.validateRateLimit(instance.rateLimit);
|
88
|
+
return instance;
|
61
89
|
}
|
62
90
|
|
63
91
|
/**
|
@@ -82,21 +110,21 @@ export class RLNBaseContract {
|
|
82
110
|
}
|
83
111
|
|
84
112
|
/**
|
85
|
-
* Gets the minimum allowed rate limit
|
86
|
-
* @returns Promise<number> The minimum rate limit in messages per epoch
|
113
|
+
* Gets the minimum allowed rate limit (cached)
|
87
114
|
*/
|
88
|
-
public
|
89
|
-
|
90
|
-
|
115
|
+
public getMinRateLimit(): number {
|
116
|
+
if (this.minRateLimit === undefined)
|
117
|
+
throw new Error("minRateLimit not initialized");
|
118
|
+
return this.minRateLimit;
|
91
119
|
}
|
92
120
|
|
93
121
|
/**
|
94
|
-
* Gets the maximum allowed rate limit
|
95
|
-
* @returns Promise<number> The maximum rate limit in messages per epoch
|
122
|
+
* Gets the maximum allowed rate limit (cached)
|
96
123
|
*/
|
97
|
-
public
|
98
|
-
|
99
|
-
|
124
|
+
public getMaxRateLimit(): number {
|
125
|
+
if (this.maxRateLimit === undefined)
|
126
|
+
throw new Error("maxRateLimit not initialized");
|
127
|
+
return this.maxRateLimit;
|
100
128
|
}
|
101
129
|
|
102
130
|
/**
|
@@ -133,7 +161,7 @@ export class RLNBaseContract {
|
|
133
161
|
* Updates the rate limit for future registrations
|
134
162
|
* @param newRateLimit The new rate limit to use
|
135
163
|
*/
|
136
|
-
public
|
164
|
+
public setRateLimit(newRateLimit: number): void {
|
137
165
|
this.validateRateLimit(newRateLimit);
|
138
166
|
this.rateLimit = newRateLimit;
|
139
167
|
}
|
@@ -324,7 +352,7 @@ export class RLNBaseContract {
|
|
324
352
|
this.contract.on(
|
325
353
|
this.membersFilter,
|
326
354
|
(
|
327
|
-
_idCommitment:
|
355
|
+
_idCommitment: bigint,
|
328
356
|
_membershipRateLimit: ethers.BigNumber,
|
329
357
|
_index: ethers.BigNumber,
|
330
358
|
event: ethers.Event
|
@@ -336,7 +364,7 @@ export class RLNBaseContract {
|
|
336
364
|
this.contract.on(
|
337
365
|
this.membershipErasedFilter,
|
338
366
|
(
|
339
|
-
_idCommitment:
|
367
|
+
_idCommitment: bigint,
|
340
368
|
_membershipRateLimit: ethers.BigNumber,
|
341
369
|
_index: ethers.BigNumber,
|
342
370
|
event: ethers.Event
|
@@ -348,7 +376,7 @@ export class RLNBaseContract {
|
|
348
376
|
this.contract.on(
|
349
377
|
this.membersExpiredFilter,
|
350
378
|
(
|
351
|
-
_idCommitment:
|
379
|
+
_idCommitment: bigint,
|
352
380
|
_membershipRateLimit: ethers.BigNumber,
|
353
381
|
_index: ethers.BigNumber,
|
354
382
|
event: ethers.Event
|
@@ -358,94 +386,89 @@ export class RLNBaseContract {
|
|
358
386
|
);
|
359
387
|
}
|
360
388
|
|
361
|
-
/**
|
362
|
-
* Helper method to get remaining messages in current epoch
|
363
|
-
* @param membershipId The ID of the membership to check
|
364
|
-
* @returns number of remaining messages allowed in current epoch
|
365
|
-
*/
|
366
|
-
public async getRemainingMessages(membershipId: number): Promise<number> {
|
367
|
-
try {
|
368
|
-
const [startTime, , rateLimit] =
|
369
|
-
await this.contract.getMembershipInfo(membershipId);
|
370
|
-
|
371
|
-
// Calculate current epoch
|
372
|
-
const currentTime = Math.floor(Date.now() / 1000);
|
373
|
-
const epochsPassed = Math.floor(
|
374
|
-
(currentTime - startTime) / RATE_LIMIT_PARAMS.EPOCH_LENGTH
|
375
|
-
);
|
376
|
-
const currentEpochStart =
|
377
|
-
startTime + epochsPassed * RATE_LIMIT_PARAMS.EPOCH_LENGTH;
|
378
|
-
|
379
|
-
// Get message count in current epoch using contract's function
|
380
|
-
const messageCount = await this.contract.getMessageCount(
|
381
|
-
membershipId,
|
382
|
-
currentEpochStart
|
383
|
-
);
|
384
|
-
return Math.max(
|
385
|
-
0,
|
386
|
-
ethers.BigNumber.from(rateLimit)
|
387
|
-
.sub(ethers.BigNumber.from(messageCount))
|
388
|
-
.toNumber()
|
389
|
-
);
|
390
|
-
} catch (error) {
|
391
|
-
log.error(
|
392
|
-
`Error getting remaining messages: ${(error as Error).message}`
|
393
|
-
);
|
394
|
-
return 0; // Fail safe: assume no messages remaining on error
|
395
|
-
}
|
396
|
-
}
|
397
|
-
|
398
389
|
public async getMembershipInfo(
|
399
|
-
|
390
|
+
idCommitmentBigInt: bigint
|
400
391
|
): Promise<MembershipInfo | undefined> {
|
401
392
|
try {
|
402
|
-
const
|
403
|
-
await this.contract.
|
393
|
+
const membershipData =
|
394
|
+
await this.contract.memberships(idCommitmentBigInt);
|
404
395
|
const currentBlock = await this.contract.provider.getBlockNumber();
|
396
|
+
const [
|
397
|
+
depositAmount,
|
398
|
+
activeDuration,
|
399
|
+
gracePeriodStartTimestamp,
|
400
|
+
gracePeriodDuration,
|
401
|
+
rateLimit,
|
402
|
+
index,
|
403
|
+
holder,
|
404
|
+
token
|
405
|
+
] = membershipData;
|
406
|
+
|
407
|
+
const gracePeriodEnd = gracePeriodStartTimestamp.add(gracePeriodDuration);
|
405
408
|
|
406
409
|
let state: MembershipState;
|
407
|
-
if (currentBlock <
|
410
|
+
if (currentBlock < gracePeriodStartTimestamp.toNumber()) {
|
408
411
|
state = MembershipState.Active;
|
409
|
-
} else if (currentBlock <
|
412
|
+
} else if (currentBlock < gracePeriodEnd.toNumber()) {
|
410
413
|
state = MembershipState.GracePeriod;
|
411
414
|
} else {
|
412
415
|
state = MembershipState.Expired;
|
413
416
|
}
|
414
417
|
|
415
|
-
const index = await this.getMemberIndex(idCommitment);
|
416
|
-
if (!index) return undefined;
|
417
|
-
|
418
418
|
return {
|
419
419
|
index,
|
420
|
-
idCommitment,
|
421
|
-
rateLimit: rateLimit
|
422
|
-
startBlock:
|
423
|
-
endBlock:
|
424
|
-
state
|
420
|
+
idCommitment: idCommitmentBigInt.toString(),
|
421
|
+
rateLimit: Number(rateLimit),
|
422
|
+
startBlock: gracePeriodStartTimestamp.toNumber(),
|
423
|
+
endBlock: gracePeriodEnd.toNumber(),
|
424
|
+
state,
|
425
|
+
depositAmount,
|
426
|
+
activeDuration,
|
427
|
+
gracePeriodDuration,
|
428
|
+
holder,
|
429
|
+
token
|
425
430
|
};
|
426
431
|
} catch (error) {
|
432
|
+
log.error("Error in getMembershipInfo:", error);
|
427
433
|
return undefined;
|
428
434
|
}
|
429
435
|
}
|
430
436
|
|
431
437
|
public async extendMembership(
|
432
|
-
|
438
|
+
idCommitmentBigInt: bigint
|
433
439
|
): Promise<ethers.ContractTransaction> {
|
434
|
-
|
440
|
+
const tx = await this.contract.extendMemberships([idCommitmentBigInt]);
|
441
|
+
await tx.wait();
|
442
|
+
return tx;
|
435
443
|
}
|
436
444
|
|
437
445
|
public async eraseMembership(
|
438
|
-
|
446
|
+
idCommitmentBigInt: bigint,
|
439
447
|
eraseFromMembershipSet: boolean = true
|
440
448
|
): Promise<ethers.ContractTransaction> {
|
441
|
-
|
442
|
-
|
443
|
-
|
449
|
+
if (
|
450
|
+
!(await this.isExpired(idCommitmentBigInt)) ||
|
451
|
+
!(await this.isInGracePeriod(idCommitmentBigInt))
|
452
|
+
) {
|
453
|
+
throw new Error("Membership is not expired or in grace period");
|
454
|
+
}
|
455
|
+
|
456
|
+
const estimatedGas = await this.contract.estimateGas[
|
457
|
+
"eraseMemberships(uint256[],bool)"
|
458
|
+
]([idCommitmentBigInt], eraseFromMembershipSet);
|
459
|
+
const gasLimit = estimatedGas.add(10000);
|
460
|
+
|
461
|
+
const tx = await this.contract["eraseMemberships(uint256[],bool)"](
|
462
|
+
[idCommitmentBigInt],
|
463
|
+
eraseFromMembershipSet,
|
464
|
+
{ gasLimit }
|
444
465
|
);
|
466
|
+
await tx.wait();
|
467
|
+
return tx;
|
445
468
|
}
|
446
469
|
|
447
470
|
public async registerMembership(
|
448
|
-
|
471
|
+
idCommitmentBigInt: bigint,
|
449
472
|
rateLimit: number = DEFAULT_RATE_LIMIT
|
450
473
|
): Promise<ethers.ContractTransaction> {
|
451
474
|
if (
|
@@ -456,12 +479,12 @@ export class RLNBaseContract {
|
|
456
479
|
`Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`
|
457
480
|
);
|
458
481
|
}
|
459
|
-
return this.contract.register(
|
482
|
+
return this.contract.register(idCommitmentBigInt, rateLimit, []);
|
460
483
|
}
|
461
484
|
|
462
|
-
public async withdraw(token: string,
|
485
|
+
public async withdraw(token: string, walletAddress: string): Promise<void> {
|
463
486
|
try {
|
464
|
-
const tx = await this.contract.withdraw(token,
|
487
|
+
const tx = await this.contract.withdraw(token, walletAddress);
|
465
488
|
await tx.wait();
|
466
489
|
} catch (error) {
|
467
490
|
log.error(`Error in withdraw: ${(error as Error).message}`);
|
@@ -478,7 +501,7 @@ export class RLNBaseContract {
|
|
478
501
|
|
479
502
|
// Check if the ID commitment is already registered
|
480
503
|
const existingIndex = await this.getMemberIndex(
|
481
|
-
identity.IDCommitmentBigInt
|
504
|
+
identity.IDCommitmentBigInt
|
482
505
|
);
|
483
506
|
if (existingIndex) {
|
484
507
|
throw new Error(
|
@@ -516,7 +539,7 @@ export class RLNBaseContract {
|
|
516
539
|
}
|
517
540
|
|
518
541
|
const memberRegistered = txRegisterReceipt.events?.find(
|
519
|
-
(event) => event.event === "MembershipRegistered"
|
542
|
+
(event: ethers.Event) => event.event === "MembershipRegistered"
|
520
543
|
);
|
521
544
|
|
522
545
|
if (!memberRegistered || !memberRegistered.args) {
|
@@ -610,7 +633,7 @@ export class RLNBaseContract {
|
|
610
633
|
const txRegisterReceipt = await txRegisterResponse.wait();
|
611
634
|
|
612
635
|
const memberRegistered = txRegisterReceipt.events?.find(
|
613
|
-
(event) => event.event === "MembershipRegistered"
|
636
|
+
(event: ethers.Event) => event.event === "MembershipRegistered"
|
614
637
|
);
|
615
638
|
|
616
639
|
if (!memberRegistered || !memberRegistered.args) {
|
@@ -653,16 +676,16 @@ export class RLNBaseContract {
|
|
653
676
|
}
|
654
677
|
|
655
678
|
/**
|
656
|
-
* Validates that the rate limit is within the allowed range
|
679
|
+
* Validates that the rate limit is within the allowed range (sync)
|
657
680
|
* @throws Error if the rate limit is outside the allowed range
|
658
681
|
*/
|
659
682
|
private validateRateLimit(rateLimit: number): void {
|
660
|
-
if (
|
661
|
-
|
662
|
-
|
663
|
-
) {
|
683
|
+
if (this.minRateLimit === undefined || this.maxRateLimit === undefined) {
|
684
|
+
throw new Error("Rate limits not initialized");
|
685
|
+
}
|
686
|
+
if (rateLimit < this.minRateLimit || rateLimit > this.maxRateLimit) {
|
664
687
|
throw new Error(
|
665
|
-
`Rate limit must be between ${
|
688
|
+
`Rate limit must be between ${this.minRateLimit} and ${this.maxRateLimit} messages per epoch`
|
666
689
|
);
|
667
690
|
}
|
668
691
|
}
|
@@ -689,11 +712,11 @@ export class RLNBaseContract {
|
|
689
712
|
}
|
690
713
|
|
691
714
|
private async getMemberIndex(
|
692
|
-
|
715
|
+
idCommitmentBigInt: bigint
|
693
716
|
): Promise<ethers.BigNumber | undefined> {
|
694
717
|
try {
|
695
718
|
const events = await this.contract.queryFilter(
|
696
|
-
this.contract.filters.MembershipRegistered(
|
719
|
+
this.contract.filters.MembershipRegistered(idCommitmentBigInt)
|
697
720
|
);
|
698
721
|
if (events.length === 0) return undefined;
|
699
722
|
|
@@ -704,4 +727,45 @@ export class RLNBaseContract {
|
|
704
727
|
return undefined;
|
705
728
|
}
|
706
729
|
}
|
730
|
+
|
731
|
+
public async getMembershipStatus(
|
732
|
+
idCommitment: bigint
|
733
|
+
): Promise<"expired" | "grace" | "active"> {
|
734
|
+
const [isExpired, isInGrace] = await Promise.all([
|
735
|
+
this.contract.isExpired(idCommitment),
|
736
|
+
this.contract.isInGracePeriod(idCommitment)
|
737
|
+
]);
|
738
|
+
|
739
|
+
if (isExpired) return "expired";
|
740
|
+
if (isInGrace) return "grace";
|
741
|
+
return "active";
|
742
|
+
}
|
743
|
+
|
744
|
+
/**
|
745
|
+
* Checks if a membership is expired for the given idCommitment
|
746
|
+
* @param idCommitmentBigInt The idCommitment as bigint
|
747
|
+
* @returns Promise<boolean> True if expired, false otherwise
|
748
|
+
*/
|
749
|
+
public async isExpired(idCommitmentBigInt: bigint): Promise<boolean> {
|
750
|
+
try {
|
751
|
+
return await this.contract.isExpired(idCommitmentBigInt);
|
752
|
+
} catch (error) {
|
753
|
+
log.error("Error in isExpired:", error);
|
754
|
+
return false;
|
755
|
+
}
|
756
|
+
}
|
757
|
+
|
758
|
+
/**
|
759
|
+
* Checks if a membership is in grace period for the given idCommitment
|
760
|
+
* @param idCommitmentBigInt The idCommitment as bigint
|
761
|
+
* @returns Promise<boolean> True if in grace period, false otherwise
|
762
|
+
*/
|
763
|
+
public async isInGracePeriod(idCommitmentBigInt: bigint): Promise<boolean> {
|
764
|
+
try {
|
765
|
+
return await this.contract.isInGracePeriod(idCommitmentBigInt);
|
766
|
+
} catch (error) {
|
767
|
+
log.error("Error in isInGracePeriod:", error);
|
768
|
+
return false;
|
769
|
+
}
|
770
|
+
}
|
707
771
|
}
|
package/src/contract/types.ts
CHANGED
@@ -38,6 +38,11 @@ export interface MembershipInfo {
|
|
38
38
|
startBlock: number;
|
39
39
|
endBlock: number;
|
40
40
|
state: MembershipState;
|
41
|
+
depositAmount: ethers.BigNumber;
|
42
|
+
activeDuration: number;
|
43
|
+
gracePeriodDuration: number;
|
44
|
+
holder: string;
|
45
|
+
token: string;
|
41
46
|
}
|
42
47
|
|
43
48
|
export enum MembershipState {
|
@@ -80,7 +80,7 @@ export class RLNCredentialsManager {
|
|
80
80
|
|
81
81
|
this.credentials = credentials;
|
82
82
|
this.signer = signer!;
|
83
|
-
this.contract =
|
83
|
+
this.contract = await RLNBaseContract.create({
|
84
84
|
address: address!,
|
85
85
|
signer: signer!,
|
86
86
|
rateLimit: rateLimit ?? this.zerokit?.rateLimit
|
package/src/index.ts
CHANGED
package/src/keystore/keystore.ts
CHANGED
@@ -21,8 +21,8 @@ import { isCredentialValid, isKeystoreValid } from "./schema_validator.js";
|
|
21
21
|
import type {
|
22
22
|
Keccak256Hash,
|
23
23
|
KeystoreEntity,
|
24
|
+
KeystoreMembershipInfo,
|
24
25
|
MembershipHash,
|
25
|
-
MembershipInfo,
|
26
26
|
Password,
|
27
27
|
Sha256Hash
|
28
28
|
} from "./types.js";
|
@@ -310,7 +310,9 @@ export class Keystore {
|
|
310
310
|
|
311
311
|
// follows nwaku implementation
|
312
312
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L111
|
313
|
-
private static computeMembershipHash(
|
313
|
+
private static computeMembershipHash(
|
314
|
+
info: KeystoreMembershipInfo
|
315
|
+
): MembershipHash {
|
314
316
|
return bytesToHex(
|
315
317
|
sha256(utf8ToBytes(`${info.chainId}${info.address}${info.treeIndex}`))
|
316
318
|
).toUpperCase();
|
package/src/keystore/types.ts
CHANGED
@@ -7,7 +7,7 @@ export type Password = string | Uint8Array;
|
|
7
7
|
|
8
8
|
// see reference
|
9
9
|
// https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L111
|
10
|
-
export type
|
10
|
+
export type KeystoreMembershipInfo = {
|
11
11
|
chainId: string;
|
12
12
|
address: string;
|
13
13
|
treeIndex: number;
|
@@ -16,7 +16,7 @@ export type MembershipInfo = {
|
|
16
16
|
|
17
17
|
export type KeystoreEntity = {
|
18
18
|
identity: IdentityCredential;
|
19
|
-
membership:
|
19
|
+
membership: KeystoreMembershipInfo;
|
20
20
|
};
|
21
21
|
|
22
22
|
export type DecryptedCredentials = KeystoreEntity;
|
package/src/message.ts
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
import { message } from "@waku/core";
|
1
2
|
import type {
|
2
3
|
IDecodedMessage,
|
3
4
|
IMessage,
|
4
|
-
IRateLimitProof
|
5
|
+
IRateLimitProof,
|
6
|
+
IRlnMessage
|
5
7
|
} from "@waku/interfaces";
|
6
8
|
import * as utils from "@waku/utils/bytes";
|
7
9
|
|
@@ -13,12 +15,13 @@ export function toRLNSignal(contentTopic: string, msg: IMessage): Uint8Array {
|
|
13
15
|
return new Uint8Array([...(msg.payload ?? []), ...contentTopicBytes]);
|
14
16
|
}
|
15
17
|
|
16
|
-
export class RlnMessage<T extends IDecodedMessage> implements
|
18
|
+
export class RlnMessage<T extends IDecodedMessage> implements IRlnMessage {
|
17
19
|
public pubsubTopic = "";
|
20
|
+
public version = message.version_0.Version;
|
18
21
|
|
19
22
|
public constructor(
|
20
|
-
|
21
|
-
|
23
|
+
private rlnInstance: RLNInstance,
|
24
|
+
private msg: T,
|
22
25
|
public rateLimitProof: IRateLimitProof | undefined
|
23
26
|
) {}
|
24
27
|
|
@@ -1,43 +0,0 @@
|
|
1
|
-
function number(n) {
|
2
|
-
if (!Number.isSafeInteger(n) || n < 0)
|
3
|
-
throw new Error(`Wrong positive integer: ${n}`);
|
4
|
-
}
|
5
|
-
function bool(b) {
|
6
|
-
if (typeof b !== 'boolean')
|
7
|
-
throw new Error(`Expected boolean, not ${b}`);
|
8
|
-
}
|
9
|
-
function bytes(b, ...lengths) {
|
10
|
-
if (!(b instanceof Uint8Array))
|
11
|
-
throw new TypeError('Expected Uint8Array');
|
12
|
-
if (lengths.length > 0 && !lengths.includes(b.length))
|
13
|
-
throw new TypeError(`Expected Uint8Array of length ${lengths}, not of length=${b.length}`);
|
14
|
-
}
|
15
|
-
function hash(hash) {
|
16
|
-
if (typeof hash !== 'function' || typeof hash.create !== 'function')
|
17
|
-
throw new Error('Hash should be wrapped by utils.wrapConstructor');
|
18
|
-
number(hash.outputLen);
|
19
|
-
number(hash.blockLen);
|
20
|
-
}
|
21
|
-
function exists(instance, checkFinished = true) {
|
22
|
-
if (instance.destroyed)
|
23
|
-
throw new Error('Hash instance has been destroyed');
|
24
|
-
if (checkFinished && instance.finished)
|
25
|
-
throw new Error('Hash#digest() has already been called');
|
26
|
-
}
|
27
|
-
function output(out, instance) {
|
28
|
-
bytes(out);
|
29
|
-
const min = instance.outputLen;
|
30
|
-
if (out.length < min) {
|
31
|
-
throw new Error(`digestInto() expects output buffer of length at least ${min}`);
|
32
|
-
}
|
33
|
-
}
|
34
|
-
const assert = {
|
35
|
-
number,
|
36
|
-
bool,
|
37
|
-
bytes,
|
38
|
-
hash,
|
39
|
-
exists,
|
40
|
-
output,
|
41
|
-
};
|
42
|
-
|
43
|
-
export { bool, bytes, assert as default, exists, hash, number, output };
|