@waku/rln 0.1.6-f7c290d.0 → 0.1.6

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 (105) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/bundle/_virtual/utils.js +2 -2
  3. package/bundle/_virtual/utils2.js +2 -2
  4. package/bundle/index.js +1 -1
  5. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/_sha2.js +1 -1
  6. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/hmac.js +1 -1
  7. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/pbkdf2.js +1 -1
  8. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/scrypt.js +1 -1
  9. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/sha256.js +1 -1
  10. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/sha512.js +1 -1
  11. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/utils.js +1 -1
  12. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +1 -1
  13. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +2 -2
  14. package/bundle/node_modules/@chainsafe/is-ip/lib/is-ip.js +12 -0
  15. package/bundle/node_modules/@chainsafe/is-ip/lib/parse.js +26 -0
  16. package/bundle/node_modules/@chainsafe/is-ip/lib/parser.js +202 -0
  17. package/bundle/node_modules/@ethersproject/bignumber/lib.esm/bignumber.js +1 -1
  18. package/bundle/node_modules/@multiformats/multiaddr/dist/src/constants.js +43 -0
  19. package/bundle/node_modules/@multiformats/multiaddr/dist/src/errors.js +17 -0
  20. package/bundle/node_modules/@multiformats/multiaddr/dist/src/registry.js +245 -0
  21. package/bundle/node_modules/@multiformats/multiaddr/dist/src/utils.js +191 -0
  22. package/bundle/node_modules/@multiformats/multiaddr/dist/src/validation.js +30 -0
  23. package/bundle/node_modules/debug/src/browser.js +1 -1
  24. package/bundle/node_modules/debug/src/common.js +1 -1
  25. package/bundle/node_modules/lodash/lodash.js +5 -5
  26. package/bundle/node_modules/multiformats/dist/src/bases/base.js +12 -9
  27. package/bundle/node_modules/multiformats/dist/src/bytes.js +19 -3
  28. package/bundle/node_modules/multiformats/dist/src/cid.js +371 -0
  29. package/bundle/node_modules/multiformats/dist/src/hashes/digest.js +62 -0
  30. package/bundle/node_modules/multiformats/dist/src/varint.js +15 -0
  31. package/bundle/node_modules/multiformats/dist/src/vendor/varint.js +78 -0
  32. package/bundle/node_modules/uint8arrays/dist/src/concat.js +20 -0
  33. package/bundle/node_modules/uint8arrays/dist/src/to-string.js +19 -0
  34. package/bundle/node_modules/uint8arrays/dist/src/util/as-uint8array.js +9 -0
  35. package/bundle/packages/core/dist/lib/connection_manager/connection_manager.js +1 -3
  36. package/bundle/packages/proto/dist/generated/filter.js +2 -0
  37. package/bundle/packages/proto/dist/generated/filter_v2.js +2 -0
  38. package/bundle/packages/proto/dist/generated/light_push.js +2 -0
  39. package/bundle/packages/proto/dist/generated/message.js +2 -0
  40. package/bundle/packages/proto/dist/generated/metadata.js +2 -0
  41. package/bundle/packages/proto/dist/generated/peer_exchange.js +2 -0
  42. package/bundle/packages/proto/dist/generated/sds_message.js +2 -0
  43. package/bundle/packages/proto/dist/generated/store_v3.js +2 -0
  44. package/bundle/packages/proto/dist/generated/topic_only_message.js +2 -0
  45. package/bundle/packages/rln/dist/contract/constants.js +1 -7
  46. package/bundle/packages/rln/dist/contract/rln_base_contract.js +2 -5
  47. package/bundle/packages/rln/dist/contract/rln_contract.js +2 -2
  48. package/bundle/packages/rln/dist/credentials_manager.js +16 -24
  49. package/bundle/packages/rln/dist/identity.js +6 -8
  50. package/bundle/packages/rln/dist/keystore/keystore.js +10 -21
  51. package/bundle/packages/rln/dist/proof.js +2 -2
  52. package/bundle/packages/rln/dist/utils/bytes.js +58 -103
  53. package/bundle/packages/rln/dist/utils/hash.js +3 -3
  54. package/bundle/packages/rln/dist/zerokit.js +17 -17
  55. package/dist/.tsbuildinfo +1 -1
  56. package/dist/codec.test-utils.d.ts +1 -1
  57. package/dist/contract/constants.d.ts +0 -6
  58. package/dist/contract/constants.js +0 -6
  59. package/dist/contract/constants.js.map +1 -1
  60. package/dist/contract/rln_base_contract.js +2 -5
  61. package/dist/contract/rln_base_contract.js.map +1 -1
  62. package/dist/contract/rln_contract.js +2 -2
  63. package/dist/contract/rln_contract.js.map +1 -1
  64. package/dist/contract/test-setup.d.ts +1 -1
  65. package/dist/contract/test-utils.d.ts +39 -0
  66. package/dist/contract/test-utils.js +118 -0
  67. package/dist/contract/test-utils.js.map +1 -0
  68. package/dist/credentials_manager.d.ts +0 -4
  69. package/dist/credentials_manager.js +16 -25
  70. package/dist/credentials_manager.js.map +1 -1
  71. package/dist/identity.d.ts +2 -5
  72. package/dist/identity.js +5 -8
  73. package/dist/identity.js.map +1 -1
  74. package/dist/keystore/credential_validation_generated.d.ts +0 -2
  75. package/dist/keystore/keystore.js +10 -21
  76. package/dist/keystore/keystore.js.map +1 -1
  77. package/dist/keystore/keystore_validation_generated.d.ts +0 -2
  78. package/dist/proof.js +2 -2
  79. package/dist/proof.js.map +1 -1
  80. package/dist/utils/bytes.d.ts +20 -42
  81. package/dist/utils/bytes.js +57 -102
  82. package/dist/utils/bytes.js.map +1 -1
  83. package/dist/utils/hash.js +5 -5
  84. package/dist/utils/hash.js.map +1 -1
  85. package/dist/utils/index.d.ts +1 -1
  86. package/dist/utils/index.js +1 -1
  87. package/dist/utils/index.js.map +1 -1
  88. package/dist/zerokit.js +17 -17
  89. package/dist/zerokit.js.map +1 -1
  90. package/package.json +93 -1
  91. package/src/contract/constants.ts +0 -9
  92. package/src/contract/rln_base_contract.ts +3 -5
  93. package/src/contract/rln_contract.ts +2 -5
  94. package/src/contract/test-utils.ts +179 -0
  95. package/src/credentials_manager.ts +24 -46
  96. package/src/identity.ts +7 -11
  97. package/src/keystore/keystore.ts +22 -38
  98. package/src/proof.ts +2 -2
  99. package/src/utils/bytes.ts +72 -118
  100. package/src/utils/hash.ts +5 -15
  101. package/src/utils/index.ts +6 -1
  102. package/src/zerokit.ts +22 -30
  103. package/bundle/node_modules/@multiformats/multiaddr/dist/src/convert.js +0 -15
  104. package/bundle/node_modules/@multiformats/multiaddr/dist/src/multiaddr.js +0 -21
  105. package/bundle/node_modules/@multiformats/multiaddr/dist/src/protocols-table.js +0 -92
