@aztec/foundation 0.0.1-commit.2448fdb → 0.0.1-commit.2606882

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 (260) hide show
  1. package/dest/bigint-buffer/index.d.ts +1 -1
  2. package/dest/bigint-buffer/index.d.ts.map +1 -1
  3. package/dest/bigint-buffer/index.js +6 -1
  4. package/dest/branded-types/block_number.d.ts +3 -3
  5. package/dest/branded-types/block_number.d.ts.map +1 -1
  6. package/dest/branded-types/block_number.js +15 -4
  7. package/dest/branded-types/buffer32_hash.d.ts +27 -0
  8. package/dest/branded-types/buffer32_hash.d.ts.map +1 -0
  9. package/dest/branded-types/buffer32_hash.js +12 -0
  10. package/dest/branded-types/checkpoint_number.d.ts +9 -3
  11. package/dest/branded-types/checkpoint_number.d.ts.map +1 -1
  12. package/dest/branded-types/checkpoint_number.js +11 -0
  13. package/dest/branded-types/epoch.d.ts +2 -2
  14. package/dest/branded-types/epoch.d.ts.map +1 -1
  15. package/dest/branded-types/index.d.ts +2 -1
  16. package/dest/branded-types/index.d.ts.map +1 -1
  17. package/dest/branded-types/index.js +1 -0
  18. package/dest/branded-types/index_within_checkpoint.d.ts +2 -2
  19. package/dest/branded-types/index_within_checkpoint.d.ts.map +1 -1
  20. package/dest/branded-types/slot.d.ts +2 -2
  21. package/dest/branded-types/slot.d.ts.map +1 -1
  22. package/dest/buffer/buffer16.d.ts +3 -1
  23. package/dest/buffer/buffer16.d.ts.map +1 -1
  24. package/dest/buffer/buffer32.d.ts +28 -61
  25. package/dest/buffer/buffer32.d.ts.map +1 -1
  26. package/dest/buffer/buffer32.js +29 -63
  27. package/dest/collection/array.d.ts +9 -1
  28. package/dest/collection/array.d.ts.map +1 -1
  29. package/dest/collection/array.js +18 -0
  30. package/dest/collection/index.d.ts +3 -1
  31. package/dest/collection/index.d.ts.map +1 -1
  32. package/dest/collection/index.js +2 -0
  33. package/dest/collection/lru_map.d.ts +41 -0
  34. package/dest/collection/lru_map.d.ts.map +1 -0
  35. package/dest/collection/lru_map.js +119 -0
  36. package/dest/collection/lru_set.d.ts +35 -0
  37. package/dest/collection/lru_set.d.ts.map +1 -0
  38. package/dest/collection/lru_set.js +95 -0
  39. package/dest/committable/committable.js +1 -1
  40. package/dest/config/env_var.d.ts +2 -2
  41. package/dest/config/env_var.d.ts.map +1 -1
  42. package/dest/config/index.d.ts +47 -30
  43. package/dest/config/index.d.ts.map +1 -1
  44. package/dest/config/index.js +30 -45
  45. package/dest/config/network_config.d.ts +11 -55
  46. package/dest/config/network_config.d.ts.map +1 -1
  47. package/dest/config/network_config.js +2 -2
  48. package/dest/config/network_name.d.ts +2 -2
  49. package/dest/config/network_name.d.ts.map +1 -1
  50. package/dest/config/network_name.js +3 -3
  51. package/dest/config/secret_value.d.ts +2 -2
  52. package/dest/config/secret_value.d.ts.map +1 -1
  53. package/dest/crypto/aes128/index.d.ts +2 -1
  54. package/dest/crypto/aes128/index.d.ts.map +1 -1
  55. package/dest/crypto/aes128/index.js +11 -2
  56. package/dest/crypto/bls/bn254_keystore.d.ts +9 -176
  57. package/dest/crypto/bls/bn254_keystore.d.ts.map +1 -1
  58. package/dest/crypto/bls/bn254_keystore.js +0 -17
  59. package/dest/crypto/schnorr/index.d.ts +8 -7
  60. package/dest/crypto/schnorr/index.d.ts.map +1 -1
  61. package/dest/crypto/schnorr/index.js +6 -6
  62. package/dest/crypto/schnorr/signature.d.ts +9 -29
  63. package/dest/crypto/schnorr/signature.d.ts.map +1 -1
  64. package/dest/crypto/schnorr/signature.js +20 -36
  65. package/dest/curves/bls12/field.d.ts +3 -3
  66. package/dest/curves/bls12/field.d.ts.map +1 -1
  67. package/dest/curves/bls12/field.js +0 -5
  68. package/dest/curves/bls12/point.d.ts +2 -2
  69. package/dest/curves/bls12/point.d.ts.map +1 -1
  70. package/dest/curves/bn254/field.d.ts +23 -19
  71. package/dest/curves/bn254/field.d.ts.map +1 -1
  72. package/dest/curves/bn254/field.js +23 -17
  73. package/dest/curves/grumpkin/point.d.ts +15 -29
  74. package/dest/curves/grumpkin/point.d.ts.map +1 -1
  75. package/dest/curves/grumpkin/point.js +31 -48
  76. package/dest/eth-address/index.d.ts +2 -2
  77. package/dest/eth-address/index.d.ts.map +1 -1
  78. package/dest/eth-address/index.js +0 -3
  79. package/dest/eth-signature/eth_signature.d.ts +2 -2
  80. package/dest/eth-signature/eth_signature.d.ts.map +1 -1
  81. package/dest/fifo/fifo_frame_reader.d.ts +41 -0
  82. package/dest/fifo/fifo_frame_reader.d.ts.map +1 -0
  83. package/dest/fifo/fifo_frame_reader.js +91 -0
  84. package/dest/fifo/index.d.ts +2 -0
  85. package/dest/fifo/index.d.ts.map +1 -0
  86. package/dest/fifo/index.js +1 -0
  87. package/dest/fifo_set/fifo_set.d.ts +15 -0
  88. package/dest/fifo_set/fifo_set.d.ts.map +1 -0
  89. package/dest/fifo_set/fifo_set.js +39 -0
  90. package/dest/fifo_set/index.d.ts +2 -0
  91. package/dest/fifo_set/index.d.ts.map +1 -0
  92. package/dest/fifo_set/index.js +1 -0
  93. package/dest/jest/setup.js +24 -0
  94. package/dest/json-rpc/client/fetch.d.ts +1 -1
  95. package/dest/json-rpc/client/fetch.d.ts.map +1 -1
  96. package/dest/json-rpc/client/fetch.js +4 -3
  97. package/dest/json-rpc/client/safe_json_rpc_client.d.ts +1 -1
  98. package/dest/json-rpc/client/safe_json_rpc_client.d.ts.map +1 -1
  99. package/dest/json-rpc/client/safe_json_rpc_client.js +2 -2
  100. package/dest/json-rpc/client/undici.d.ts +1 -1
  101. package/dest/json-rpc/client/undici.d.ts.map +1 -1
  102. package/dest/json-rpc/client/undici.js +5 -3
  103. package/dest/json-rpc/fixtures/test_state.d.ts +4 -8
  104. package/dest/json-rpc/fixtures/test_state.d.ts.map +1 -1
  105. package/dest/json-rpc/fixtures/test_state.js +57 -17
  106. package/dest/json-rpc/server/safe_json_rpc_server.d.ts +8 -3
  107. package/dest/json-rpc/server/safe_json_rpc_server.d.ts.map +1 -1
  108. package/dest/json-rpc/server/safe_json_rpc_server.js +27 -13
  109. package/dest/log/pino-logger.d.ts +1 -1
  110. package/dest/log/pino-logger.d.ts.map +1 -1
  111. package/dest/log/pino-logger.js +17 -2
  112. package/dest/noir/noir_package_config.d.ts +19 -104
  113. package/dest/noir/noir_package_config.d.ts.map +1 -1
  114. package/dest/noir/noir_package_config.js +1 -1
  115. package/dest/queue/batch_queue.d.ts +1 -1
  116. package/dest/queue/batch_queue.d.ts.map +1 -1
  117. package/dest/queue/batch_queue.js +1 -0
  118. package/dest/retry/index.d.ts +12 -1
  119. package/dest/retry/index.d.ts.map +1 -1
  120. package/dest/retry/index.js +21 -0
  121. package/dest/schemas/api.d.ts +11 -9
  122. package/dest/schemas/api.d.ts.map +1 -1
  123. package/dest/schemas/api.js +7 -1
  124. package/dest/schemas/parse.d.ts +4 -4
  125. package/dest/schemas/parse.d.ts.map +1 -1
  126. package/dest/schemas/parse.js +6 -5
  127. package/dest/schemas/schemas.d.ts +15 -15
  128. package/dest/schemas/types.d.ts +3 -3
  129. package/dest/schemas/types.d.ts.map +1 -1
  130. package/dest/schemas/utils.d.ts +7 -11
  131. package/dest/schemas/utils.d.ts.map +1 -1
  132. package/dest/schemas/utils.js +2 -18
  133. package/dest/serialize/buffer_reader.d.ts +7 -20
  134. package/dest/serialize/buffer_reader.d.ts.map +1 -1
  135. package/dest/serialize/buffer_reader.js +5 -18
  136. package/dest/serialize/buffer_sink.d.ts +134 -0
  137. package/dest/serialize/buffer_sink.d.ts.map +1 -0
  138. package/dest/serialize/buffer_sink.js +297 -0
  139. package/dest/serialize/field_reader.d.ts +5 -13
  140. package/dest/serialize/field_reader.d.ts.map +1 -1
  141. package/dest/serialize/field_reader.js +0 -13
  142. package/dest/serialize/index.d.ts +2 -1
  143. package/dest/serialize/index.d.ts.map +1 -1
  144. package/dest/serialize/index.js +1 -0
  145. package/dest/sleep/index.d.ts +2 -1
  146. package/dest/sleep/index.d.ts.map +1 -1
  147. package/dest/sleep/index.js +10 -1
  148. package/dest/string/index.js +1 -1
  149. package/dest/timer/date.d.ts +3 -1
  150. package/dest/timer/date.d.ts.map +1 -1
  151. package/dest/timer/date.js +4 -0
  152. package/dest/timer/index.d.ts +2 -2
  153. package/dest/timer/index.d.ts.map +1 -1
  154. package/dest/timer/index.js +1 -1
  155. package/dest/timer/timeout.d.ts +3 -1
  156. package/dest/timer/timeout.d.ts.map +1 -1
  157. package/dest/timer/timeout.js +26 -0
  158. package/dest/transport/dispatch/create_dispatch_proxy.d.ts +11 -2
  159. package/dest/transport/dispatch/create_dispatch_proxy.d.ts.map +1 -1
  160. package/dest/transport/index.d.ts +1 -2
  161. package/dest/transport/index.d.ts.map +1 -1
  162. package/dest/transport/index.js +0 -1
  163. package/dest/trees/balanced_merkle_tree_root.d.ts +2 -3
  164. package/dest/trees/balanced_merkle_tree_root.d.ts.map +1 -1
  165. package/dest/trees/balanced_merkle_tree_root.js +2 -3
  166. package/dest/trees/hasher.d.ts +3 -2
  167. package/dest/trees/hasher.d.ts.map +1 -1
  168. package/dest/trees/hasher.js +5 -5
  169. package/dest/trees/indexed_merkle_tree_calculator.d.ts +1 -1
  170. package/dest/trees/indexed_merkle_tree_calculator.d.ts.map +1 -1
  171. package/dest/trees/indexed_merkle_tree_calculator.js +5 -1
  172. package/dest/trees/membership_witness.d.ts +2 -2
  173. package/dest/trees/membership_witness.d.ts.map +1 -1
  174. package/dest/trees/merkle_tree_calculator.d.ts +4 -2
  175. package/dest/trees/merkle_tree_calculator.d.ts.map +1 -1
  176. package/dest/trees/merkle_tree_calculator.js +1 -5
  177. package/dest/trees/sibling_path.d.ts +5 -4
  178. package/dest/trees/sibling_path.d.ts.map +1 -1
  179. package/dest/trees/sibling_path.js +10 -8
  180. package/dest/trees/unbalanced_merkle_tree_root.d.ts +2 -3
  181. package/dest/trees/unbalanced_merkle_tree_root.d.ts.map +1 -1
  182. package/dest/trees/unbalanced_merkle_tree_root.js +2 -3
  183. package/dest/types/index.d.ts +23 -1
  184. package/dest/types/index.d.ts.map +1 -1
  185. package/dest/types/index.js +15 -0
  186. package/package.json +6 -4
  187. package/src/bigint-buffer/index.ts +6 -1
  188. package/src/branded-types/block_number.ts +20 -2
  189. package/src/branded-types/buffer32_hash.ts +38 -0
  190. package/src/branded-types/checkpoint_number.ts +16 -1
  191. package/src/branded-types/epoch.ts +1 -1
  192. package/src/branded-types/index.ts +1 -0
  193. package/src/branded-types/index_within_checkpoint.ts +1 -1
  194. package/src/branded-types/slot.ts +1 -1
  195. package/src/buffer/buffer16.ts +3 -0
  196. package/src/buffer/buffer32.ts +39 -68
  197. package/src/collection/array.ts +20 -0
  198. package/src/collection/index.ts +2 -0
  199. package/src/collection/lru_map.ts +143 -0
  200. package/src/collection/lru_set.ts +115 -0
  201. package/src/committable/committable.ts +1 -1
  202. package/src/config/env_var.ts +28 -20
  203. package/src/config/index.ts +102 -97
  204. package/src/config/network_config.ts +1 -1
  205. package/src/config/network_name.ts +6 -6
  206. package/src/config/secret_value.ts +1 -1
  207. package/src/crypto/aes128/index.ts +11 -2
  208. package/src/crypto/bls/bn254_keystore.ts +0 -23
  209. package/src/crypto/schnorr/index.ts +9 -8
  210. package/src/crypto/schnorr/signature.ts +17 -46
  211. package/src/curves/bls12/field.ts +0 -7
  212. package/src/curves/bn254/field.ts +35 -34
  213. package/src/curves/grumpkin/point.ts +24 -44
  214. package/src/eth-address/index.ts +0 -4
  215. package/src/fifo/fifo_frame_reader.ts +113 -0
  216. package/src/fifo/index.ts +1 -0
  217. package/src/fifo_set/fifo_set.ts +52 -0
  218. package/src/fifo_set/index.ts +1 -0
  219. package/src/jest/setup.mjs +27 -0
  220. package/src/json-rpc/client/fetch.ts +4 -3
  221. package/src/json-rpc/client/safe_json_rpc_client.ts +2 -2
  222. package/src/json-rpc/client/undici.ts +5 -3
  223. package/src/json-rpc/fixtures/test_state.ts +10 -10
  224. package/src/json-rpc/server/safe_json_rpc_server.ts +31 -13
  225. package/src/log/pino-logger.ts +19 -2
  226. package/src/noir/noir_package_config.ts +32 -20
  227. package/src/queue/batch_queue.ts +1 -0
  228. package/src/retry/index.ts +30 -0
  229. package/src/schemas/api.ts +21 -24
  230. package/src/schemas/parse.ts +9 -6
  231. package/src/schemas/schemas.ts +4 -4
  232. package/src/schemas/types.ts +2 -2
  233. package/src/schemas/utils.ts +4 -38
  234. package/src/serialize/buffer_reader.ts +6 -29
  235. package/src/serialize/buffer_sink.ts +350 -0
  236. package/src/serialize/field_reader.ts +4 -22
  237. package/src/serialize/index.ts +1 -0
  238. package/src/sleep/index.ts +10 -1
  239. package/src/string/index.ts +1 -1
  240. package/src/timer/date.ts +6 -0
  241. package/src/timer/index.ts +1 -1
  242. package/src/timer/timeout.ts +31 -0
  243. package/src/transport/dispatch/create_dispatch_proxy.ts +11 -1
  244. package/src/transport/index.ts +0 -1
  245. package/src/trees/balanced_merkle_tree_root.ts +2 -5
  246. package/src/trees/hasher.ts +6 -3
  247. package/src/trees/indexed_merkle_tree_calculator.ts +5 -1
  248. package/src/trees/membership_witness.ts +2 -2
  249. package/src/trees/merkle_tree_calculator.ts +4 -10
  250. package/src/trees/sibling_path.ts +11 -6
  251. package/src/trees/unbalanced_merkle_tree_root.ts +2 -5
  252. package/src/types/index.ts +47 -0
  253. package/dest/crypto/serialize.d.ts +0 -51
  254. package/dest/crypto/serialize.d.ts.map +0 -1
  255. package/dest/crypto/serialize.js +0 -68
  256. package/dest/transport/dispatch/create_dispatch_fn.d.ts +0 -25
  257. package/dest/transport/dispatch/create_dispatch_fn.d.ts.map +0 -1
  258. package/dest/transport/dispatch/create_dispatch_fn.js +0 -17
  259. package/src/crypto/serialize.ts +0 -85
  260. package/src/transport/dispatch/create_dispatch_fn.ts +0 -35
