@waku/rln 0.1.6-76fb1ea.0 → 0.1.6-86bbf5b.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 (58) hide show
  1. package/bundle/index.js +1 -1
  2. package/bundle/packages/core/dist/lib/connection_manager/connection_manager.js +0 -1
  3. package/bundle/packages/core/dist/lib/connection_manager/keep_alive_manager.js +0 -1
  4. package/bundle/packages/core/dist/lib/filter/filter.js +0 -3
  5. package/bundle/packages/core/dist/lib/light_push/light_push.js +0 -3
  6. package/bundle/packages/core/dist/lib/message/version_0.js +0 -2
  7. package/bundle/packages/core/dist/lib/metadata/metadata.js +0 -3
  8. package/bundle/packages/core/dist/lib/store/store.js +0 -3
  9. package/bundle/packages/proto/dist/generated/light_push.js +22 -28
  10. package/bundle/packages/rln/dist/codec.js +0 -1
  11. package/bundle/packages/rln/dist/contract/constants.js +7 -1
  12. package/bundle/packages/rln/dist/contract/rln_base_contract.js +10 -6
  13. package/bundle/packages/rln/dist/contract/rln_contract.js +0 -1
  14. package/bundle/packages/rln/dist/credentials_manager.js +16 -15
  15. package/bundle/packages/rln/dist/identity.js +40 -7
  16. package/bundle/packages/rln/dist/keystore/keystore.js +15 -12
  17. package/bundle/packages/rln/dist/message.js +0 -15
  18. package/bundle/packages/rln/dist/rln.js +0 -15
  19. package/bundle/packages/rln/dist/utils/bytes.js +37 -16
  20. package/bundle/packages/rln/dist/utils/epoch.js +0 -1
  21. package/bundle/packages/utils/dist/common/sharding/index.js +0 -1
  22. package/dist/.tsbuildinfo +1 -1
  23. package/dist/contract/constants.d.ts +6 -0
  24. package/dist/contract/constants.js +6 -0
  25. package/dist/contract/constants.js.map +1 -1
  26. package/dist/contract/rln_base_contract.js +10 -5
  27. package/dist/contract/rln_base_contract.js.map +1 -1
  28. package/dist/credentials_manager.js +16 -14
  29. package/dist/credentials_manager.js.map +1 -1
  30. package/dist/identity.d.ts +11 -2
  31. package/dist/identity.js +26 -6
  32. package/dist/identity.js.map +1 -1
  33. package/dist/keystore/keystore.js +15 -11
  34. package/dist/keystore/keystore.js.map +1 -1
  35. package/dist/utils/bytes.d.ts +12 -5
  36. package/dist/utils/bytes.js +36 -15
  37. package/dist/utils/bytes.js.map +1 -1
  38. package/dist/utils/index.d.ts +1 -1
  39. package/dist/utils/index.js +1 -1
  40. package/dist/utils/index.js.map +1 -1
  41. package/package.json +1 -1
  42. package/src/contract/constants.ts +9 -0
  43. package/src/contract/rln_base_contract.ts +12 -13
  44. package/src/credentials_manager.ts +27 -21
  45. package/src/identity.ts +41 -6
  46. package/src/keystore/keystore.ts +28 -24
  47. package/src/utils/bytes.ts +46 -25
  48. package/src/utils/index.ts +1 -1
  49. package/bundle/packages/core/dist/lib/light_push/light_push_v3.js +0 -31
  50. package/bundle/packages/core/dist/lib/light_push/status_codes.js +0 -26
  51. package/bundle/packages/core/dist/lib/light_push/status_codes_v3.js +0 -17
  52. package/bundle/packages/interfaces/dist/light_push_v3.js +0 -16
  53. package/bundle/packages/proto/dist/generated/light_push_v2.js +0 -389
  54. package/bundle/packages/proto/dist/generated/light_push_v3.js +0 -348
  55. package/dist/contract/test-utils.d.ts +0 -39
  56. package/dist/contract/test-utils.js +0 -118
  57. package/dist/contract/test-utils.js.map +0 -1
  58. package/src/contract/test-utils.ts +0 -179
package/bundle/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { RLNDecoder, RLNEncoder } from './packages/rln/dist/codec.js';
2
2
  export { RLN_ABI } from './packages/rln/dist/contract/abi.js';
3
3
  export { RLNContract } from './packages/rln/dist/contract/rln_contract.js';
4
- export { DEFAULT_RATE_LIMIT, LINEA_CONTRACT, RATE_LIMIT_PARAMS, RATE_LIMIT_TIERS } from './packages/rln/dist/contract/constants.js';
4
+ export { DEFAULT_Q, DEFAULT_RATE_LIMIT, LINEA_CONTRACT, RATE_LIMIT_PARAMS, RATE_LIMIT_TIERS } from './packages/rln/dist/contract/constants.js';
5
5
  export { MembershipState } from './packages/rln/dist/contract/types.js';
6
6
  export { RLNBaseContract } from './packages/rln/dist/contract/rln_base_contract.js';