@@ -0,0 +1,179 @@
1
+ import { hexToBytes } from "@waku/utils/bytes";
2
+ import { expect } from "chai";
3
+ import * as ethers from "ethers";
4
+ import sinon from "sinon";
5
+
6
+ import type { IdentityCredential } from "../identity.js";
7
+
8
+ import { DEFAULT_RATE_LIMIT, LINEA_CONTRACT } from "./constants.js";
9
+
10
+ export const mockRateLimits = {
11
+ minRate: 20,
12
+ maxRate: 600,
13
+ maxTotalRate: 1200,
14
+ currentTotalRate: 500
15
+ };
16
+
17
+ type MockProvider = {
18
+ getLogs: () => never[];
19
+ getBlockNumber: () => Promise<number>;
20
+ getNetwork: () => Promise<{ chainId: number }>;
21
+ };
22
+
23
+ type MockFilters = {
24
+ MembershipRegistered: () => { address: string };
25
+ MembershipErased: () => { address: string };
26
+ MembershipExpired: () => { address: string };
27
+ };
28
+
29
+ export function createMockProvider(): MockProvider {
30
+ return {
31
+ getLogs: () => [],
32
+ getBlockNumber: () => Promise.resolve(1000),
33
+ getNetwork: () => Promise.resolve({ chainId: 11155111 })
34
+ };
35
+ }
36
+
37
+ export function createMockFilters(): MockFilters {
38
+ return {
39
+ MembershipRegistered: () => ({ address: LINEA_CONTRACT.address }),
40
+ MembershipErased: () => ({ address: LINEA_CONTRACT.address }),
41
+ MembershipExpired: () => ({ address: LINEA_CONTRACT.address })
42
+ };
43
+ }
44
+
45
+ type ContractOverrides = Partial<{
46
+ filters: Record<string, unknown>;
47
+ [key: string]: unknown;
48
+ }>;
49
+
50
+ export function createMockRegistryContract(
51
+ overrides: ContractOverrides = {}
52
+ ): ethers.Contract {
53
+ const filters = {
54
+ MembershipRegistered: () => ({ address: LINEA_CONTRACT.address }),
55
+ MembershipErased: () => ({ address: LINEA_CONTRACT.address }),
56
+ MembershipExpired: () => ({ address: LINEA_CONTRACT.address })
57
+ };
58
+
59
+ const baseContract = {
60
+ minMembershipRateLimit: () =>
61
+ Promise.resolve(ethers.BigNumber.from(mockRateLimits.minRate)),
62
+ maxMembershipRateLimit: () =>
63
+ Promise.resolve(ethers.BigNumber.from(mockRateLimits.maxRate)),
64
+ maxTotalRateLimit: () =>
65
+ Promise.resolve(ethers.BigNumber.from(mockRateLimits.maxTotalRate)),
66
+ currentTotalRateLimit: () =>
67
+ Promise.resolve(ethers.BigNumber.from(mockRateLimits.currentTotalRate)),
68
+ queryFilter: () => [],
69
+ provider: createMockProvider(),
70
+ filters,
71
+ on: () => ({}),
72
+ removeAllListeners: () => ({}),
73
+ register: () => ({
74
+ wait: () =>
75
+ Promise.resolve({
76
+ events: [mockRLNRegisteredEvent()]
77
+ })
78
+ }),
79
+ estimateGas: {
80
+ register: () => Promise.resolve(ethers.BigNumber.from(100000))
81
+ },
82
+ functions: {
83
+ register: () => Promise.resolve()
84
+ },
85
+ getMemberIndex: () => Promise.resolve(null),
86
+ interface: {
87
+ getEvent: (eventName: string) => ({
88
+ name: eventName,
89
+ format: () => {}
90
+ })
91
+ },
92
+ address: LINEA_CONTRACT.address
93
+ };
94
+
95
+ // Merge overrides while preserving filters
96
+ const merged = {
97
+ ...baseContract,
98
+ ...overrides,
99
+ filters: { ...filters, ...(overrides.filters || {}) }
100
+ };
101
+
102
+ return merged as unknown as ethers.Contract;
103
+ }
104
+
105
+ export function mockRLNRegisteredEvent(idCommitment?: string): ethers.Event {
106
+ return {
107
+ args: {
108
+ idCommitment:
109
+ idCommitment ||
110
+ "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
111
+ membershipRateLimit: ethers.BigNumber.from(DEFAULT_RATE_LIMIT),
112
+ index: ethers.BigNumber.from(1)
113
+ },
114
+ event: "MembershipRegistered"
115
+ } as unknown as ethers.Event;
116
+ }
117
+
118
+ export function formatIdCommitment(idCommitmentBigInt: bigint): string {
119
+ return "0x" + idCommitmentBigInt.toString(16).padStart(64, "0");
120
+ }
121
+
122
+ export function createRegisterStub(
123
+ identity: IdentityCredential
124
+ ): sinon.SinonStub {
125
+ return sinon.stub().callsFake(() => ({
126
+ wait: () =>
127
+ Promise.resolve({
128
+ events: [
129
+ {
130
+ event: "MembershipRegistered",
131
+ args: {
132
+ idCommitment: formatIdCommitment(identity.IDCommitmentBigInt),
133
+ membershipRateLimit: ethers.BigNumber.from(DEFAULT_RATE_LIMIT),
134
+ index: ethers.BigNumber.from(1)
135
+ }
136
+ }
137
+ ]
138
+ })
139
+ }));
140
+ }
141
+
142
+ export function verifyRegistration(
143
+ decryptedCredentials: any,
144
+ identity: IdentityCredential,
145
+ registerStub: sinon.SinonStub,
146
+ insertMemberSpy: sinon.SinonStub
147
+ ): void {
148
+ if (!decryptedCredentials) {
149
+ throw new Error("Decrypted credentials should not be undefined");
150
+ }
151
+
152
+ // Verify registration call
153
+ expect(
154
+ registerStub.calledWith(
155
+ sinon.match.same(identity.IDCommitmentBigInt),
156
+ sinon.match.same(DEFAULT_RATE_LIMIT),
157
+ sinon.match.array,
158
+ sinon.match.object
159
+ )
160
+ ).to.be.true;
161
+
162
+ // Verify credential properties
163
+ expect(decryptedCredentials).to.have.property("identity");
164
+ expect(decryptedCredentials).to.have.property("membership");
165
+ expect(decryptedCredentials.membership).to.include({
166
+ address: LINEA_CONTRACT.address,
167
+ treeIndex: 1
168
+ });
169
+
170
+ // Verify member insertion
171
+ const expectedIdCommitment = ethers.utils.zeroPad(
172
+ hexToBytes(formatIdCommitment(identity.IDCommitmentBigInt)),
173
+ 32
174
+ );
175
+ expect(insertMemberSpy.callCount).to.equal(1);
176
+ expect(insertMemberSpy.getCall(0).args[0]).to.deep.equal(
177
+ expectedIdCommitment
178
+ );
179
+ }
@@ -1,9 +1,9 @@
1
1
  import { hmac } from "@noble/hashes/hmac";
