@waku/rln 0.1.8-e224c05.0 → 0.1.8-e800af3.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 (187) hide show
  1. package/bundle/_virtual/utils.js +2 -2
  2. package/bundle/_virtual/utils2.js +2 -2
  3. package/bundle/index.js +6 -1
  4. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/_sha2.js +1 -1
  5. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/hmac.js +1 -1
  6. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/pbkdf2.js +1 -1
  7. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/scrypt.js +1 -1
  8. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/sha256.js +1 -1
  9. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/sha512.js +1 -1
  10. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes/utils.js +1 -1
  11. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/random.js +1 -1
  12. package/bundle/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography/utils.js +2 -2
  13. package/bundle/node_modules/@chainsafe/is-ip/lib/is-ip.js +12 -0
  14. package/bundle/node_modules/@chainsafe/is-ip/lib/parse.js +26 -0
  15. package/bundle/node_modules/@chainsafe/is-ip/lib/parser.js +202 -0
  16. package/bundle/node_modules/@multiformats/multiaddr/dist/src/constants.js +43 -0
  17. package/bundle/node_modules/@multiformats/multiaddr/dist/src/errors.js +17 -0
  18. package/bundle/node_modules/@multiformats/multiaddr/dist/src/registry.js +245 -0
  19. package/bundle/node_modules/@multiformats/multiaddr/dist/src/utils.js +191 -0
  20. package/bundle/node_modules/@multiformats/multiaddr/dist/src/validation.js +30 -0
  21. package/bundle/node_modules/@noble/hashes/esm/hmac.js +88 -0
  22. package/bundle/node_modules/@noble/hashes/esm/sha3.js +1 -1
  23. package/bundle/node_modules/@noble/hashes/esm/utils.js +8 -1
  24. package/bundle/node_modules/@waku/zerokit-rln-wasm/rln_wasm.js +517 -255
  25. package/bundle/node_modules/it-length-prefixed/dist/src/decode.js +6 -0
  26. package/bundle/node_modules/multiformats/dist/src/bases/base10.js +3 -1
  27. package/bundle/node_modules/multiformats/dist/src/bases/base16.js +4 -2
  28. package/bundle/node_modules/multiformats/dist/src/bases/base2.js +3 -1
  29. package/bundle/node_modules/multiformats/dist/src/bases/base256emoji.js +3 -1
  30. package/bundle/node_modules/multiformats/dist/src/bases/base32.js +11 -9
  31. package/bundle/node_modules/multiformats/dist/src/bases/base36.js +4 -2
  32. package/bundle/node_modules/multiformats/dist/src/bases/base58.js +4 -2
  33. package/bundle/node_modules/multiformats/dist/src/bases/base64.js +6 -4
  34. package/bundle/node_modules/multiformats/dist/src/bases/base8.js +3 -1
  35. package/bundle/node_modules/multiformats/dist/src/bases/identity.js +3 -1
  36. package/bundle/node_modules/multiformats/dist/src/basics.js +15 -0
  37. package/bundle/node_modules/multiformats/dist/src/bytes.js +15 -1
  38. package/bundle/node_modules/multiformats/dist/src/cid.js +371 -0
  39. package/bundle/node_modules/multiformats/dist/src/hashes/digest.js +62 -0
  40. package/bundle/node_modules/multiformats/dist/src/varint.js +15 -0
  41. package/bundle/node_modules/multiformats/dist/src/vendor/varint.js +78 -0
  42. package/bundle/node_modules/protons-runtime/dist/src/codec.js +20 -0
  43. package/bundle/node_modules/protons-runtime/dist/src/codecs/enum.js +24 -0
  44. package/bundle/node_modules/protons-runtime/dist/src/codecs/message.js +7 -0
  45. package/bundle/node_modules/protons-runtime/dist/src/decode.js +8 -0
  46. package/bundle/node_modules/protons-runtime/dist/src/encode.js +11 -0
  47. package/bundle/node_modules/protons-runtime/dist/src/index.js +30 -0
  48. package/bundle/node_modules/protons-runtime/dist/src/utils/float.js +54 -0
  49. package/bundle/node_modules/protons-runtime/dist/src/utils/longbits.js +175 -0
  50. package/bundle/node_modules/protons-runtime/dist/src/utils/pool.js +28 -0
  51. package/bundle/node_modules/protons-runtime/dist/src/utils/reader.js +367 -0
  52. package/bundle/node_modules/protons-runtime/dist/src/utils/utf8.js +99 -0
  53. package/bundle/node_modules/protons-runtime/dist/src/utils/writer.js +438 -0
  54. package/bundle/node_modules/uint8-varint/dist/src/index.js +124 -0
  55. package/bundle/node_modules/uint8arrays/dist/src/alloc.js +17 -0
  56. package/bundle/node_modules/uint8arrays/dist/src/concat.js +20 -0
  57. package/bundle/node_modules/uint8arrays/dist/src/from-string.js +19 -0
  58. package/bundle/node_modules/uint8arrays/dist/src/to-string.js +19 -0
  59. package/bundle/node_modules/uint8arrays/dist/src/util/as-uint8array.js +9 -0
  60. package/bundle/node_modules/uint8arrays/dist/src/util/bases.js +49 -0
  61. package/bundle/packages/core/dist/lib/connection_manager/connection_limiter.js +18 -0
  62. package/bundle/packages/core/dist/lib/connection_manager/connection_manager.js +24 -0
  63. package/bundle/packages/core/dist/lib/connection_manager/dialer.js +14 -0
  64. package/bundle/packages/core/dist/lib/connection_manager/discovery_dialer.js +14 -0
  65. package/bundle/packages/core/dist/lib/connection_manager/keep_alive_manager.js +15 -0
  66. package/bundle/packages/core/dist/lib/connection_manager/shard_reader.js +14 -0
  67. package/bundle/packages/core/dist/lib/filter/filter.js +28 -0
  68. package/bundle/packages/core/dist/lib/light_push/light_push.js +28 -0
  69. package/bundle/packages/core/dist/lib/message/version_0.js +172 -0
  70. package/bundle/packages/core/dist/lib/metadata/metadata.js +28 -0
  71. package/bundle/packages/core/dist/lib/store/store.js +24 -0
  72. package/bundle/packages/interfaces/dist/connection_manager.js +9 -0
  73. package/bundle/packages/interfaces/dist/health_status.js +17 -0
  74. package/bundle/packages/interfaces/dist/protocols.js +92 -0
  75. package/bundle/packages/interfaces/dist/waku.js +7 -0
  76. package/bundle/packages/proto/dist/generated/filter.js +447 -0
  77. package/bundle/packages/proto/dist/generated/filter_v2.js +426 -0
  78. package/bundle/packages/proto/dist/generated/light_push.js +550 -0
  79. package/bundle/packages/proto/dist/generated/message.js +215 -0
  80. package/bundle/packages/proto/dist/generated/metadata.js +132 -0
  81. package/bundle/packages/proto/dist/generated/peer_exchange.js +211 -0
  82. package/bundle/packages/proto/dist/generated/sds_message.js +172 -0
  83. package/bundle/packages/proto/dist/generated/store_v3.js +492 -0
  84. package/bundle/packages/proto/dist/generated/topic_only_message.js +63 -0
  85. package/bundle/packages/rln/dist/codec.js +92 -0
  86. package/bundle/packages/rln/dist/contract/constants.js +14 -7
  87. package/bundle/packages/rln/dist/contract/rln_base_contract.js +2 -1
  88. package/bundle/packages/rln/dist/contract/rln_contract.js +109 -0
  89. package/bundle/packages/rln/dist/credentials_manager.js +45 -4
  90. package/bundle/packages/rln/dist/identity.js +2 -1
  91. package/bundle/packages/rln/dist/keystore/keystore.js +30 -9
  92. package/bundle/packages/rln/dist/message.js +59 -0
  93. package/bundle/packages/rln/dist/proof.js +54 -0
  94. package/bundle/packages/rln/dist/resources/verification_key.js +112 -0
  95. package/bundle/packages/rln/dist/resources/witness_calculator.js +1 -1
  96. package/bundle/packages/rln/dist/rln.js +36 -4
  97. package/bundle/packages/rln/dist/root_tracker.js +76 -0
  98. package/bundle/packages/rln/dist/utils/bytes.js +70 -31
  99. package/bundle/packages/rln/dist/utils/epoch.js +23 -1
  100. package/bundle/packages/rln/dist/utils/hash.js +10 -0
  101. package/bundle/packages/rln/dist/zerokit.js +99 -2
  102. package/bundle/packages/utils/dist/bytes/index.js +31 -0
  103. package/bundle/resources/rln.wasm +0 -0
  104. package/bundle/resources/rln_final.zkey +0 -0
  105. package/bundle/resources/verification_key.d.ts +13 -0
  106. package/bundle/resources/verification_key.js +112 -0
  107. package/bundle/resources/witness_calculator.d.ts +7 -21
  108. package/bundle/resources/witness_calculator.js +1 -1
  109. package/dist/.tsbuildinfo +1 -1
  110. package/dist/codec.d.ts +40 -0
  111. package/dist/codec.js +79 -0
  112. package/dist/codec.js.map +1 -0
  113. package/dist/codec.test-utils.d.ts +37 -0
  114. package/dist/codec.test-utils.js +61 -0
  115. package/dist/codec.test-utils.js.map +1 -0
  116. package/dist/contract/constants.d.ts +10 -3
  117. package/dist/contract/constants.js +13 -6
  118. package/dist/contract/constants.js.map +1 -1
  119. package/dist/contract/index.d.ts +1 -0
  120. package/dist/contract/index.js +1 -0
  121. package/dist/contract/index.js.map +1 -1
  122. package/dist/contract/rln_base_contract.js +2 -1
  123. package/dist/contract/rln_base_contract.js.map +1 -1
  124. package/dist/contract/rln_contract.d.ts +17 -0
  125. package/dist/contract/rln_contract.js +107 -0
  126. package/dist/contract/rln_contract.js.map +1 -0
  127. package/dist/contract/test_setup.d.ts +26 -0
  128. package/dist/contract/test_setup.js +56 -0
  129. package/dist/contract/test_setup.js.map +1 -0
  130. package/dist/contract/test_utils.d.ts +39 -0
  131. package/dist/contract/test_utils.js +118 -0
  132. package/dist/contract/test_utils.js.map +1 -0
  133. package/dist/credentials_manager.d.ts +14 -2
  134. package/dist/credentials_manager.js +45 -4
  135. package/dist/credentials_manager.js.map +1 -1
  136. package/dist/identity.js +2 -1
  137. package/dist/identity.js.map +1 -1
  138. package/dist/index.d.ts +6 -2
  139. package/dist/index.js +6 -2
  140. package/dist/index.js.map +1 -1
  141. package/dist/keystore/keystore.js +30 -9
  142. package/dist/keystore/keystore.js.map +1 -1
  143. package/dist/message.d.ts +19 -0
  144. package/dist/message.js +51 -0
  145. package/dist/message.js.map +1 -0
  146. package/dist/proof.d.ts +21 -0
  147. package/dist/proof.js +50 -0
  148. package/dist/proof.js.map +1 -0
  149. package/dist/resources/rln.wasm +0 -0
  150. package/dist/resources/rln_final.zkey +0 -0
  151. package/dist/resources/verification_key.d.ts +13 -0
  152. package/dist/resources/verification_key.js +112 -0
  153. package/dist/resources/witness_calculator.d.ts +7 -21
  154. package/dist/resources/witness_calculator.js +1 -1
  155. package/dist/rln.d.ts +9 -0
  156. package/dist/rln.js +32 -4
  157. package/dist/rln.js.map +1 -1
  158. package/dist/root_tracker.d.ts +10 -0
  159. package/dist/root_tracker.js +75 -0
  160. package/dist/root_tracker.js.map +1 -0
  161. package/dist/utils/bytes.d.ts +31 -9
  162. package/dist/utils/bytes.js +70 -31
  163. package/dist/utils/bytes.js.map +1 -1
  164. package/dist/zerokit.d.ts +11 -0
  165. package/dist/zerokit.js +97 -1
  166. package/dist/zerokit.js.map +1 -1
  167. package/package.json +1 -1
  168. package/src/codec.test-utils.ts +88 -0
  169. package/src/codec.ts +138 -0
  170. package/src/contract/constants.ts +16 -6
  171. package/src/contract/index.ts +1 -0
  172. package/src/contract/rln_base_contract.ts +2 -1
  173. package/src/contract/rln_contract.ts +147 -0
  174. package/src/contract/test_setup.ts +86 -0
  175. package/src/contract/test_utils.ts +179 -0
  176. package/src/credentials_manager.ts +72 -8
  177. package/src/identity.ts +2 -1
  178. package/src/index.ts +11 -1
  179. package/src/keystore/keystore.ts +32 -9
  180. package/src/message.ts +73 -0
  181. package/src/proof.ts +69 -0
  182. package/src/resources/verification_key.d.ts +13 -0
  183. package/src/resources/witness_calculator.d.ts +7 -21
  184. package/src/rln.ts +65 -5
  185. package/src/root_tracker.ts +92 -0
  186. package/src/utils/bytes.ts +73 -36
  187. package/src/zerokit.ts +217 -1