@@ -1,4 +1,5 @@
1
1
  import { BarretenbergSync } from '@aztec/bb.js';
2
+ import type { Fr } from '@aztec/foundation/curves/bn254';
2
3
  import type { GrumpkinScalar } from '@aztec/foundation/curves/grumpkin';
3
4
  import { Point } from '@aztec/foundation/curves/grumpkin';
4
5
 
@@ -23,33 +24,33 @@ export class Schnorr {
23
24
  }
24
25
 
25
26
  /**
26
- * Constructs a Schnorr signature given a msg and a private key.
27
- * @param msg - Message over which the signature is constructed.
27
+ * Constructs a Schnorr signature over a 32-byte message field element.
28
+ * @param msg - The message hash, as a grumpkin base field element.
28
29
  * @param privateKey - The private key of the signer.
29
30
  * @returns A Schnorr signature of the form (s, e).
30
31
  */
31
- public async constructSignature(msg: Uint8Array, privateKey: GrumpkinScalar) {
32
+ public async constructSignature(msg: Fr, privateKey: GrumpkinScalar) {
32
33
  await BarretenbergSync.initSingleton();
33
34
  const api = BarretenbergSync.getSingleton();
34
35
  const response = api.schnorrConstructSignature({
35
- message: msg,
36
+ messageField: msg.toBuffer(),
36
37
  privateKey: privateKey.toBuffer(),
37
38
  });
38
39
  return new SchnorrSignature(Buffer.from([...response.s, ...response.e]));
39
40
  }
40
41
 
41
42
  /**
42
- * Verifies a Schnorr signature given a Grumpkin public key.
43
- * @param msg - Message over which the signature was constructed.
43
+ * Verifies a Schnorr signature against a Grumpkin public key.
44
+ * @param msg - The message hash, as a grumpkin base field element.
44
45
  * @param pubKey - The Grumpkin public key of the signer.
45
46
  * @param sig - The Schnorr signature.
46
47
  * @returns True or false.
47
48
  */
48
- public async verifySignature(msg: Uint8Array, pubKey: Point, sig: SchnorrSignature) {
49
+ public async verifySignature(msg: Fr, pubKey: Point, sig: SchnorrSignature) {
49
50
  await BarretenbergSync.initSingleton();
50
51
  const api = BarretenbergSync.getSingleton();
51
52
  const response = api.schnorrVerifySignature({
52
- message: msg,
53
+ messageField: msg.toBuffer(),
53
54
  publicKey: { x: pubKey.x.toBuffer(), y: pubKey.y.toBuffer() },
54
55
  s: sig.s,
55
56
  e: sig.e,
@@ -1,6 +1,5 @@
1
- import { randomBytes } from '@aztec/foundation/crypto/random';
2
1
  import { Fr } from '@aztec/foundation/curves/bn254';
3
- import { BufferReader, mapTuple } from '@aztec/foundation/serialize';
2
+ import { mapTuple } from '@aztec/foundation/serialize';
4
3
 
5
4
  import type { Signature } from '../signature/index.js';
6
5
 
@@ -14,46 +13,12 @@ export class SchnorrSignature implements Signature {
14
13
  */
15
14
  public static SIZE = 64;
16
15
 
17
- /**
18
- * An empty signature.
19
- */
20
- public static EMPTY = new SchnorrSignature(Buffer.alloc(64));
21
-
22
16
  constructor(private buffer: Buffer) {
23
17
  if (buffer.length !== SchnorrSignature.SIZE) {
24
18
  throw new Error(`Invalid signature buffer of length ${buffer.length}.`);
25
19
  }
26
20
  }
27
21
 
28
- /**
29
- * Determines if the provided signature is valid or not.
30
- * @param signature - The data to be checked.
31
- * @returns Boolean indicating if the provided data is a valid schnorr signature.
32
- */
33
- public static isSignature(signature: string) {
34
- return /^(0x)?[0-9a-f]{128}$/i.test(signature);
35
- }
36
-
37
- /**
38
- * Constructs a SchnorrSignature from the provided string.
39
- * @param signature - The string to be converted to a schnorr signature.
40
- * @returns The constructed schnorr signature.
41
- */
42
- public static fromString(signature: string) {
43
- if (!SchnorrSignature.isSignature(signature)) {
44
- throw new Error(`Invalid signature string: ${signature}`);
45
- }
46
- return new SchnorrSignature(Buffer.from(signature.replace(/^0x/i, ''), 'hex'));
47
- }
48
-
49
- /**
50
- * Generates a random schnorr signature.
51
- * @returns The randomly constructed signature.
52
- */
53
- public static random() {
54
- return new SchnorrSignature(randomBytes(64));
55
- }
56
-
57
22
  /**
58
23
  * Returns the 's' component of the signature.
59
24
  * @returns A buffer containing the signature's 's' component.
@@ -78,16 +43,6 @@ export class SchnorrSignature implements Signature {
78
43
  return this.buffer;
79
44
  }
80
45
 
81
- /**
82
- * Deserializes from a buffer.
83
- * @param buffer - The buffer representation of the object.
84
- * @returns The new object.
85
- */
86
- static fromBuffer(buffer: Buffer | BufferReader): SchnorrSignature {
87
- const reader = BufferReader.asReader(buffer);
88
- return new SchnorrSignature(reader.readBytes(SchnorrSignature.SIZE));
89
- }
90
-
91
46
  /**
92
47
  * Returns the full signature as a hex string.
93
48
  * @returns A string containing the signature in hex format.
@@ -113,4 +68,20 @@ export class SchnorrSignature implements Signature {
113
68
 
114
69
  return mapTuple([buf1, buf2, buf3], Fr.fromBuffer);
115
70
  }
71
+
72
+ /**
73
+ * Splits the signature into the four 128-bit limbs that Noir's `EmbeddedCurveScalar` consumes:
74
+ * `[s.lo, s.hi, e.lo, e.hi]`, where each component scalar is encoded as `lo + hi * 2^128`.
75
+ *
76
+ * Each 32-byte big-endian component is sliced into its top 16 bytes (`hi`) and bottom 16 bytes
77
+ * (`lo`); each half is zero-padded into a 32-byte buffer and decoded as `Fr` (big-endian).
78
+ */
79
+ toLimbFields(): [Fr, Fr, Fr, Fr] {
80
+ const limb = (start: number) => {
81
+ const buf = Buffer.alloc(32);
82
+ this.buffer.copy(buf, 16, start, start + 16);
83
+ return Fr.fromBuffer(buf);
84
+ };
85
+ return [limb(16), limb(0), limb(48), limb(32)];
86
+ }
116
87
  }
@@ -6,7 +6,6 @@ import { toBigIntBE, toBufferBE } from '../../bigint-buffer/index.js';
6
6
  import { randomBytes } from '../../crypto/random/index.js';
7
7
  import { hexSchemaFor } from '../../schemas/utils.js';
8
8
  import { BufferReader } from '../../serialize/buffer_reader.js';
9
- import { TypeRegistry } from '../../serialize/type_registry.js';
10
9
  import { Fr } from '../bn254/field.js';
11
10
 
12
11
  /**
@@ -323,9 +322,6 @@ export class BLS12Fr extends BLS12Field {
323
322
  }
324
323
  }
325
324
 
326
- // For deserializing JSON.
327
- TypeRegistry.register('BLS12Fr', BLS12Fr);
328
-
329
325
  /**
330
326
  * Fq field class.
331
327
  * @dev This class is used to represent elements of BLS12-381 base field.
@@ -458,6 +454,3 @@ export class BLS12Fq extends BLS12Field {
458
454
  return hexSchemaFor(BLS12Fq);
459
455
  }
460
456
  }
461
-
462
- // For deserializing JSON.
463
- TypeRegistry.register('BLS12Fq', BLS12Fq);
@@ -6,9 +6,7 @@ import { toBigIntBE, toBufferBE } from '../../bigint-buffer/index.js';
6
6
  import { randomBytes } from '../../crypto/random/index.js';
7
7
  import { hexSchemaFor } from '../../schemas/utils.js';
8
8
  import { BufferReader } from '../../serialize/buffer_reader.js';
9
- import { TypeRegistry } from '../../serialize/type_registry.js';
10
-
11
- /* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
9
+ import type { BufferSink } from '../../serialize/buffer_sink.js';
12
10
 
13
11
  /**
14
12
  * Represents a field derived from BaseField.
@@ -67,10 +65,16 @@ abstract class BaseField {
67
65
  protected abstract modulus(): bigint;
68
66
 
69
67
  /**
70
- * Converts the bigint to a Buffer.
68
+ * Converts the bigint to a Buffer. With a sink, streams the 32 big-endian bytes straight in (no allocation)
69
+ * and returns undefined; without one, returns a freshly allocated buffer.
71
70
  */
72
- toBuffer(): Buffer {
73
- return toBufferBE(this.asBigInt, 32);
71
+ toBuffer(): Buffer;
72
+ toBuffer(sink: BufferSink): void;
73
+ toBuffer(sink?: BufferSink): Buffer | void {
74
+ if (!sink) {
75
+ return toBufferBE(this.asBigInt, BaseField.SIZE_IN_BYTES);
76
+ }
77
+ sink.writeField(this.asBigInt);
74
78
  }
75
79
 
76
80
  toString(): `0x${string}` {
@@ -187,10 +191,25 @@ function fromHexString<T extends BaseField>(buf: string, f: DerivedField<T>) {
187
191
  return new f(toBigIntBE(buffer));
188
192
  }
189
193
 
190
- /** Branding to ensure fields are not interchangeable types. */
191
- export interface Fr {
192
- /** Brand. */
193
- _branding: 'Fr';
194
+ /**
195
+ * Abstract unbranded base class for BN254 scalar field elements.
196
+ * Extend this instead of Fr when defining a branded subtype (e.g. BlockHash)
197
+ * to avoid inheriting Fr's `_branding`.
198
+ */
199
+ export abstract class BaseFr extends BaseField {
200
+ static MODULUS = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n;
201
+
202
+ constructor(value: number | bigint | boolean | BaseField | Buffer) {
203
+ super(value);
204
+ }
205
+
206
+ protected modulus() {
207
+ return BaseFr.MODULUS;
208
+ }
209
+
210
+ toJSON() {
211
+ return this.toString();
212
+ }
194
213
  }
195
214
 
196
215
  /**
@@ -198,10 +217,12 @@ export interface Fr {
198
217
  * @dev This class is used to represent elements of BN254 scalar field or elements in the base field of Grumpkin.
199
218
  * (Grumpkin's scalar field corresponds to BN254's base field and vice versa.)
200
219
  */
201
- export class Fr extends BaseField {
220
+ export class Fr extends BaseFr {
221
+ /** Branding for nominal typing. */
222
+ declare private readonly _branding: 'Fr';
223
+ static override MODULUS = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n;
202
224
  static ZERO = new Fr(0n);
203
225
  static ONE = new Fr(1n);
204
- static MODULUS = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001n;
205
226
  static MAX_FIELD_VALUE = new Fr(this.MODULUS - 1n);
206
227
 
207
228
  constructor(value: number | bigint | boolean | Fr | Buffer) {
@@ -212,10 +233,6 @@ export class Fr extends BaseField {
212
233
  return `Fr<${this.toString()}>`;
213
234
  }
214
235
 
215
- protected modulus() {
216
- return Fr.MODULUS;
217
- }
218
-
219
236
  static random() {
220
237
  return random(Fr);
221
238
  }
@@ -320,10 +337,6 @@ export class Fr extends BaseField {
320
337
  return Fr.fromBuffer(Buffer.from(response.value));
321
338
  }
322
339
 
323
- toJSON() {
324
- return this.toString();
325
- }
326
-
327
340
  /**
328
341
  * Creates an Fr instance from a plain object without Zod validation.
329
342
  * This method is optimized for performance and skips validation, making it suitable
@@ -345,23 +358,14 @@ export class Fr extends BaseField {
345
358
  }
346
359
  }
347
360
 
348
- // For deserializing JSON.
349
- TypeRegistry.register('Fr', Fr);
350
-
351
- /**
352
- * Branding to ensure fields are not interchangeable types.
353
- */
354
- export interface Fq {
355
- /** Brand. */
356
- _branding: 'Fq';
357
- }
358
-
359
361
  /**
360
362
  * Fq field class.
361
363
  * @dev This class is used to represent elements of BN254 base field or elements in the scalar field of Grumpkin.
362
364
  * (Grumpkin's scalar field corresponds to BN254's base field and vice versa.)
363
365
  */
364
366
  export class Fq extends BaseField {
367
+ /** Branding for nominal typing. */
368
+ declare private readonly _branding: 'Fq';
365
369
  static ZERO = new Fq(0n);
366
370
  static MODULUS = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47n;
367
371
  private static HIGH_SHIFT = BigInt((BaseField.SIZE_IN_BYTES / 2) * 8);
@@ -470,9 +474,6 @@ export class Fq extends BaseField {
470
474
  }
471
475
  }
472
476
 
473
- // For deserializing JSON.
474
- TypeRegistry.register('Fq', Fq);
475
-
476
477
  // Beware: Performance bottleneck below
477
478
 
478
479
  /**
@@ -1,5 +1,4 @@
1
1
  import { toBigIntBE } from '../../bigint-buffer/index.js';
2
- import { poseidon2Hash } from '../../crypto/poseidon/index.js';
3
2
  import { randomBoolean } from '../../crypto/random/index.js';
4
3
  import { hexSchemaFor } from '../../schemas/utils.js';
5
4
  import { BufferReader, FieldReader, serializeToBuffer } from '../../serialize/index.js';
@@ -13,13 +12,16 @@ import { Fr } from '../bn254/field.js';
13
12
  * TODO(#7386): Clean up this class.
14
13
  */
15
14
  export class Point {
16
- static ZERO = new Point(Fr.ZERO, Fr.ZERO, false);
15
+ static INFINITY = new Point(Fr.ZERO, Fr.ZERO);
17
16
  static SIZE_IN_BYTES = Fr.SIZE_IN_BYTES * 2;
18
17
  static COMPRESSED_SIZE_IN_BYTES = Fr.SIZE_IN_BYTES;
19
18
 
20
19
  /** Used to differentiate this class from AztecAddress */
21
20
  public readonly kind = 'point';
22
21
 
22
+ /** Whether the point is at infinity */
23
+ public readonly isInfinite: boolean;
24
+
23
25
  constructor(
24
26
  /**
25
27
  * The point's x coordinate
@@ -29,12 +31,10 @@ export class Point {
29
31
  * The point's y coordinate
30
32
  */
31
33
  public readonly y: Fr,
32
- /**
33
- * Whether the point is at infinity
34
- */
35
- public readonly isInfinite: boolean,
36
34
  ) {
37
35
  // TODO(#7386): check if on curve
36
+ // NOTE: now there is no isInfinite in the struct, empty == inf, so an empty class would pass an on-curve check. This may be fine depending on the usage.
37
+ this.isInfinite = x.isZero() && y.isZero();
38
38
  }
39
39
 
40
40
  toJSON() {
@@ -61,7 +61,7 @@ export class Point {
61
61
  if (obj instanceof Buffer || Buffer.isBuffer(obj)) {
62
62
  return Point.fromBuffer(obj);
63
63
  }
64
- return new Point(Fr.fromPlainObject(obj.x), Fr.fromPlainObject(obj.y), obj.isInfinite ?? false);
64
+ return new this(Fr.fromPlainObject(obj.x), Fr.fromPlainObject(obj.y));
65
65
  }
66
66
 
67
67
  /**
@@ -92,7 +92,7 @@ export class Point {
92
92
  */
93
93
  static fromBuffer(buffer: Buffer | BufferReader) {
94
94
  const reader = BufferReader.asReader(buffer);
95
- return new this(Fr.fromBuffer(reader), Fr.fromBuffer(reader), false);
95
+ return new this(Fr.fromBuffer(reader), Fr.fromBuffer(reader));
96
96
  }
97
97
 
98
98
  /**
@@ -125,19 +125,17 @@ export class Point {
125
125
  }
126
126
 
127
127
  /**
128
- * Returns the contents of the point as an array of 3 fields.
129
- * @returns The point as an array of 3 fields
128
+ * Returns the contents of the point as an array of 2 fields.
129
+ * @returns The point as an array of 2 fields
130
130
  */
131
- // TODO(F-553): Once we take the breaking change and drop the custom Noir `Point` wrapper in
132
- // `noir-projects/noir-protocol-circuits/crates/types/src/point.nr`, revert this to serialize as `[x, y]` (2 fields)
133
- // and drop the `is_infinite` flag from `fromFields` / `toNoirStruct` below.
134
131
  toFields() {
135
- return [this.x, this.y, new Fr(this.isInfinite)];
132
+ return [this.x, this.y];
136
133
  }
137
134
 
138
135
  static fromFields(fields: Fr[] | FieldReader) {
139
136
  const reader = FieldReader.asReader(fields);
140
- return new this(reader.readField(), reader.readField(), reader.readBoolean());
137
+ const [x, y] = [reader.readField(), reader.readField()];
138
+ return new this(x, y);
141
139
  }
142
140
 
143
141
  /**
@@ -162,11 +160,12 @@ export class Point {
162
160
  const finalY = sign ? new Fr(yPositiveBigInt) : new Fr(yNegativeBigInt);
163
161
 
164
162
  // Create and return the new Point
165
- return new this(x, finalY, false);
163
+ return new this(x, finalY);
166
164
  }
167
165
 
168
166
  /**
169
- * @returns
167
+ * @param x - The x coordinate of the point
168
+ * @returns y^2 such that y^2 = x^3 - 17
170
169
  */
171
170
  static YFromX(x: Fr): Promise<Fr | null> {
172
171
  // Calculate y^2 = x^3 - 17 (i.e. the Grumpkin curve equation)
@@ -194,24 +193,15 @@ export class Point {
194
193
  return {
195
194
  x: this.x.toBigInt(),
196
195
  y: this.y.toBigInt(),
197
- isInfinite: this.isInfinite ? 1n : 0n,
198
196
  };
199
197
  }
200
198
 
201
199
  /**
202
200
  * Converts the Point instance to a Buffer representation of the coordinates.
203
201
  * @returns A Buffer representation of the Point instance.
204
- * @dev Note that toBuffer does not include the isInfinite flag and other serialization methods do (e.g. toFields).
205
- * This is because currently when we work with point as bytes we don't want to populate the extra bytes for
206
- * isInfinite flag because:
207
- * 1. Our Grumpkin BB API currently does not handle point at infinity,
208
- * 2. we use toBuffer when serializing notes and events and there we only work with public keys and point at infinity
209
- * is not considered a valid public key and the extra byte would raise DA cost.
202
+ * @dev Note that toBuffer does not include the isInfinite flag. The point at infinity is serialized as (0, 0).
210
203
  */
211
204
  toBuffer() {
212
- if (this.isInfinite) {
213
- throw new Error('Cannot serialize infinite point with isInfinite flag');
214
- }
215
205
  const buf = serializeToBuffer([this.x, this.y]);
216
206
  if (buf.length !== Point.SIZE_IN_BYTES) {
217
207
  throw new Error(`Invalid buffer length for Point: ${buf.length}`);
@@ -261,12 +251,10 @@ export class Point {
261
251
  }
262
252
 
263
253
  toNoirStruct() {
264
- /* eslint-disable camelcase */
265
- return { x: this.x, y: this.y, is_infinite: this.isInfinite };
266
- /* eslint-enable camelcase */
254
+ return { x: this.x, y: this.y };
267
255
  }
268
256
 
269
- // Used for IvpkM, OvpkM, NpkM and TpkM. TODO(#8124): Consider removing this method.
257
+ // Used for IvpkM. TODO(#8124): Consider removing this method.
270
258
  toWrappedNoirStruct() {
271
259
  return { inner: this.toNoirStruct() };
272
260
  }
@@ -286,21 +274,13 @@ export class Point {
286
274
  return this.x.isZero() && this.y.isZero();
287
275
  }
288
276
 
289
- hash() {
290
- return poseidon2Hash(this.toFields());
291
- }
292
-
293
277
  /**
294
- * Check if this is point at infinity.
295
- * Check this is consistent with how bb is encoding the point at infinity
278
+ * @param x - The x coordinate of the point
279
+ * @param y - The y coordinate of the point
280
+ * @returns Whether the point exists on Grumpkin
296
281
  */
297
- public get inf() {
298
- return this.isInfinite;
299
- }
300
-
301
- isOnGrumpkin() {
302
- // TODO: Check this against how bb handles curve check and infinity point check
303
- if (this.inf) {
282
+ isOnCurve() {
283
+ if (this.isInfinite) {
304
284
  return true;
305
285
  }
306
286
 
@@ -5,7 +5,6 @@ import { randomBytes } from '../crypto/random/index.js';
5
5
  import { Fr } from '../curves/bn254/index.js';
6
6
  import { hexSchemaFor } from '../schemas/utils.js';
7
7
  import { BufferReader, FieldReader } from '../serialize/index.js';
8
- import { TypeRegistry } from '../serialize/type_registry.js';
9
8
  import { bufferToHex } from '../string/index.js';
10
9
 
11
10
  /**
@@ -268,6 +267,3 @@ export class EthAddress {
268
267
  return addrA.equals(addrB);
269
268
  }
270
269
  }
271
-
272
- // For deserializing JSON.
273
- TypeRegistry.register('EthAddress', EthAddress);
@@ -0,0 +1,113 @@
1
+ import EventEmitter from 'node:events';
2
+ import * as fs from 'node:fs';
3
+ import * as net from 'node:net';
4
+ import type { Readable } from 'node:stream';
5
+
6
+ /**
7
+ * Events emitted by FifoFrameReader.
8
+ *
9
+ * - `frame`: A complete frame payload (without the 4-byte length header).
10
+ * - `error`: An unrecoverable error (invalid frame length, stream error).
11
+ * - `end`: The underlying stream has ended.
12
+ */
13
+ export interface FifoFrameReaderEvents {
14
+ frame: [payload: Buffer];
15
+ error: [error: Error];
16
+ end: [];
17
+ }
18
+
19
+ /**
20
+ * Reads length-delimited frames from a readable stream (typically a named FIFO pipe).
21
+ *
22
+ * Wire format: `[4-byte big-endian payload length][payload bytes]`
23
+ *
24
+ * Emits a `frame` event for each complete frame with the raw payload buffer.
25
+ * Callers are responsible for deserializing the payload (e.g., via msgpack).
26
+ *
27
+ * On encountering an invalid payload length (0 or >maxPayloadSize), emits `error`
28
+ * and destroys the stream.
29
+ */
30
+ export class FifoFrameReader extends EventEmitter<FifoFrameReaderEvents> {
31
+ private stream: Readable | null = null;
32
+ private pendingBuf: Buffer = Buffer.alloc(0);
33
+ private running = false;
34
+
35
+ constructor(private readonly maxPayloadSize = 10 * 1024 * 1024) {
36
+ super();
37
+ }
38
+
39
+ /** Open a FIFO at the given path and start reading frames. */
40
+ start(fifoPath: string): void {
41
+ // Read the FIFO through a libuv pipe handle (net.Socket) rather than fs.createReadStream.
42
+ // An fs read stream services the pipe with a blocking threadpool read that destroy() cannot
43
+ // cancel: if a writer never closes, that read stays parked and keeps the host process alive
44
+ // (manifesting as Jest "did not exit"). Opening O_NONBLOCK and wrapping the fd in a pipe
45
+ // handle makes reads epoll-based, so stop()'s destroy() releases the handle immediately,
46
+ // regardless of whether the writer is still attached.
47
+ const fd = fs.openSync(fifoPath, fs.constants.O_RDONLY | fs.constants.O_NONBLOCK);
48
+ let socket: net.Socket;
49
+ try {
50
+ socket = new net.Socket({ fd, readable: true, writable: false });
51
+ } catch (err) {
52
+ fs.closeSync(fd);
53
+ throw err;
54
+ }
55
+ this.startFromStream(socket);
56
+ }
57
+
58
+ /** Start reading frames from an existing readable stream. */
59
+ startFromStream(stream: Readable): void {
60
+ if (this.running) {
61
+ throw new Error('FifoFrameReader is already running');
62
+ }
63
+ this.running = true;
64
+ this.pendingBuf = Buffer.alloc(0);
65
+ this.stream = stream;
66
+
67
+ stream.on('data', (chunk: Buffer | string) => {
68
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
69
+ this.pendingBuf = this.pendingBuf.length > 0 ? Buffer.concat([this.pendingBuf, buf]) : buf;
70
+ this.drainFrames();
71
+ });
72
+
73
+ stream.on('error', (err: Error) => {
74
+ if (this.running) {
75
+ this.emit('error', err);
76
+ }
77
+ });
78
+
79
+ stream.on('end', () => {
80
+ this.emit('end');
81
+ });
82
+ }
83
+
84
+ /** Stop reading and destroy the underlying stream. */
85
+ stop(): void {
86
+ this.running = false;
87
+ if (this.stream) {
88
+ this.stream.destroy();
89
+ this.stream = null;
90
+ }
91
+ }
92
+
93
+ /** Parse complete frames out of the pending buffer. */
94
+ private drainFrames(): void {
95
+ while (this.pendingBuf.length >= 4) {
96
+ const payloadLen = this.pendingBuf.readUInt32BE(0);
97
+ if (payloadLen === 0 || payloadLen > this.maxPayloadSize) {
98
+ this.emit('error', new Error(`Invalid payload length: ${payloadLen}`));
99
+ this.stop();
100
+ return;
101
+ }
102
+
103
+ const frameLen = 4 + payloadLen;
104
+ if (this.pendingBuf.length < frameLen) {
105
+ break; // Wait for more data
106
+ }
107
+
108
+ const payload = this.pendingBuf.subarray(4, frameLen);
109
+ this.pendingBuf = this.pendingBuf.subarray(frameLen);
110
+ this.emit('frame', Buffer.from(payload));
111
+ }
112
+ }
113
+ }
@@ -0,0 +1 @@
1
+ export { FifoFrameReader } from './fifo_frame_reader.js';
@@ -0,0 +1,52 @@
1
+ /** A Set capped to a fixed number of entries, evicting the oldest inserted value when full. */
2
+ export class FifoSet<T> extends Set<T> {
3
+ private _limit: number | undefined;
4
+
5
+ private constructor(values?: Iterable<T>) {
6
+ super(values);
7
+ }
8
+
9
+ /** Creates a bounded set with a positive integer limit. */
10
+ static withLimit<T>(limit: number, values?: Iterable<T>): FifoSet<T> {
11
+ if (!Number.isSafeInteger(limit) || limit <= 0) {
12
+ throw new TypeError(`FifoSet limit must be a positive safe integer: ${limit}`);
13
+ }
14
+
15
+ const set = new FifoSet(values);
16
+ set._limit = limit;
17
+ set.compact();
18
+
19
+ return set;
20
+ }
21
+
22
+ override add(value: T): this {
23
+ super.add(value);
24
+ this.compact();
25
+ return this;
26
+ }
27
+
28
+ /** Maximum number of entries retained by this set. */
29
+ public get limit(): number {
30
+ return this._limit ?? Infinity;
31
+ }
32
+
33
+ /** Evicts oldest entries until the set is within its limit. */
34
+ public compact(): void {
35
+ while (this.size > this.limit) {
36
+ const head = this.values().next();
37
+ if (head.done) {
38
+ return;
39
+ }
40
+ this.delete(head.value);
41
+ }
42
+ }
43
+
44
+ /** Adds a value only if it is absent, returning whether the set changed. */
45
+ public addIfAbsent(value: T): boolean {
46
+ if (this.has(value)) {
47
+ return false;
48
+ }
49
+ this.add(value);
50
+ return true;
51
+ }
52
+ }
@@ -0,0 +1 @@
1
+ export * from './fifo_set.js';
@@ -10,3 +10,30 @@ import pretty from 'pino-pretty';
10
10
  if (!parseBooleanEnv(process.env.LOG_JSON)) {
11
11
  overwriteLoggingStream(pretty(pinoPrettyOpts));
12
12
  }
13
+
14
+ // Prevent timers from keeping the process alive after tests complete.
15
+ // Libraries like viem create internal polling loops (via setTimeout) that
16
+ // reschedule themselves indefinitely. In test environments we never want a
17
+ // timer to be the reason the process can't exit. We also unref stdout/stderr
18
+ // which, when they are pipes (as in Jest workers), remain ref'd by default.
19
+ {
20
+ const origSetTimeout = globalThis.setTimeout;
21
+ const origSetInterval = globalThis.setInterval;
22
+ globalThis.setTimeout = function unrefSetTimeout(...args) {
23
+ const id = origSetTimeout.apply(this, args);
24
+ id?.unref?.();
25
+ return id;
26
+ };
27
+ // Preserve .unref, .__promisify__ etc. that may exist on the original
28
+ Object.setPrototypeOf(globalThis.setTimeout, origSetTimeout);
29
+
30
+ globalThis.setInterval = function unrefSetInterval(...args) {
31
+ const id = origSetInterval.apply(this, args);
32
+ id?.unref?.();
33
+ return id;
34
+ };
35
+ Object.setPrototypeOf(globalThis.setInterval, origSetInterval);
36
+
37
+ if (process.stdout?._handle?.unref) process.stdout._handle.unref();
38
+ if (process.stderr?._handle?.unref) process.stderr._handle.unref();
39
+ }