2
- import { sha256 } from "@noble/hashes/sha2";
2
+ import { sha256 } from "@noble/hashes/sha256";
3
3
  import { Logger } from "@waku/utils";
4
4
  import { ethers } from "ethers";
5
5
 
6
- import { DEFAULT_Q, LINEA_CONTRACT } from "./contract/constants.js";
6
+ import { LINEA_CONTRACT } from "./contract/constants.js";
7
7
  import { RLNBaseContract } from "./contract/rln_base_contract.js";
8
8
  import { IdentityCredential } from "./identity.js";
9
9
  import { Keystore } from "./keystore/index.js";
@@ -13,8 +13,10 @@ import type {
13
13
  } from "./keystore/index.js";
14
14
  import { KeystoreEntity, Password } from "./keystore/types.js";
15
15
  import { RegisterMembershipOptions, StartRLNOptions } from "./types.js";
16
- import { BytesUtils } from "./utils/bytes.js";
17
- import { extractMetaMaskSigner } from "./utils/index.js";
16
+ import {
17
+ buildBigIntFromUint8Array,
18
+ extractMetaMaskSigner
19
+ } from "./utils/index.js";
18
20
  import { Zerokit } from "./zerokit.js";
19
21
 
20
22
  const log = new Logger("waku:credentials");