package/src/rln.ts CHANGED
@@ -1,14 +1,37 @@
1
+ import { createDecoder, createEncoder } from "@waku/core";
2
+ import type {
3
+ ContentTopic,
4
+ IDecodedMessage,
5
+ IRoutingInfo,
6
+ EncoderOptions as WakuEncoderOptions
7
+ } from "@waku/interfaces";
1
8
  import { Logger } from "@waku/utils";
2
- import init, * as zerokitRLN from "@waku/zerokit-rln-wasm";
9
+ import init from "@waku/zerokit-rln-wasm";
10
+ import * as zerokitRLN from "@waku/zerokit-rln-wasm";
3
11
 
12
+ import {
13
+ createRLNDecoder,
14
+ createRLNEncoder,
15
+ type RLNDecoder,
16
+ type RLNEncoder
17
+ } from "./codec.js";
4
18
  import { DEFAULT_RATE_LIMIT } from "./contract/constants.js";
5
19
  import { RLNCredentialsManager } from "./credentials_manager.js";
20
+ import type {
21
+ DecryptedCredentials,
22
+ EncryptedCredentials
23
+ } from "./keystore/index.js";
24
+ import verificationKey from "./resources/verification_key";
6
25
  import * as wc from "./resources/witness_calculator";
7
26
  import { WitnessCalculator } from "./resources/witness_calculator";