7
7
  export { createRLN } from './packages/rln/dist/create.js';
@@ -12,7 +12,6 @@ import '../../../../../node_modules/multiformats/dist/src/codecs/json.js';
12
12
  import '../../../../../node_modules/@multiformats/multiaddr/dist/src/convert.js';
13
13
  import '../../../../../node_modules/@multiformats/multiaddr/dist/src/protocols-table.js';
14
14
  import '../../../../../node_modules/@multiformats/multiaddr/dist/src/multiaddr.js';
15
- import '../../../../interfaces/dist/light_push_v3.js';
16
15
  import '../../../../interfaces/dist/protocols.js';
17
16
  import '../../../../interfaces/dist/connection_manager.js';
18
17
  import '../../../../interfaces/dist/health_indicator.js';
@@ -1,4 +1,3 @@
1
- import '../../../../interfaces/dist/light_push_v3.js';
2
1
  import '../../../../interfaces/dist/protocols.js';
3
2
  import '../../../../interfaces/dist/connection_manager.js';
4
3
  import '../../../../interfaces/dist/health_indicator.js';
@@ -1,4 +1,3 @@
1
- import '../../../../interfaces/dist/light_push_v3.js';
2
1
  import '../../../../interfaces/dist/protocols.js';
3
2
  import '../../../../interfaces/dist/connection_manager.js';
4
3
  import '../../../../interfaces/dist/health_indicator.js';
@@ -20,8 +19,6 @@ import '../../../../proto/dist/generated/filter.js';
20
19
  import '../../../../proto/dist/generated/topic_only_message.js';
21
20
  import '../../../../proto/dist/generated/filter_v2.js';
22
21
  import '../../../../proto/dist/generated/light_push.js';
23
- import '../../../../proto/dist/generated/light_push_v2.js';
24
- import '../../../../proto/dist/generated/light_push_v3.js';
25
22
  import '../../../../proto/dist/generated/store_v3.js';
26
23
  import '../../../../proto/dist/generated/peer_exchange.js';
27
24
  import '../../../../proto/dist/generated/metadata.js';
@@ -1,4 +1,3 @@
1
- import '../../../../interfaces/dist/light_push_v3.js';
2
1
  import '../../../../interfaces/dist/protocols.js';
3
2
  import '../../../../interfaces/dist/connection_manager.js';
4
3
  import '../../../../interfaces/dist/health_indicator.js';
@@ -7,8 +6,6 @@ import '../../../../proto/dist/generated/filter.js';
7
6
  import '../../../../proto/dist/generated/topic_only_message.js';
8
7
  import '../../../../proto/dist/generated/filter_v2.js';
9
8
  export { PushResponse } from '../../../../proto/dist/generated/light_push.js';
10
- import '../../../../proto/dist/generated/light_push_v2.js';
11
- import '../../../../proto/dist/generated/light_push_v3.js';
12
9
  import '../../../../proto/dist/generated/store_v3.js';
13
10
  import '../../../../proto/dist/generated/peer_exchange.js';
14
11
  import '../../../../proto/dist/generated/metadata.js';
@@ -3,8 +3,6 @@ import '../../../../proto/dist/generated/filter.js';
3
3
  import '../../../../proto/dist/generated/topic_only_message.js';
4
4
  import '../../../../proto/dist/generated/filter_v2.js';
5
5
  import '../../../../proto/dist/generated/light_push.js';
6
- import '../../../../proto/dist/generated/light_push_v2.js';
7
- import '../../../../proto/dist/generated/light_push_v3.js';
8
6
  import '../../../../proto/dist/generated/store_v3.js';
9
7
  import '../../../../proto/dist/generated/peer_exchange.js';
10
8
  import '../../../../proto/dist/generated/metadata.js';
@@ -1,4 +1,3 @@
1
- import '../../../../interfaces/dist/light_push_v3.js';
2
1
  import '../../../../interfaces/dist/protocols.js';
3
2
  import '../../../../interfaces/dist/connection_manager.js';
4
3
  import '../../../../interfaces/dist/health_indicator.js';
@@ -7,8 +6,6 @@ import '../../../../proto/dist/generated/filter.js';
7
6
  import '../../../../proto/dist/generated/topic_only_message.js';
8
7
  import '../../../../proto/dist/generated/filter_v2.js';
9
8
  import '../../../../proto/dist/generated/light_push.js';
10
- import '../../../../proto/dist/generated/light_push_v2.js';
11
- import '../../../../proto/dist/generated/light_push_v3.js';
12
9
  import '../../../../proto/dist/generated/store_v3.js';
13
10
  import '../../../../proto/dist/generated/peer_exchange.js';
14
11
  import '../../../../proto/dist/generated/metadata.js';
@@ -1,4 +1,3 @@
1
- import '../../../../interfaces/dist/light_push_v3.js';
2
1
  import '../../../../interfaces/dist/protocols.js';
3
2
  import '../../../../interfaces/dist/connection_manager.js';
4
3
  import '../../../../interfaces/dist/health_indicator.js';