@@ -114,9 +116,7 @@ export class RLNCredentialsManager {
114
116
  );
115
117
  } else {
116
118
  log.info("Using local implementation to generate identity");
117
- identity = await this.generateSeededIdentityCredential(
118
- options.signature
119
- );
119
+ identity = this.generateSeededIdentityCredential(options.signature);
120
120
  }
121
121
  }
122
122
 
@@ -249,9 +249,7 @@ export class RLNCredentialsManager {
249
249
  * @param seed A string seed to generate the identity from
250
250
  * @returns IdentityCredential
251
251
  */
252
- private async generateSeededIdentityCredential(
253
- seed: string
254
- ): Promise<IdentityCredential> {
252
+ private generateSeededIdentityCredential(seed: string): IdentityCredential {
255
253
  log.info("Generating seeded identity credential");
256
254
  // Convert the seed to bytes
257
255
  const encoder = new TextEncoder();
@@ -259,46 +257,26 @@ export class RLNCredentialsManager {
259
257
 
260
258
  // Generate deterministic values using HMAC-SHA256
261
259
  // We use different context strings for each component to ensure they're different
262
- const idTrapdoorBE = hmac(sha256, seedBytes, encoder.encode("IDTrapdoor"));
263
- const idNullifierBE = hmac(
264
- sha256,
265
- seedBytes,
266
- encoder.encode("IDNullifier")
267
- );
260
+ const idTrapdoor = hmac(sha256, seedBytes, encoder.encode("IDTrapdoor"));
261
+ const idNullifier = hmac(sha256, seedBytes, encoder.encode("IDNullifier"));
268
262
 
269
- const combinedBytes = new Uint8Array([...idTrapdoorBE, ...idNullifierBE]);
270
- const idSecretHashBE = sha256(combinedBytes);
263
+ // Generate IDSecretHash as a hash of IDTrapdoor and IDNullifier
264
+ const combinedBytes = new Uint8Array([...idTrapdoor, ...idNullifier]);
265
+ const idSecretHash = sha256(combinedBytes);
271
266
 
272
- const idCommitmentRawBE = sha256(idSecretHashBE);
273
- const idCommitmentBE = this.reduceIdCommitment(idCommitmentRawBE);
267
+ // Generate IDCommitment as a hash of IDSecretHash
268
+ const idCommitment = sha256(idSecretHash);
274
269
 
275
- log.info(
276
- "Successfully generated identity credential, storing in Big Endian format"
277
- );
270
+ // Convert IDCommitment to BigInt
271
+ const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment);
272
+
273
+ log.info("Successfully generated identity credential");
278
274
  return new IdentityCredential(
279
- idTrapdoorBE,
280
- idNullifierBE,
281
- idSecretHashBE,
282
- idCommitmentBE
275
+ idTrapdoor,
276
+ idNullifier,
277
+ idSecretHash,
278
+ idCommitment,
279
+ idCommitmentBigInt
283
280
  );
284
281
  }
285
-
286
- /**
287
- * Helper: take 32-byte BE, reduce mod Q, return 32-byte BE
288
- */
289
- private reduceIdCommitment(
290
- bytesBE: Uint8Array,
291
- limit: bigint = DEFAULT_Q
292
- ): Uint8Array {
293
- const nBE = BytesUtils.buildBigIntFromUint8ArrayBE(bytesBE);
294
-
295
- if (nBE >= limit) {
296
- log.warn(
297
- `ID commitment is greater than Q, reducing it by Q: ${nBE} % ${limit}`
298
- );
299
- return BytesUtils.bigIntToUint8Array32BE(nBE % limit);
300
- }
301
-
302
- return bytesBE;
303
- }
304
282
  }
package/src/identity.ts CHANGED
@@ -1,19 +1,13 @@
1
- import { BytesUtils } from "./utils/bytes.js";
1
+ import { buildBigIntFromUint8Array } from "./utils/index.js";
2
2
 
3
3
  export class IdentityCredential {
4
- public IDCommitmentBigInt: bigint;
5
- /**
6
- * All variables are in little-endian format
7
- */
8
4
  public constructor(
9
5
  public readonly IDTrapdoor: Uint8Array,
10
6
  public readonly IDNullifier: Uint8Array,
11
7
  public readonly IDSecretHash: Uint8Array,
12
- public readonly IDCommitment: Uint8Array
13
- ) {
14
- this.IDCommitmentBigInt =
15
- BytesUtils.buildBigIntFromUint8ArrayBE(IDCommitment);
16
- }
8
+ public readonly IDCommitment: Uint8Array,
9
+ public readonly IDCommitmentBigInt: bigint
10
+ ) {}
17
11
 
18
12
  public static fromBytes(memKeys: Uint8Array): IdentityCredential {
19
13
  if (memKeys.length < 128) {
@@ -24,12 +18,14 @@ export class IdentityCredential {
24
18
  const idNullifier = memKeys.subarray(32, 64);
25
19
  const idSecretHash = memKeys.subarray(64, 96);
26
20
  const idCommitment = memKeys.subarray(96, 128);
21
+ const idCommitmentBigInt = buildBigIntFromUint8Array(idCommitment, 32);
27
22
 
28
23
  return new IdentityCredential(
29
24
  idTrapdoor,
30
25
  idNullifier,
31
26
  idSecretHash,
32
- idCommitment
27
+ idCommitment,
28
+ idCommitmentBigInt
33
29
  );
34
30
  }
35
31
  }
@@ -14,7 +14,7 @@ import {
14
14
  import _ from "lodash";
15
15
  import { v4 as uuidV4 } from "uuid";
16
16
 
17
- import { BytesUtils } from "../utils/bytes.js";
17
+ import { buildBigIntFromUint8Array } from "../utils/bytes.js";
18
18
 
19
19
  import { decryptEipKeystore, keccak256Checksum } from "./cipher.js";
20
20
  import { isCredentialValid, isKeystoreValid } from "./schema_validator.js";
@@ -250,35 +250,26 @@ export class Keystore {
250
250
  const str = bytesToUtf8(bytes);
251
251
  const obj = JSON.parse(str);
252
252
 
253
- // Little Endian
254
- const idCommitmentLE = Keystore.fromArraylikeToBytes(
255
- _.get(obj, "identityCredential.idCommitment", [])
256
- );
257
- const idTrapdoorLE = Keystore.fromArraylikeToBytes(
258
- _.get(obj, "identityCredential.idTrapdoor", [])
259
- );
260
- const idNullifierLE = Keystore.fromArraylikeToBytes(
261
- _.get(obj, "identityCredential.idNullifier", [])
262
- );
263
- const idSecretHashLE = Keystore.fromArraylikeToBytes(
264
- _.get(obj, "identityCredential.idSecretHash", [])
265
- );
266
-
267
- // Big Endian
268
- const idCommitmentBE = BytesUtils.switchEndianness(idCommitmentLE);
269
- const idTrapdoorBE = BytesUtils.switchEndianness(idTrapdoorLE);
270
- const idNullifierBE = BytesUtils.switchEndianness(idNullifierLE);
271
- const idSecretHashBE = BytesUtils.switchEndianness(idSecretHashLE);
272
- const idCommitmentBigInt =
273
- BytesUtils.buildBigIntFromUint8ArrayBE(idCommitmentBE);
274
-
253
+ // TODO: add runtime validation of nwaku credentials
275
254
  return {
276
255
  identity: {
277
- IDCommitment: idCommitmentBE,
278
- IDTrapdoor: idTrapdoorBE,
279
- IDNullifier: idNullifierBE,
280
- IDSecretHash: idSecretHashBE,
281
- IDCommitmentBigInt: idCommitmentBigInt
256
+ IDCommitment: Keystore.fromArraylikeToBytes(
257
+ _.get(obj, "identityCredential.idCommitment", [])
258
+ ),
259
+ IDTrapdoor: Keystore.fromArraylikeToBytes(
260
+ _.get(obj, "identityCredential.idTrapdoor", [])
261
+ ),
262
+ IDNullifier: Keystore.fromArraylikeToBytes(
263
+ _.get(obj, "identityCredential.idNullifier", [])
264
+ ),
265
+ IDCommitmentBigInt: buildBigIntFromUint8Array(
266
+ Keystore.fromArraylikeToBytes(
267
+ _.get(obj, "identityCredential.idCommitment", [])
268
+ )
269
+ ),
270
+ IDSecretHash: Keystore.fromArraylikeToBytes(
271
+ _.get(obj, "identityCredential.idSecretHash", [])
272
+ )
282
273
  },
283
274
  membership: {
284
275
  treeIndex: _.get(obj, "treeIndex"),
@@ -329,21 +320,14 @@ export class Keystore {
329
320
 
330
321
  // follows nwaku implementation
331
322
  // https://github.com/waku-org/nwaku/blob/f05528d4be3d3c876a8b07f9bb7dfaae8aa8ec6e/waku/waku_keystore/protocol_types.nim#L98
332
- // IdentityCredential is stored in Big Endian format => switch to Little Endian
333
323
  private static fromIdentityToBytes(options: KeystoreEntity): Uint8Array {
334
324
  return utf8ToBytes(
335
325
  JSON.stringify({
336
326
  treeIndex: options.membership.treeIndex,
337
327
  identityCredential: {
338
- idCommitment: Array.from(
339
- BytesUtils.switchEndianness(options.identity.IDCommitment)
340
- ),
341
- idNullifier: Array.from(
342
- BytesUtils.switchEndianness(options.identity.IDNullifier)
343
- ),
344
- idSecretHash: Array.from(
345
- BytesUtils.switchEndianness(options.identity.IDSecretHash)
346
- ),
328
+ idCommitment: Array.from(options.identity.IDCommitment),
329
+ idNullifier: Array.from(options.identity.IDNullifier),
330
+ idSecretHash: Array.from(options.identity.IDSecretHash),
347
331
  idTrapdoor: Array.from(options.identity.IDTrapdoor)
348
332
  },
349
333
  membershipContract: {
package/src/proof.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { IRateLimitProof } from "@waku/interfaces";
2
2
 
3
- import { BytesUtils, poseidonHash } from "./utils/index.js";
3
+ import { concatenate, poseidonHash } from "./utils/index.js";
4
4
 
5
5
  const proofOffset = 128;
6
6
  const rootOffset = proofOffset + 32;
@@ -57,7 +57,7 @@ export class Proof implements IRateLimitProof {
57
57
  }
58
58
 
59
59
  export function proofToBytes(p: IRateLimitProof): Uint8Array {
60
- return BytesUtils.concatenate(
60
+ return concatenate(
61
61
  p.proof,
62
62
  p.merkleRoot,
63
63
  p.epoch,
@@ -1,130 +1,84 @@
1
- export class BytesUtils {
2
- /**
3
- * Switches endianness of a byte array
4
- */
5
- public static switchEndianness(bytes: Uint8Array): Uint8Array {
6
- return new Uint8Array(bytes.reverse());
1
+ /**
2
+ * Concatenate Uint8Arrays
3
+ * @param input
4
+ * @returns concatenation of all Uint8Array received as input
5
+ */
6
+ export function concatenate(...input: Uint8Array[]): Uint8Array {
7
+ let totalLength = 0;
8
+ for (const arr of input) {
9
+ totalLength += arr.length;
7
10
  }
8
-
9
- /**
10
- * Builds a BigInt from a big-endian Uint8Array
11
- * @param bytes The big-endian bytes to convert
12
- * @returns The resulting BigInt in big-endian format
13
- */
14
- public static buildBigIntFromUint8ArrayBE(bytes: Uint8Array): bigint {
15
- let result = 0n;
16
- for (let i = 0; i < bytes.length; i++) {
17
- result = (result << 8n) + BigInt(bytes[i]);
18
- }
19
- return result;
11
+ const result = new Uint8Array(totalLength);
12
+ let offset = 0;
13
+ for (const arr of input) {
14
+ result.set(arr, offset);
15
+ offset += arr.length;
20
16
  }
17
+ return result;
18
+ }
21
19
 
22
- /**
23
- * Switches endianness of a bigint value
24
- * @param value The bigint value to switch endianness for
25
- * @returns The bigint value with reversed endianness
26
- */
27
- public static switchEndiannessBigInt(value: bigint): bigint {
28
- // Convert bigint to byte array
29
- const bytes = [];
30
- let tempValue = value;
31
- while (tempValue > 0n) {
32
- bytes.push(Number(tempValue & 0xffn));
33
- tempValue >>= 8n;
34
- }
20
+ // Adapted from https://github.com/feross/buffer
21
+ function checkInt(
22
+ buf: Uint8Array,
23
+ value: number,
24
+ offset: number,
25
+ ext: number,
26
+ max: number,
27
+ min: number
28
+ ): void {
29
+ if (value > max || value < min)
30
+ throw new RangeError('"value" argument is out of bounds');
31
+ if (offset + ext > buf.length) throw new RangeError("Index out of range");
32
+ }
35
33
 
36
- // Reverse bytes and convert back to bigint
37
- return bytes
38
- .reverse()
39
- .reduce((acc, byte) => (acc << 8n) + BigInt(byte), 0n);
34
+ export function writeUIntLE(
35
+ buf: Uint8Array,
36
+ value: number,
37
+ offset: number,
38
+ byteLength: number,
39
+ noAssert?: boolean
40
+ ): Uint8Array {
41
+ value = +value;
42
+ offset = offset >>> 0;
43
+ byteLength = byteLength >>> 0;
44
+ if (!noAssert) {
45
+ const maxBytes = Math.pow(2, 8 * byteLength) - 1;
46
+ checkInt(buf, value, offset, byteLength, maxBytes, 0);
40
47
  }
41
48
 
42
- /**
43
- * Converts a big-endian bigint to a 32-byte big-endian Uint8Array
44
- * @param value The big-endian bigint to convert
45
- * @returns A 32-byte big-endian Uint8Array
46
- */
47
- public static bigIntToUint8Array32BE(value: bigint): Uint8Array {
48
- const bytes = new Uint8Array(32);
49
- for (let i = 31; i >= 0; i--) {
50
- bytes[i] = Number(value & 0xffn);
51
- value >>= 8n;
52
- }
53
- return bytes;
49
+ let mul = 1;
50
+ let i = 0;
51
+ buf[offset] = value & 0xff;
52
+ while (++i < byteLength && (mul *= 0x100)) {
53
+ buf[offset + i] = (value / mul) & 0xff;
54
54
  }
55
55
 
56
- /**
57
- * Writes an unsigned integer to a buffer in little-endian format
58
- */
59
- public static writeUIntLE(
60
- buf: Uint8Array,
61
- value: number,
62
- offset: number,
63
- byteLength: number,
64
- noAssert?: boolean
65
- ): Uint8Array {
66
- value = +value;
67
- offset = offset >>> 0;
68
- byteLength = byteLength >>> 0;
69
- if (!noAssert) {
70
- const maxBytes = Math.pow(2, 8 * byteLength) - 1;
71
- BytesUtils.checkInt(buf, value, offset, byteLength, maxBytes, 0);
72
- }
73
-
74
- let mul = 1;
75
- let i = 0;
76
- buf[offset] = value & 0xff;
77
- while (++i < byteLength && (mul *= 0x100)) {
78
- buf[offset + i] = (value / mul) & 0xff;
79
- }
80
-
81
- return buf;
82
- }
83
-
84
- /**
85
- * Fills with zeros to set length
86
- * @param array little endian Uint8Array
87
- * @param length amount to pad
88
- * @returns little endian Uint8Array padded with zeros to set length
89
- */
90
- public static zeroPadLE(array: Uint8Array, length: number): Uint8Array {
91
- const result = new Uint8Array(length);
92
- for (let i = 0; i < length; i++) {
93
- result[i] = array[i] || 0;
94
- }
95
- return result;
96
- }
56
+ return buf;
57
+ }
97
58
 
98
- // Adapted from https://github.com/feross/buffer
99
- public static checkInt(
100
- buf: Uint8Array,
101
- value: number,
102
- offset: number,
103
- ext: number,
104
- max: number,
105
- min: number
106
- ): void {
107
- if (value > max || value < min)
108
- throw new RangeError('"value" argument is out of bounds');
109
- if (offset + ext > buf.length) throw new RangeError("Index out of range");
110
- }
59
+ /**
60
+ * Transforms Uint8Array into BigInt
61
+ * @param array: Uint8Array
62
+ * @returns BigInt
63
+ */
64
+ export function buildBigIntFromUint8Array(
65
+ array: Uint8Array,
66
+ byteOffset: number = 0
67
+ ): bigint {
68
+ const dataView = new DataView(array.buffer);
69
+ return dataView.getBigUint64(byteOffset, true);
70
+ }
111
71
 
112
- /**
113
- * Concatenate Uint8Arrays
114
- * @param input
115
- * @returns concatenation of all Uint8Array received as input
116
- */
117
- public static concatenate(...input: Uint8Array[]): Uint8Array {
118
- let totalLength = 0;
119
- for (const arr of input) {
120
- totalLength += arr.length;
121
- }
122
- const result = new Uint8Array(totalLength);
123
- let offset = 0;
124
- for (const arr of input) {
125
- result.set(arr, offset);
126
- offset += arr.length;
127
- }
128
- return result;
72
+ /**
73
+ * Fills with zeros to set length
74
+ * @param array little endian Uint8Array
75
+ * @param length amount to pad
76
+ * @returns little endian Uint8Array padded with zeros to set length
77
+ */
78
+ export function zeroPadLE(array: Uint8Array, length: number): Uint8Array {
79
+ const result = new Uint8Array(length);
80
+ for (let i = 0; i < length; i++) {
81
+ result[i] = array[i] || 0;
129
82
  }
83
+ return result;
130
84
  }
package/src/utils/hash.ts CHANGED
@@ -1,25 +1,15 @@
1
1
  import * as zerokitRLN from "@waku/zerokit-rln-wasm";
2
2
 
3
- import { BytesUtils } from "./bytes.js";
3
+ import { concatenate, writeUIntLE } from "./bytes.js";
4
4
 
5
5
  export function poseidonHash(...input: Array<Uint8Array>): Uint8Array {
6
- const inputLen = BytesUtils.writeUIntLE(
7
- new Uint8Array(8),
8
- input.length,
9
- 0,
10
- 8
11
- );
12
- const lenPrefixedData = BytesUtils.concatenate(inputLen, ...input);
6
+ const inputLen = writeUIntLE(new Uint8Array(8), input.length, 0, 8);
7
+ const lenPrefixedData = concatenate(inputLen, ...input);
13
8
  return zerokitRLN.poseidonHash(lenPrefixedData);
14
9
  }
15
10
 
16
11
  export function sha256(input: Uint8Array): Uint8Array {
17
- const inputLen = BytesUtils.writeUIntLE(
18
- new Uint8Array(8),
19
- input.length,
20
- 0,
21
- 8
22
- );
23
- const lenPrefixedData = BytesUtils.concatenate(inputLen, input);
12
+ const inputLen = writeUIntLE(new Uint8Array(8), input.length, 0, 8);
13
+ const lenPrefixedData = concatenate(inputLen, input);
24
14
  return zerokitRLN.hash(lenPrefixedData);
25
15
  }
@@ -1,4 +1,9 @@
1
1
  export { extractMetaMaskSigner } from "./metamask.js";
2
- export { BytesUtils } from "./bytes.js";
2
+ export {
3
+ concatenate,
4
+ writeUIntLE,
5
+ buildBigIntFromUint8Array,
6
+ zeroPadLE
7
+ } from "./bytes.js";
3
8
  export { sha256, poseidonHash } from "./hash.js";
4
9
  export { dateToEpoch, epochIntToBytes, epochBytesToInt } from "./epoch.js";