8
27
  import { Zerokit } from "./zerokit.js";
9
28
 
10
29
  const log = new Logger("waku:rln");
11
30
 
31
+ type WakuRLNEncoderOptions = WakuEncoderOptions & {
32
+ credentials: EncryptedCredentials | DecryptedCredentials;
33
+ };
34
+
12
35
  export class RLNInstance extends RLNCredentialsManager {
13
36
  /**
14
37
  * Create an instance of RLN
@@ -16,14 +39,18 @@ export class RLNInstance extends RLNCredentialsManager {
16
39
  */
17
40
  public static async create(): Promise<RLNInstance> {
18
41
  try {
19
- await init();
20
-
21
- zerokitRLN.initPanicHook();
42
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
+ await (init as any)?.();
44
+ zerokitRLN.init_panic_hook();
22
45
 
23
46
  const witnessCalculator = await RLNInstance.loadWitnessCalculator();
24
47
  const zkey = await RLNInstance.loadZkey();
25
48
 
26
- const zkRLN = zerokitRLN.newRLN(zkey);
49
+ const stringEncoder = new TextEncoder();
50
+ const vkey = stringEncoder.encode(JSON.stringify(verificationKey));
51
+
52
+ const DEPTH = 20;
53
+ const zkRLN = zerokitRLN.newRLN(DEPTH, zkey, vkey);
27
54
  const zerokit = new Zerokit(zkRLN, witnessCalculator, DEFAULT_RATE_LIMIT);
28
55
 
29
56
  return new RLNInstance(zerokit);
@@ -37,6 +64,39 @@ export class RLNInstance extends RLNCredentialsManager {
37
64
  super(zerokit);
38
65
  }
39
66
 
67
+ public async createEncoder(
68
+ options: WakuRLNEncoderOptions
69
+ ): Promise<RLNEncoder> {
70
+ const { credentials: decryptedCredentials } =
71
+ await RLNInstance.decryptCredentialsIfNeeded(options.credentials);
72
+ const credentials = decryptedCredentials || this.credentials;
73
+
74
+ if (!credentials) {
75
+ throw Error(
76
+ "Failed to create Encoder: missing RLN credentials. Use createRLNEncoder directly."
77
+ );
78
+ }
79
+
80
+ await this.verifyCredentialsAgainstContract(credentials);
81
+
82
+ return createRLNEncoder({
83
+ encoder: createEncoder(options),
84
+ rlnInstance: this,
85
+ index: credentials.membership.treeIndex,
86
+ credential: credentials.identity
87
+ });
88
+ }
89
+
90
+ public createDecoder(
91
+ contentTopic: ContentTopic,
92
+ routingInfo: IRoutingInfo
93
+ ): RLNDecoder<IDecodedMessage> {
94
+ return createRLNDecoder({
95
+ rlnInstance: this,
96
+ decoder: createDecoder(contentTopic, routingInfo)
97
+ });
98
+ }
99
+
40
100
  public static async loadWitnessCalculator(): Promise<WitnessCalculator> {
41
101
  try {
42
102
  const url = new URL("./resources/rln.wasm", import.meta.url);
@@ -0,0 +1,92 @@
1
+ class RootPerBlock {
2
+ public constructor(
3
+ public root: Uint8Array,
4
+ public blockNumber: number
5
+ ) {}
6
+ }
7
+
8
+ const maxBufferSize = 20;
9
+
10
+ export class MerkleRootTracker {
11
+ private validMerkleRoots: Array<RootPerBlock> = new Array<RootPerBlock>();
12
+ private merkleRootBuffer: Array<RootPerBlock> = new Array<RootPerBlock>();
13
+
14
+ public constructor(
15
+ private acceptableRootWindowSize: number,
16
+ initialRoot: Uint8Array
17
+ ) {
18
+ this.pushRoot(0, initialRoot);
19
+ }
20
+
21
+ public backFill(fromBlockNumber: number): void {
22
+ if (this.validMerkleRoots.length == 0) return;
23
+
24
+ let numBlocks = 0;
25
+ for (let i = this.validMerkleRoots.length - 1; i >= 0; i--) {
26
+ if (this.validMerkleRoots[i].blockNumber >= fromBlockNumber) {
27
+ numBlocks++;
28
+ }
29
+ }
30
+
31
+ if (numBlocks == 0) return;
32
+
33
+ const olderBlock = fromBlockNumber < this.validMerkleRoots[0].blockNumber;
34
+
35
+ // Remove last roots
36
+ let rootsToPop = numBlocks;
37
+ if (this.validMerkleRoots.length < rootsToPop) {
38
+ rootsToPop = this.validMerkleRoots.length;
39
+ }
40
+
41
+ this.validMerkleRoots = this.validMerkleRoots.slice(
42
+ 0,
43
+ this.validMerkleRoots.length - rootsToPop
44
+ );
45
+
46
+ if (this.merkleRootBuffer.length == 0) return;
47
+
48
+ if (olderBlock) {
49
+ const idx = this.merkleRootBuffer.findIndex(
50
+ (x) => x.blockNumber == fromBlockNumber
51
+ );
52
+ if (idx > -1) {
53
+ this.merkleRootBuffer = this.merkleRootBuffer.slice(0, idx);
54
+ }
55
+ }
56
+
57
+ // Backfill the tree's acceptable roots
58
+ let rootsToRestore =
59
+ this.acceptableRootWindowSize - this.validMerkleRoots.length;
60
+ if (this.merkleRootBuffer.length < rootsToRestore) {
61
+ rootsToRestore = this.merkleRootBuffer.length;
62
+ }
63
+
64
+ for (let i = 0; i < rootsToRestore; i++) {
65
+ const x = this.merkleRootBuffer.pop();
66
+ if (x) this.validMerkleRoots.unshift(x);
67
+ }
68
+ }
69
+
70
+ public pushRoot(blockNumber: number, root: Uint8Array): void {
71
+ this.validMerkleRoots.push(new RootPerBlock(root, blockNumber));
72
+
73
+ // Maintain valid merkle root window
74
+ if (this.validMerkleRoots.length > this.acceptableRootWindowSize) {
75
+ const x = this.validMerkleRoots.shift();
76
+ if (x) this.merkleRootBuffer.push(x);
77
+ }
78
+
79
+ // Maintain merkle root buffer
80
+ if (this.merkleRootBuffer.length > maxBufferSize) {
81
+ this.merkleRootBuffer.shift();
82
+ }
83
+ }
84
+
85
+ public roots(): Array<Uint8Array> {
86
+ return this.validMerkleRoots.map((x) => x.root);
87
+ }
88
+
89
+ public buffer(): Array<Uint8Array> {
90
+ return this.merkleRootBuffer.map((x) => x.root);
91
+ }
92
+ }
@@ -1,52 +1,56 @@
1
1
  export class BytesUtils {
2
2
  /**
3
- * Concatenate Uint8Arrays
4
- * @param input
5
- * @returns concatenation of all Uint8Array received as input
3
+ * Switches endianness of a byte array
6
4
  */
7
- public static concatenate(...input: Uint8Array[]): Uint8Array {
8
- let totalLength = 0;
9
- for (const arr of input) {
10
- totalLength += arr.length;
11
- }
12
- const result = new Uint8Array(totalLength);
13
- let offset = 0;
14
- for (const arr of input) {
15
- result.set(arr, offset);
16
- offset += arr.length;
5
+ public static switchEndianness(bytes: Uint8Array): Uint8Array {
6
+ return new Uint8Array([...bytes].reverse());
7
+ }
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]);
17
18
  }
18
19
  return result;
19
20
  }
20
21
 
21
22
  /**
22
- * Convert a Uint8Array to a BigInt with configurable input endianness
23
- * @param bytes - The byte array to convert
24
- * @param inputEndianness - Endianness of the input bytes ('big' or 'little')
25
- * @returns BigInt representation of the bytes
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
26
  */
27
- public static toBigInt(
28
- bytes: Uint8Array,
29
- inputEndianness: "big" | "little" = "little"
30
- ): bigint {
31
- if (bytes.length === 0) {
32
- return 0n;
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;
33
34
  }
34
35
 
35
- // Create a copy to avoid modifying the original array
36
- const workingBytes = new Uint8Array(bytes);
37
-
38
- // Reverse bytes if input is little-endian to work with big-endian internally
39
- if (inputEndianness === "little") {
40
- workingBytes.reverse();
41
- }
36
+ // Reverse bytes and convert back to bigint
37
+ return bytes
38
+ .reverse()
39
+ .reduce((acc, byte) => (acc << 8n) + BigInt(byte), 0n);
40
+ }
42
41
 
43
- // Convert to BigInt
44
- let result = 0n;
45
- for (let i = 0; i < workingBytes.length; i++) {
46
- result = (result << 8n) | BigInt(workingBytes[i]);
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;
47
52
  }
48
-
49
- return result;
53
+ return bytes;
50
54
  }
51
55
 
52
56
  /**
@@ -77,6 +81,20 @@ export class BytesUtils {
77
81
  return buf;
78
82
  }
79
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
+ }
97
+
80
98
  // Adapted from https://github.com/feross/buffer
81
99
  public static checkInt(
82
100
  buf: Uint8Array,
@@ -90,4 +108,23 @@ export class BytesUtils {
90
108
  throw new RangeError('"value" argument is out of bounds');
91
109
  if (offset + ext > buf.length) throw new RangeError("Index out of range");
92
110
  }
111
+
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;
129
+ }
93
130
  }
package/src/zerokit.ts CHANGED
@@ -1,8 +1,11 @@
1
+ import type { IRateLimitProof } from "@waku/interfaces";
1
2
  import * as zerokitRLN from "@waku/zerokit-rln-wasm";
2
3
 
3
- import { DEFAULT_RATE_LIMIT } from "./contract/constants.js";
4
+ import { DEFAULT_RATE_LIMIT, RATE_LIMIT_PARAMS } from "./contract/constants.js";
4
5
  import { IdentityCredential } from "./identity.js";
6
+ import { Proof, proofToBytes } from "./proof.js";
5
7
  import { WitnessCalculator } from "./resources/witness_calculator";
8
+ import { BytesUtils, dateToEpoch, epochIntToBytes } from "./utils/index.js";
6
9
 
7
10
  export class Zerokit {
8
11
  public constructor(
@@ -23,13 +26,226 @@ export class Zerokit {
23
26
  return this._rateLimit;
24
27
  }
25
28
 
29
+ public generateIdentityCredentials(): IdentityCredential {
30
+ const memKeys = zerokitRLN.generateExtendedMembershipKey(this.zkRLN); // TODO: rename this function in zerokit rln-wasm
31
+ return IdentityCredential.fromBytes(memKeys);
32
+ }
33
+
26
34
  public generateSeededIdentityCredential(seed: string): IdentityCredential {
27
35
  const stringEncoder = new TextEncoder();
28
36
  const seedBytes = stringEncoder.encode(seed);
37
+ // TODO: rename this function in zerokit rln-wasm
29
38
  const memKeys = zerokitRLN.generateSeededExtendedMembershipKey(
30
39
  this.zkRLN,
31
40
  seedBytes
32
41
  );
33
42
  return IdentityCredential.fromBytes(memKeys);
34
43
  }
44
+
45
+ public insertMember(idCommitment: Uint8Array): void {
46
+ zerokitRLN.insertMember(this.zkRLN, idCommitment);
47
+ }
48
+
49
+ public insertMembers(
50
+ index: number,
51
+ ...idCommitments: Array<Uint8Array>
52
+ ): void {
53
+ // serializes a seq of IDCommitments to a byte seq
54
+ // the order of serialization is |id_commitment_len<8>|id_commitment<var>|
55
+ const idCommitmentLen = BytesUtils.writeUIntLE(
56
+ new Uint8Array(8),
57
+ idCommitments.length,
58
+ 0,
59
+ 8
60
+ );
61
+ const idCommitmentBytes = BytesUtils.concatenate(
62
+ idCommitmentLen,
63
+ ...idCommitments
64
+ );
65
+ zerokitRLN.setLeavesFrom(this.zkRLN, index, idCommitmentBytes);
66
+ }
67
+
68
+ public deleteMember(index: number): void {
69
+ zerokitRLN.deleteLeaf(this.zkRLN, index);
70
+ }
71
+
72
+ public getMerkleRoot(): Uint8Array {
73
+ return zerokitRLN.getRoot(this.zkRLN);
74
+ }
75
+
76
+ public serializeMessage(
77
+ uint8Msg: Uint8Array,
78
+ memIndex: number,
79
+ epoch: Uint8Array,
80
+ idKey: Uint8Array,
81
+ rateLimit?: number
82
+ ): Uint8Array {
83
+ // calculate message length
84
+ const msgLen = BytesUtils.writeUIntLE(
85
+ new Uint8Array(8),
86
+ uint8Msg.length,
87
+ 0,
88
+ 8
89
+ );
90
+ const memIndexBytes = BytesUtils.writeUIntLE(
91
+ new Uint8Array(8),
92
+ memIndex,
93
+ 0,
94
+ 8
95
+ );
96
+ const rateLimitBytes = BytesUtils.writeUIntLE(
97
+ new Uint8Array(8),
98
+ rateLimit ?? this.rateLimit,
99
+ 0,
100
+ 8
101
+ );
102
+
103
+ // [ id_key<32> | id_index<8> | epoch<32> | signal_len<8> | signal<var> | rate_limit<8> ]
104
+ return BytesUtils.concatenate(
105
+ idKey,
106
+ memIndexBytes,
107
+ epoch,
108
+ msgLen,
109
+ uint8Msg,
110
+ rateLimitBytes
111
+ );
112
+ }
113
+
114
+ public async generateRLNProof(
115
+ msg: Uint8Array,
116
+ index: number,
117
+ epoch: Uint8Array | Date | undefined,
118
+ idSecretHash: Uint8Array,
119
+ rateLimit?: number
120
+ ): Promise<IRateLimitProof> {
121
+ if (epoch === undefined) {
122
+ epoch = epochIntToBytes(dateToEpoch(new Date()));
123
+ } else if (epoch instanceof Date) {
124
+ epoch = epochIntToBytes(dateToEpoch(epoch));
125
+ }
126
+
127
+ const effectiveRateLimit = rateLimit ?? this.rateLimit;
128
+
129
+ if (epoch.length !== 32) throw new Error("invalid epoch");
130
+ if (idSecretHash.length !== 32) throw new Error("invalid id secret hash");
131
+ if (index < 0) throw new Error("index must be >= 0");
132
+ if (
133
+ effectiveRateLimit < RATE_LIMIT_PARAMS.MIN_RATE ||
134
+ effectiveRateLimit > RATE_LIMIT_PARAMS.MAX_RATE
135
+ ) {
136
+ throw new Error(
137
+ `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}`
138
+ );
139
+ }
140
+
141
+ const serialized_msg = this.serializeMessage(
142
+ msg,
143
+ index,
144
+ epoch,
145
+ idSecretHash,
146
+ effectiveRateLimit
147
+ );
148
+ const rlnWitness = zerokitRLN.getSerializedRLNWitness(
149
+ this.zkRLN,
150
+ serialized_msg
151
+ );
152
+ const inputs = zerokitRLN.RLNWitnessToJson(this.zkRLN, rlnWitness);
153
+ const calculatedWitness = await this.witnessCalculator.calculateWitness(
154
+ inputs,
155
+ false
156
+ );
157
+
158
+ const proofBytes = zerokitRLN.generate_rln_proof_with_witness(
159
+ this.zkRLN,
160
+ calculatedWitness,
161
+ rlnWitness
162
+ );
163
+
164
+ return new Proof(proofBytes);
165
+ }
166
+
167
+ public verifyRLNProof(
168
+ proof: IRateLimitProof | Uint8Array,
169
+ msg: Uint8Array,
170
+ rateLimit?: number
171
+ ): boolean {
172
+ let pBytes: Uint8Array;
173
+ if (proof instanceof Uint8Array) {
174
+ pBytes = proof;
175
+ } else {
176
+ pBytes = proofToBytes(proof);
177
+ }
178
+
179
+ // calculate message length
180
+ const msgLen = BytesUtils.writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
181
+ const rateLimitBytes = BytesUtils.writeUIntLE(
182
+ new Uint8Array(8),
183
+ rateLimit ?? this.rateLimit,
184
+ 0,
185
+ 8
186
+ );
187
+
188
+ return zerokitRLN.verifyRLNProof(
189
+ this.zkRLN,
190
+ BytesUtils.concatenate(pBytes, msgLen, msg, rateLimitBytes)
191
+ );
192
+ }
193
+
194
+ public verifyWithRoots(
195
+ proof: IRateLimitProof | Uint8Array,
196
+ msg: Uint8Array,
197
+ roots: Array<Uint8Array>,
198
+ rateLimit?: number
199
+ ): boolean {
200
+ let pBytes: Uint8Array;
201
+ if (proof instanceof Uint8Array) {
202
+ pBytes = proof;
203
+ } else {
204
+ pBytes = proofToBytes(proof);
205
+ }
206
+ // calculate message length
207
+ const msgLen = BytesUtils.writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
208
+ const rateLimitBytes = BytesUtils.writeUIntLE(
209
+ new Uint8Array(8),
210
+ rateLimit ?? this.rateLimit,
211
+ 0,
212
+ 8
213
+ );
214
+
215
+ const rootsBytes = BytesUtils.concatenate(...roots);
216
+
217
+ return zerokitRLN.verifyWithRoots(
218
+ this.zkRLN,
219
+ BytesUtils.concatenate(pBytes, msgLen, msg, rateLimitBytes),
220
+ rootsBytes
221
+ );
222
+ }
223
+
224
+ public verifyWithNoRoot(
225
+ proof: IRateLimitProof | Uint8Array,
226
+ msg: Uint8Array,
227
+ rateLimit?: number
228
+ ): boolean {
229
+ let pBytes: Uint8Array;
230
+ if (proof instanceof Uint8Array) {
231
+ pBytes = proof;
232
+ } else {
233
+ pBytes = proofToBytes(proof);
234
+ }
235
+
236
+ // calculate message length
237
+ const msgLen = BytesUtils.writeUIntLE(new Uint8Array(8), msg.length, 0, 8);
238
+ const rateLimitBytes = BytesUtils.writeUIntLE(
239
+ new Uint8Array(8),
240
+ rateLimit ?? this.rateLimit,
241
+ 0,
242
+ 8
243
+ );
244
+
245
+ return zerokitRLN.verifyWithRoots(
246
+ this.zkRLN,
247
+ BytesUtils.concatenate(pBytes, msgLen, msg, rateLimitBytes),
248
+ new Uint8Array()
249
+ );
250
+ }
35
251
  }