@@ -20,8 +19,6 @@ import '../../../../proto/dist/generated/filter.js';
20
19
  import '../../../../proto/dist/generated/topic_only_message.js';
21
20
  import '../../../../proto/dist/generated/filter_v2.js';
22
21
  import '../../../../proto/dist/generated/light_push.js';
23
- import '../../../../proto/dist/generated/light_push_v2.js';
24
- import '../../../../proto/dist/generated/light_push_v3.js';
25
22
  import '../../../../proto/dist/generated/store_v3.js';
26
23
  import '../../../../proto/dist/generated/peer_exchange.js';
27
24
  import '../../../../proto/dist/generated/metadata.js';
@@ -21,28 +21,30 @@ var PushRequest;
21
21
  if (opts.lengthDelimited !== false) {
22
22
  w.fork();
23
23
  }
24
- if (obj.pubsubTopic != null) {
25
- w.uint32(162);
24
+ if ((obj.pubsubTopic != null && obj.pubsubTopic !== '')) {
25
+ w.uint32(10);
26
26
  w.string(obj.pubsubTopic);
27
27
  }
28
28
  if (obj.message != null) {
29
- w.uint32(170);
29
+ w.uint32(18);
30
30
  WakuMessage.codec().encode(obj.message, w);
31
31
  }
32
32
  if (opts.lengthDelimited !== false) {
33
33
  w.ldelim();
34
34
  }
35
35
  }, (reader, length, opts = {}) => {
36
- const obj = {};
36
+ const obj = {
37
+ pubsubTopic: ''
38
+ };
37
39
  const end = length == null ? reader.len : reader.pos + length;
38
40
  while (reader.pos < end) {
39
41
  const tag = reader.uint32();
40
42
  switch (tag >>> 3) {
41
- case 20: {
43
+ case 1: {
42
44
  obj.pubsubTopic = reader.string();
43
45
  break;
44
46
  }
45
- case 21: {
47
+ case 2: {
46
48
  obj.message = WakuMessage.codec().decode(reader, reader.uint32(), {
47
49
  limits: opts.limits?.message
48
50
  });
@@ -75,39 +77,31 @@ var PushResponse;
75
77
  if (opts.lengthDelimited !== false) {
76
78
  w.fork();
77
79
  }
78
- if ((obj.statusCode != null && obj.statusCode !== 0)) {
79
- w.uint32(160);
80
- w.uint32(obj.statusCode);
81
- }
82
- if (obj.statusDesc != null) {
83
- w.uint32(242);
84
- w.string(obj.statusDesc);
80
+ if ((obj.isSuccess != null && obj.isSuccess !== false)) {
81
+ w.uint32(8);
82
+ w.bool(obj.isSuccess);
85
83
  }
86
- if (obj.relayPeerCount != null) {
87
- w.uint32(320);
88
- w.uint32(obj.relayPeerCount);
84
+ if (obj.info != null) {
85
+ w.uint32(18);
86
+ w.string(obj.info);
89
87
  }
90
88
  if (opts.lengthDelimited !== false) {
91
89
  w.ldelim();
92
90
  }
93
91
  }, (reader, length, opts = {}) => {
94
92
  const obj = {
95
- statusCode: 0
93
+ isSuccess: false
96
94
  };
97
95
  const end = length == null ? reader.len : reader.pos + length;
98
96
  while (reader.pos < end) {
99
97
  const tag = reader.uint32();
100
98
  switch (tag >>> 3) {
101
- case 20: {
102
- obj.statusCode = reader.uint32();
103
- break;
104
- }
105
- case 30: {
106
- obj.statusDesc = reader.string();
99
+ case 1: {
100
+ obj.isSuccess = reader.bool();
107
101
  break;
108
102
  }
109
- case 40: {
110
- obj.relayPeerCount = reader.uint32();
103
+ case 2: {
104
+ obj.info = reader.string();
111
105
  break;
112
106
  }
113
107
  default: {
@@ -128,7 +122,7 @@ var PushResponse;
128
122
  return decodeMessage(buf, PushResponse.codec(), opts);
129
123
  };
130
124
  })(PushResponse || (PushResponse = {}));
131
- var PushRpc;
125
+ var PushRpc$1;
132
126
  (function (PushRpc) {
133
127
  let _codec;
134
128
  PushRpc.codec = () => {
@@ -193,7 +187,7 @@ var PushRpc;
193
187
  PushRpc.decode = (buf, opts) => {
194
188
  return decodeMessage(buf, PushRpc.codec(), opts);
195
189
  };
196
- })(PushRpc || (PushRpc = {}));
190
+ })(PushRpc$1 || (PushRpc$1 = {}));
197
191
  var RateLimitProof;
198
192
  (function (RateLimitProof) {
199
193
  let _codec;
@@ -392,4 +386,4 @@ var WakuMessage;
392
386
  };
393
387
  })(WakuMessage || (WakuMessage = {}));
394
388
 
395
- export { PushRequest, PushResponse, PushRpc, RateLimitProof, WakuMessage };
389
+ export { PushRequest, PushResponse, PushRpc$1 as PushRpc, RateLimitProof, WakuMessage };
@@ -1,4 +1,3 @@
1
- import '../../interfaces/dist/light_push_v3.js';
2
1
  import '../../interfaces/dist/protocols.js';
3
2
  import '../../interfaces/dist/connection_manager.js';
4
3
  import '../../interfaces/dist/health_indicator.js';
@@ -22,6 +22,12 @@ const RATE_LIMIT_PARAMS = {
22
22
  MAX_TOTAL_RATE: 160_000, // Maximum total rate limit across all memberships
23
23
  EPOCH_LENGTH: 600 // Epoch length in seconds (10 minutes)
24
24
  };
25
+ /**
26
+ * Default Q value for the RLN contract
27
+ * This is the upper bound for the ID commitment
28
+ * @see https://github.com/waku-org/specs/blob/master/standards/core/rln-contract.md#implementation-suggestions
29
+ */
30
+ const DEFAULT_Q = BigInt("21888242871839275222246405745257275088548364400416034343698204186575808495617");
25
31
  const DEFAULT_RATE_LIMIT = RATE_LIMIT_PARAMS.MAX_RATE;
26
32
 
27
- export { DEFAULT_RATE_LIMIT, LINEA_CONTRACT, RATE_LIMIT_PARAMS, RATE_LIMIT_TIERS };
33
+ export { DEFAULT_Q, DEFAULT_RATE_LIMIT, LINEA_CONTRACT, RATE_LIMIT_PARAMS, RATE_LIMIT_TIERS };
@@ -1,4 +1,3 @@
1
- import '../../../interfaces/dist/light_push_v3.js';
2
1
  import '../../../interfaces/dist/protocols.js';
3
2
  import '../../../interfaces/dist/connection_manager.js';
4
3
  import '../../../interfaces/dist/health_indicator.js';
@@ -14,6 +13,7 @@ import '../../../../node_modules/multiformats/dist/src/bases/base8.js';
14
13
  import '../../../../node_modules/multiformats/dist/src/bases/identity.js';
15
14
  import '../../../../node_modules/multiformats/dist/src/codecs/json.js';
16
15
  import { Logger } from '../../../utils/dist/logger/index.js';
16
+ import { IdentityCredential } from '../identity.js';
17
17
  import { RLN_ABI } from './abi.js';
18
18
  import { DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS } from './constants.js';
19
19
  import { MembershipState } from './types.js';
@@ -67,7 +67,8 @@ class RLNBaseContract {
67
67
  const instance = new RLNBaseContract(options);
68
68
  const [min, max] = await Promise.all([
69
69
  instance.contract.minMembershipRateLimit(),
70
- instance.contract.maxMembershipRateLimit()
70
+ instance.contract.maxMembershipRateLimit(),
71
+ instance.contract.Q()
71
72
  ]);
72
73
  instance.minRateLimit = BigNumber.from(min).toNumber();
73
74
  instance.maxRateLimit = BigNumber.from(max).toNumber();
@@ -341,8 +342,9 @@ class RLNBaseContract {
341
342
  async registerWithIdentity(identity) {
342
343
  try {
343
344
  log.info(`Registering identity with rate limit: ${this.rateLimit} messages/epoch`);
345
+ const idCommitmentBigInt = IdentityCredential.getIdCommitmentBigInt(identity.IDCommitment);
344
346
  // Check if the ID commitment is already registered
345
- const existingIndex = await this.getMemberIndex(identity.IDCommitmentBigInt);
347
+ const existingIndex = await this.getMemberIndex(idCommitmentBigInt);
346
348
  if (existingIndex) {
347
349
  throw new Error(`ID commitment is already registered with index ${existingIndex}`);
348
350
  }
@@ -351,9 +353,11 @@ class RLNBaseContract {
351
353
  if (remainingRateLimit < this.rateLimit) {
352
354
  throw new Error(`Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}`);
353
355
  }
354
- const estimatedGas = await this.contract.estimateGas.register(identity.IDCommitmentBigInt, this.rateLimit, []);
356
+ const estimatedGas = await this.contract.estimateGas.register(idCommitmentBigInt, this.rateLimit, []);
355
357
  const gasLimit = estimatedGas.add(10000);
356
- const txRegisterResponse = await this.contract.register(identity.IDCommitmentBigInt, this.rateLimit, [], { gasLimit });
358
+ const txRegisterResponse = await this.contract.register(idCommitmentBigInt, this.rateLimit, [], {
359
+ gasLimit
360
+ });
357
361
  const txRegisterReceipt = await txRegisterResponse.wait();
358
362
  if (txRegisterReceipt.status === 0) {
359
363
  throw new Error("Transaction failed on-chain");
@@ -415,7 +419,7 @@ class RLNBaseContract {
415
419
  async registerWithPermitAndErase(identity, permit, idCommitmentsToErase) {
416
420
  try {
417
421
  log.info(`Registering identity with permit and rate limit: ${this.rateLimit} messages/epoch`);
418
- const txRegisterResponse = await this.contract.registerWithPermit(permit.owner, permit.deadline, permit.v, permit.r, permit.s, identity.IDCommitmentBigInt, this.rateLimit, idCommitmentsToErase.map((id) => BigNumber.from(id)));
422
+ const txRegisterResponse = await this.contract.registerWithPermit(permit.owner, permit.deadline, permit.v, permit.r, permit.s, IdentityCredential.getIdCommitmentBigInt(identity.IDCommitment), this.rateLimit, idCommitmentsToErase.map((id) => BigNumber.from(id)));
419
423
  const txRegisterReceipt = await txRegisterResponse.wait();
420
424
  const memberRegistered = txRegisterReceipt.events?.find((event) => event.event === "MembershipRegistered");
421
425
  if (!memberRegistered || !memberRegistered.args) {
@@ -1,4 +1,3 @@
1
- import '../../../interfaces/dist/light_push_v3.js';
2
1
  import '../../../interfaces/dist/protocols.js';
3
2
  import '../../../interfaces/dist/connection_manager.js';
4
3
  import '../../../interfaces/dist/health_indicator.js';
@@ -1,6 +1,5 @@
1
1
  import { hmac } from '../../../node_modules/@noble/hashes/esm/hmac.js';
2
- import { sha256 } from '../../../node_modules/@noble/hashes/esm/sha256.js';
3
- import '../../interfaces/dist/light_push_v3.js';
2
+ import { sha256 } from '../../../node_modules/@noble/hashes/esm/sha2.js';
4
3
  import '../../interfaces/dist/protocols.js';
5
4
  import '../../interfaces/dist/connection_manager.js';
6
5
  import '../../interfaces/dist/health_indicator.js';
@@ -21,7 +20,7 @@ import { RLNBaseContract } from './contract/rln_base_contract.js';
21
20
  import { IdentityCredential } from './identity.js';
22
21
  import { Keystore } from './keystore/keystore.js';
23
22
  import { extractMetaMaskSigner } from './utils/metamask.js';
24
- import { buildBigIntFromUint8Array } from './utils/bytes.js';
23
+ import { switchEndianness } from './utils/bytes.js';
25
24
  import './utils/epoch.js';
26
25
 
27
26
  const log = new Logger("waku:credentials");
@@ -96,7 +95,7 @@ class RLNCredentialsManager {
96
95
  }
97
96
  else {
98
97
  log.info("Using local implementation to generate identity");
99
- identity = this.generateSeededIdentityCredential(options.signature);
98
+ identity = await this.generateSeededIdentityCredential(options.signature);
100
99
  }
101
100
  }
102
101
  if (!identity) {
@@ -192,24 +191,26 @@ class RLNCredentialsManager {
192
191
  * @param seed A string seed to generate the identity from
193
192
  * @returns IdentityCredential
194
193
  */
195
- generateSeededIdentityCredential(seed) {
194
+ async generateSeededIdentityCredential(seed) {
196
195
  log.info("Generating seeded identity credential");
197
196
  // Convert the seed to bytes
198
197
  const encoder = new TextEncoder();
199
198
  const seedBytes = encoder.encode(seed);
200
199
  // Generate deterministic values using HMAC-SHA256
201
200
  // We use different context strings for each component to ensure they're different
202
- const idTrapdoor = hmac(sha256, seedBytes, encoder.encode("IDTrapdoor"));
203
- const idNullifier = hmac(sha256, seedBytes, encoder.encode("IDNullifier"));
204
- // Generate IDSecretHash as a hash of IDTrapdoor and IDNullifier
205
- const combinedBytes = new Uint8Array([...idTrapdoor, ...idNullifier]);
206
- const idSecretHash = sha256(combinedBytes);
207
- // Generate IDCommitment as a hash of IDSecretHash
208
- const idCommitment = sha256(idSecretHash);
209
- // Convert IDCommitment to BigInt
210
- const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment);
201
+ const idTrapdoorBE = hmac(sha256, seedBytes, encoder.encode("IDTrapdoor"));
202
+ const idNullifierBE = hmac(sha256, seedBytes, encoder.encode("IDNullifier"));
203
+ const combinedBytes = new Uint8Array([...idTrapdoorBE, ...idNullifierBE]);
204
+ const idSecretHashBE = sha256(combinedBytes);
205
+ const idCommitmentBE = sha256(idSecretHashBE);
206
+ // All hashing functions return big-endian bytes
207
+ // We need to switch to little-endian for the identity credential
208
+ const idTrapdoorLE = switchEndianness(idTrapdoorBE);
209
+ const idNullifierLE = switchEndianness(idNullifierBE);
210
+ const idSecretHashLE = switchEndianness(idSecretHashBE);
211
+ const idCommitmentLE = switchEndianness(idCommitmentBE);
211
212
  log.info("Successfully generated identity credential");
212
- return new IdentityCredential(idTrapdoor, idNullifier, idSecretHash, idCommitment, idCommitmentBigInt);
213
+ return new IdentityCredential(idTrapdoorLE, idNullifierLE, idSecretHashLE, idCommitmentLE);
213
214
  }
214
215
  }
215
216
 
@@ -1,18 +1,35 @@
1
- import { buildBigIntFromUint8Array } from './utils/bytes.js';
2
- import './utils/epoch.js';
1
+ import '../../interfaces/dist/protocols.js';
2
+ import '../../interfaces/dist/connection_manager.js';
3
+ import '../../interfaces/dist/health_indicator.js';
4
+ import '../../../node_modules/multiformats/dist/src/bases/base10.js';
5
+ import '../../../node_modules/multiformats/dist/src/bases/base16.js';
6
+ import '../../../node_modules/multiformats/dist/src/bases/base2.js';
7
+ import '../../../node_modules/multiformats/dist/src/bases/base256emoji.js';
8
+ import '../../../node_modules/multiformats/dist/src/bases/base32.js';
9
+ import '../../../node_modules/multiformats/dist/src/bases/base36.js';
10
+ import '../../../node_modules/multiformats/dist/src/bases/base58.js';
11
+ import '../../../node_modules/multiformats/dist/src/bases/base64.js';
12
+ import '../../../node_modules/multiformats/dist/src/bases/base8.js';
13
+ import '../../../node_modules/multiformats/dist/src/bases/identity.js';
14
+ import '../../../node_modules/multiformats/dist/src/codecs/json.js';
15
+ import { Logger } from '../../utils/dist/logger/index.js';
16
+ import { DEFAULT_Q } from './contract/constants.js';
17
+ import { buildBigIntFromUint8ArrayLE, switchEndiannessBigInt } from './utils/bytes.js';
3
18
 
19
+ const log = new Logger("waku:rln:identity");
4
20
  class IdentityCredential {
5
21
  IDTrapdoor;
6
22
  IDNullifier;
7
23
  IDSecretHash;
8
24
  IDCommitment;
9
- IDCommitmentBigInt;
10
- constructor(IDTrapdoor, IDNullifier, IDSecretHash, IDCommitment, IDCommitmentBigInt) {
25
+ /**
26
+ * All variables are in little-endian format
27
+ */
28
+ constructor(IDTrapdoor, IDNullifier, IDSecretHash, IDCommitment) {
11
29
  this.IDTrapdoor = IDTrapdoor;
12
30
  this.IDNullifier = IDNullifier;
13
31
  this.IDSecretHash = IDSecretHash;
14
32
  this.IDCommitment = IDCommitment;
15
- this.IDCommitmentBigInt = IDCommitmentBigInt;
16
33
  }
17
34
  static fromBytes(memKeys) {
18
35
  if (memKeys.length < 128) {
@@ -22,8 +39,24 @@ class IdentityCredential {
22
39
  const idNullifier = memKeys.subarray(32, 64);
23
40
  const idSecretHash = memKeys.subarray(64, 96);
24
41
  const idCommitment = memKeys.subarray(96, 128);
25
- const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment, 32);
26
- return new IdentityCredential(idTrapdoor, idNullifier, idSecretHash, idCommitment, idCommitmentBigInt);
42
+ return new IdentityCredential(idTrapdoor, idNullifier, idSecretHash, idCommitment);
43
+ }
44
+ /**
45
+ * Converts an ID commitment from bytes to a BigInt, normalizing it against a limit if needed
46
+ * @param bytes The ID commitment bytes to convert
47
+ * @param limit Optional limit to normalize against (Q value)
48
+ * @returns The ID commitment as a BigInt
49
+ */
50
+ static getIdCommitmentBigInt(idCommitment, returnType = "big-endian", limit = DEFAULT_Q) {
51
+ let idCommitmentBigIntLE = buildBigIntFromUint8ArrayLE(idCommitment);
52
+ if (limit && idCommitmentBigIntLE >= limit) {
53
+ log.warn(`ID commitment is greater than Q, reducing it by Q: ${idCommitmentBigIntLE} % ${limit}`);
54
+ idCommitmentBigIntLE = idCommitmentBigIntLE % limit;
55
+ }
56
+ if (returnType === "big-endian") {
57
+ return switchEndiannessBigInt(idCommitmentBigIntLE);
58
+ }
59
+ return idCommitmentBigIntLE;
27
60
  }
28
61
  }
29
62
 
@@ -1,5 +1,4 @@
1
1
  import '../../../../node_modules/@chainsafe/bls-keystore/lib/index.js';
2
- import '../../../interfaces/dist/light_push_v3.js';
3
2
  import '../../../interfaces/dist/protocols.js';
4
3
  import '../../../interfaces/dist/connection_manager.js';
5
4
  import '../../../interfaces/dist/health_indicator.js';
@@ -18,7 +17,6 @@ import { Logger } from '../../../utils/dist/logger/index.js';
18
17
  import { sha256 } from '../../../../node_modules/ethereum-cryptography/esm/sha256.js';
19
18
  import { bytesToUtf8 } from '../../../../node_modules/ethereum-cryptography/esm/utils.js';
20
19
  import _ from '../../../../node_modules/lodash/lodash.js';
21
- import { buildBigIntFromUint8Array } from '../utils/bytes.js';
22
20
  import { keccak256Checksum, decryptEipKeystore } from './cipher.js';
23
21
  import { isKeystoreValid, isCredentialValid } from './schema_validator.js';
24
22
  import { __exports as lib } from '../../../../_virtual/index.js';
@@ -165,14 +163,16 @@ class Keystore {
165
163
  try {
166
164
  const str = bytesToUtf8(bytes);
167
165
  const obj = JSON.parse(str);
168
- // TODO: add runtime validation of nwaku credentials
166
+ const idCommitmentLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idCommitment", []));
167
+ const idTrapdoorLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idTrapdoor", []));
168
+ const idNullifierLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idNullifier", []));
169
+ const idSecretHashLE = Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idSecretHash", []));
169
170
  return {
170
171
  identity: {
171
- IDCommitment: Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idCommitment", [])),
172
- IDTrapdoor: Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idTrapdoor", [])),
173
- IDNullifier: Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idNullifier", [])),
174
- IDCommitmentBigInt: buildBigIntFromUint8Array(Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idCommitment", []))),
175
- IDSecretHash: Keystore.fromArraylikeToBytes(_.get(obj, "identityCredential.idSecretHash", []))
172
+ IDCommitment: idCommitmentLE,
173
+ IDTrapdoor: idTrapdoorLE,
174
+ IDNullifier: idNullifierLE,
175
+ IDSecretHash: idSecretHashLE
176
176
  },
177
177
  membership: {
178
178
  treeIndex: _.get(obj, "treeIndex"),
@@ -209,13 +209,16 @@ class Keystore {
209
209
  // follows nwaku implementation
210
210
  // https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L98
211
211
  static fromIdentityToBytes(options) {
212
+ function toLittleEndian(bytes) {
213
+ return new Uint8Array(bytes).reverse();
214
+ }
212
215
  return utf8ToBytes(JSON.stringify({
213
216
  treeIndex: options.membership.treeIndex,
214
217
  identityCredential: {
215
- idCommitment: Array.from(options.identity.IDCommitment),
216
- idNullifier: Array.from(options.identity.IDNullifier),
217
- idSecretHash: Array.from(options.identity.IDSecretHash),
218
- idTrapdoor: Array.from(options.identity.IDTrapdoor)
218
+ idCommitment: Array.from(toLittleEndian(options.identity.IDCommitment)),
219
+ idNullifier: Array.from(toLittleEndian(options.identity.IDNullifier)),
220
+ idSecretHash: Array.from(toLittleEndian(options.identity.IDSecretHash)),
221
+ idTrapdoor: Array.from(toLittleEndian(options.identity.IDTrapdoor))
219
222
  },
220
223
  membershipContract: {
221
224
  chainId: options.membership.chainId,
@@ -1,23 +1,8 @@
1
1
  import { Version } from '../../core/dist/lib/message/version_0.js';
2
2
  import '../../core/dist/lib/filter/filter.js';
3
3
  import '../../core/dist/lib/light_push/light_push.js';
4
- import '../../core/dist/lib/light_push/light_push_v3.js';
5
- import '../../proto/dist/generated/message.js';
6
- import '../../proto/dist/generated/filter.js';
7
- import '../../proto/dist/generated/topic_only_message.js';
8
- import '../../proto/dist/generated/filter_v2.js';
9
- import '../../proto/dist/generated/light_push.js';
10
- import '../../proto/dist/generated/light_push_v2.js';
11
- import '../../proto/dist/generated/light_push_v3.js';
12
- import '../../proto/dist/generated/store_v3.js';
13
- import '../../proto/dist/generated/peer_exchange.js';
14
- import '../../proto/dist/generated/metadata.js';
15
- import '../../proto/dist/generated/sds_message.js';
16
- import '../../core/dist/lib/light_push/status_codes_v3.js';
17
- import '../../core/dist/lib/light_push/status_codes.js';
18
4
  import '../../core/dist/lib/store/store.js';
19
5
  import '../../core/dist/lib/connection_manager/connection_manager.js';
20
- import '../../interfaces/dist/light_push_v3.js';
21
6
  import '../../interfaces/dist/protocols.js';
22
7
  import '../../interfaces/dist/connection_manager.js';
23
8
  import '../../interfaces/dist/health_indicator.js';
@@ -1,23 +1,8 @@
1
1
  import { createEncoder, createDecoder } from '../../core/dist/lib/message/version_0.js';
2
2
  import '../../core/dist/lib/filter/filter.js';
3
3
  import '../../core/dist/lib/light_push/light_push.js';
4
- import '../../core/dist/lib/light_push/light_push_v3.js';
5
- import '../../proto/dist/generated/message.js';
6
- import '../../proto/dist/generated/filter.js';
7
- import '../../proto/dist/generated/topic_only_message.js';
8
- import '../../proto/dist/generated/filter_v2.js';
9
- import '../../proto/dist/generated/light_push.js';
10
- import '../../proto/dist/generated/light_push_v2.js';
11
- import '../../proto/dist/generated/light_push_v3.js';
12
- import '../../proto/dist/generated/store_v3.js';
13
- import '../../proto/dist/generated/peer_exchange.js';
14
- import '../../proto/dist/generated/metadata.js';
15
- import '../../proto/dist/generated/sds_message.js';
16
- import '../../core/dist/lib/light_push/status_codes_v3.js';
17
- import '../../core/dist/lib/light_push/status_codes.js';
18
4
  import '../../core/dist/lib/store/store.js';
19
5
  import '../../core/dist/lib/connection_manager/connection_manager.js';
20
- import '../../interfaces/dist/light_push_v3.js';
21
6
  import '../../interfaces/dist/protocols.js';
22
7
  import '../../interfaces/dist/connection_manager.js';
23
8
  import '../../interfaces/dist/health_indicator.js';
@@ -16,12 +16,35 @@ function concatenate(...input) {
16
16
  }
17
17
  return result;
18
18
  }
19
- // Adapted from https://github.com/feross/buffer
20
- function checkInt(buf, value, offset, ext, max, min) {
21
- if (value > max || value < min)
22
- throw new RangeError('"value" argument is out of bounds');
23
- if (offset + ext > buf.length)
24
- throw new RangeError("Index out of range");
19
+ function switchEndianness(bytes) {
20
+ return new Uint8Array(bytes.reverse());
21
+ }
22
+ /**
23
+ * Builds a BigInt from a little-endian Uint8Array
24
+ * @param bytes The little-endian bytes to convert
25
+ * @returns The resulting BigInt in little-endian format
26
+ */
27
+ function buildBigIntFromUint8ArrayLE(bytes) {
28
+ let result = 0n;
29
+ for (let i = bytes.length - 1; i >= 0; i--) {
30
+ result = (result << 8n) + BigInt(bytes[i]);
31
+ }
32
+ return result;
33
+ }
34
+ /**
35
+ * Switches endianness of a bigint value
36
+ * @param value The bigint value to switch endianness for
37
+ * @returns The bigint value with reversed endianness
38
+ */
39
+ function switchEndiannessBigInt(value) {
40
+ // Convert bigint to byte array
41
+ const bytes = [];
42
+ while (value > 0n) {
43
+ bytes.push(Number(value & 0xffn));
44
+ value >>= 8n;
45
+ }
46
+ // Reverse bytes and convert back to bigint
47
+ return bytes.reverse().reduce((acc, byte) => (acc << 8n) + BigInt(byte), 0n);
25
48
  }
26
49
  function writeUIntLE(buf, value, offset, byteLength, noAssert) {
27
50
  value = +value;
@@ -39,15 +62,6 @@ function writeUIntLE(buf, value, offset, byteLength, noAssert) {
39
62
  }
40
63
  return buf;
41
64
  }
42
- /**
43
- * Transforms Uint8Array into BigInt
44
- * @param array: Uint8Array
45
- * @returns BigInt
46
- */
47
- function buildBigIntFromUint8Array(array, byteOffset = 0) {
48
- const dataView = new DataView(array.buffer);
49
- return dataView.getBigUint64(byteOffset, true);
50
- }
51
65
  /**
52
66
  * Fills with zeros to set length
53
67
  * @param array little endian Uint8Array
@@ -61,5 +75,12 @@ function zeroPadLE(array, length) {
61
75
  }
62
76
  return result;
63
77
  }
78
+ // Adapted from https://github.com/feross/buffer
79
+ function checkInt(buf, value, offset, ext, max, min) {
80
+ if (value > max || value < min)
81
+ throw new RangeError('"value" argument is out of bounds');
82
+ if (offset + ext > buf.length)
83
+ throw new RangeError("Index out of range");
84
+ }
64
85
 
65
- export { buildBigIntFromUint8Array, concatenate, writeUIntLE, zeroPadLE };
86
+ export { buildBigIntFromUint8ArrayLE, concatenate, switchEndianness, switchEndiannessBigInt, writeUIntLE, zeroPadLE };
@@ -1,4 +1,3 @@
1
- import '../../../interfaces/dist/light_push_v3.js';
2
1
  import '../../../interfaces/dist/protocols.js';
3
2
  import '../../../interfaces/dist/connection_manager.js';
4
3
  import '../../../interfaces/dist/health_indicator.js';
@@ -1,5 +1,4 @@
1
1
  import { sha256 } from '../../../../../node_modules/@noble/hashes/esm/sha256.js';
2
- import '../../../../interfaces/dist/light_push_v3.js';
3
2
  import '../../../../interfaces/dist/protocols.js';
4
3
  import '../../../../interfaces/dist/connection_manager.js';
5
4
  import { DEFAULT_CLUSTER_ID } from '../../../../interfaces/dist/constants.js';