@aztec/foundation 0.0.1-commit.3469e52 → 0.0.1-commit.350e0a4d

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 (338) hide show
  1. package/dest/array/sorted_array.d.ts +6 -1
  2. package/dest/array/sorted_array.d.ts.map +1 -1
  3. package/dest/array/sorted_array.js +18 -15
  4. package/dest/bigint-buffer/index.d.ts +1 -1
  5. package/dest/bigint-buffer/index.d.ts.map +1 -1
  6. package/dest/bigint-buffer/index.js +6 -1
  7. package/dest/branded-types/block_number.d.ts +3 -3
  8. package/dest/branded-types/block_number.d.ts.map +1 -1
  9. package/dest/branded-types/block_number.js +15 -4
  10. package/dest/branded-types/buffer32_hash.d.ts +27 -0
  11. package/dest/branded-types/buffer32_hash.d.ts.map +1 -0
  12. package/dest/branded-types/buffer32_hash.js +12 -0
  13. package/dest/branded-types/checkpoint_number.d.ts +9 -3
  14. package/dest/branded-types/checkpoint_number.d.ts.map +1 -1
  15. package/dest/branded-types/checkpoint_number.js +11 -0
  16. package/dest/branded-types/epoch.d.ts +2 -2
  17. package/dest/branded-types/epoch.d.ts.map +1 -1
  18. package/dest/branded-types/index.d.ts +2 -1
  19. package/dest/branded-types/index.d.ts.map +1 -1
  20. package/dest/branded-types/index.js +1 -0
  21. package/dest/branded-types/index_within_checkpoint.d.ts +2 -2
  22. package/dest/branded-types/index_within_checkpoint.d.ts.map +1 -1
  23. package/dest/branded-types/slot.d.ts +5 -2
  24. package/dest/branded-types/slot.d.ts.map +1 -1
  25. package/dest/branded-types/slot.js +3 -0
  26. package/dest/buffer/buffer16.d.ts +3 -1
  27. package/dest/buffer/buffer16.d.ts.map +1 -1
  28. package/dest/buffer/buffer32.d.ts +28 -61
  29. package/dest/buffer/buffer32.d.ts.map +1 -1
  30. package/dest/buffer/buffer32.js +29 -63
  31. package/dest/buffer/index.d.ts +2 -1
  32. package/dest/buffer/index.d.ts.map +1 -1
  33. package/dest/buffer/index.js +1 -0
  34. package/dest/buffer/utils.d.ts +3 -0
  35. package/dest/buffer/utils.d.ts.map +1 -0
  36. package/dest/buffer/utils.js +7 -0
  37. package/dest/collection/array.d.ts +22 -1
  38. package/dest/collection/array.d.ts.map +1 -1
  39. package/dest/collection/array.js +84 -0
  40. package/dest/collection/index.d.ts +3 -1
  41. package/dest/collection/index.d.ts.map +1 -1
  42. package/dest/collection/index.js +2 -0
  43. package/dest/collection/lru_map.d.ts +41 -0
  44. package/dest/collection/lru_map.d.ts.map +1 -0
  45. package/dest/collection/lru_map.js +119 -0
  46. package/dest/collection/lru_set.d.ts +35 -0
  47. package/dest/collection/lru_set.d.ts.map +1 -0
  48. package/dest/collection/lru_set.js +95 -0
  49. package/dest/committable/committable.js +1 -1
  50. package/dest/config/env_var.d.ts +2 -2
  51. package/dest/config/env_var.d.ts.map +1 -1
  52. package/dest/config/index.d.ts +67 -37
  53. package/dest/config/index.d.ts.map +1 -1
  54. package/dest/config/index.js +86 -70
  55. package/dest/config/network_config.d.ts +15 -41
  56. package/dest/config/network_config.d.ts.map +1 -1
  57. package/dest/config/network_config.js +4 -1
  58. package/dest/config/network_name.d.ts +2 -2
  59. package/dest/config/network_name.d.ts.map +1 -1
  60. package/dest/config/network_name.js +3 -3
  61. package/dest/config/secret_value.d.ts +2 -2
  62. package/dest/config/secret_value.d.ts.map +1 -1
  63. package/dest/crypto/aes128/index.d.ts +2 -1
  64. package/dest/crypto/aes128/index.d.ts.map +1 -1
  65. package/dest/crypto/aes128/index.js +11 -2
  66. package/dest/crypto/bls/bn254_keystore.d.ts +10 -177
  67. package/dest/crypto/bls/bn254_keystore.d.ts.map +1 -1
  68. package/dest/crypto/bls/bn254_keystore.js +22 -34
  69. package/dest/crypto/keys/index.d.ts +3 -2
  70. package/dest/crypto/keys/index.d.ts.map +1 -1
  71. package/dest/crypto/keys/index.js +30 -6
  72. package/dest/crypto/poseidon/index.d.ts +1 -2
  73. package/dest/crypto/poseidon/index.d.ts.map +1 -1
  74. package/dest/crypto/poseidon/index.js +40 -42
  75. package/dest/crypto/random/randomness_singleton.d.ts +4 -3
  76. package/dest/crypto/random/randomness_singleton.d.ts.map +1 -1
  77. package/dest/crypto/random/randomness_singleton.js +4 -4
  78. package/dest/crypto/schnorr/index.d.ts +8 -7
  79. package/dest/crypto/schnorr/index.d.ts.map +1 -1
  80. package/dest/crypto/schnorr/index.js +6 -6
  81. package/dest/crypto/schnorr/signature.d.ts +9 -29
  82. package/dest/crypto/schnorr/signature.d.ts.map +1 -1
  83. package/dest/crypto/schnorr/signature.js +20 -36
  84. package/dest/crypto/secp256k1-signer/utils.d.ts +12 -1
  85. package/dest/crypto/secp256k1-signer/utils.d.ts.map +1 -1
  86. package/dest/crypto/secp256k1-signer/utils.js +26 -0
  87. package/dest/crypto/sync/poseidon/index.d.ts +1 -2
  88. package/dest/crypto/sync/poseidon/index.d.ts.map +1 -1
  89. package/dest/crypto/sync/poseidon/index.js +0 -8
  90. package/dest/curves/bls12/field.d.ts +3 -3
  91. package/dest/curves/bls12/field.d.ts.map +1 -1
  92. package/dest/curves/bls12/field.js +0 -5
  93. package/dest/curves/bls12/point.d.ts +2 -2
  94. package/dest/curves/bls12/point.d.ts.map +1 -1
  95. package/dest/curves/bn254/field.d.ts +24 -19
  96. package/dest/curves/bn254/field.d.ts.map +1 -1
  97. package/dest/curves/bn254/field.js +28 -19
  98. package/dest/curves/grumpkin/point.d.ts +14 -28
  99. package/dest/curves/grumpkin/point.d.ts.map +1 -1
  100. package/dest/curves/grumpkin/point.js +29 -43
  101. package/dest/eth-address/index.d.ts +2 -2
  102. package/dest/eth-address/index.d.ts.map +1 -1
  103. package/dest/eth-address/index.js +0 -3
  104. package/dest/eth-signature/eth_signature.d.ts +3 -2
  105. package/dest/eth-signature/eth_signature.d.ts.map +1 -1
  106. package/dest/eth-signature/eth_signature.js +7 -2
  107. package/dest/fifo/fifo_frame_reader.d.ts +41 -0
  108. package/dest/fifo/fifo_frame_reader.d.ts.map +1 -0
  109. package/dest/fifo/fifo_frame_reader.js +91 -0
  110. package/dest/fifo/index.d.ts +2 -0
  111. package/dest/fifo/index.d.ts.map +1 -0
  112. package/dest/fifo/index.js +1 -0
  113. package/dest/fifo_set/fifo_set.d.ts +15 -0
  114. package/dest/fifo_set/fifo_set.d.ts.map +1 -0
  115. package/dest/fifo_set/fifo_set.js +39 -0
  116. package/dest/fifo_set/index.d.ts +2 -0
  117. package/dest/fifo_set/index.d.ts.map +1 -0
  118. package/dest/fifo_set/index.js +1 -0
  119. package/dest/jest/setup.js +28 -1
  120. package/dest/json-rpc/client/fetch.d.ts +1 -1
  121. package/dest/json-rpc/client/fetch.d.ts.map +1 -1
  122. package/dest/json-rpc/client/fetch.js +4 -3
  123. package/dest/json-rpc/client/safe_json_rpc_client.d.ts +2 -1
  124. package/dest/json-rpc/client/safe_json_rpc_client.d.ts.map +1 -1
  125. package/dest/json-rpc/client/safe_json_rpc_client.js +3 -3
  126. package/dest/json-rpc/client/undici.d.ts +1 -1
  127. package/dest/json-rpc/client/undici.d.ts.map +1 -1
  128. package/dest/json-rpc/client/undici.js +23 -4
  129. package/dest/json-rpc/fixtures/test_state.d.ts +4 -8
  130. package/dest/json-rpc/fixtures/test_state.d.ts.map +1 -1
  131. package/dest/json-rpc/fixtures/test_state.js +57 -17
  132. package/dest/json-rpc/server/api_key_auth.d.ts +19 -0
  133. package/dest/json-rpc/server/api_key_auth.d.ts.map +1 -0
  134. package/dest/json-rpc/server/api_key_auth.js +57 -0
  135. package/dest/json-rpc/server/index.d.ts +2 -1
  136. package/dest/json-rpc/server/index.d.ts.map +1 -1
  137. package/dest/json-rpc/server/index.js +1 -0
  138. package/dest/json-rpc/server/safe_json_rpc_server.d.ts +8 -3
  139. package/dest/json-rpc/server/safe_json_rpc_server.d.ts.map +1 -1
  140. package/dest/json-rpc/server/safe_json_rpc_server.js +28 -14
  141. package/dest/log/bigint-utils.d.ts +5 -0
  142. package/dest/log/bigint-utils.d.ts.map +1 -0
  143. package/dest/log/bigint-utils.js +21 -0
  144. package/dest/log/gcloud-logger-config.d.ts +1 -1
  145. package/dest/log/gcloud-logger-config.d.ts.map +1 -1
  146. package/dest/log/gcloud-logger-config.js +3 -0
  147. package/dest/log/libp2p_logger.d.ts +5 -2
  148. package/dest/log/libp2p_logger.d.ts.map +1 -1
  149. package/dest/log/libp2p_logger.js +14 -4
  150. package/dest/log/log-filters.d.ts +17 -4
  151. package/dest/log/log-filters.d.ts.map +1 -1
  152. package/dest/log/log-filters.js +26 -12
  153. package/dest/log/pino-logger-server.d.ts +9 -0
  154. package/dest/log/pino-logger-server.d.ts.map +1 -0
  155. package/dest/log/pino-logger-server.js +18 -0
  156. package/dest/log/pino-logger.d.ts +37 -8
  157. package/dest/log/pino-logger.d.ts.map +1 -1
  158. package/dest/log/pino-logger.js +137 -29
  159. package/dest/noir/noir_package_config.d.ts +19 -104
  160. package/dest/noir/noir_package_config.d.ts.map +1 -1
  161. package/dest/noir/noir_package_config.js +1 -1
  162. package/dest/promise/running-promise.d.ts +5 -4
  163. package/dest/promise/running-promise.d.ts.map +1 -1
  164. package/dest/promise/running-promise.js +7 -3
  165. package/dest/queue/base_memory_queue.d.ts +2 -2
  166. package/dest/queue/base_memory_queue.d.ts.map +1 -1
  167. package/dest/queue/batch_queue.d.ts +1 -1
  168. package/dest/queue/batch_queue.d.ts.map +1 -1
  169. package/dest/queue/batch_queue.js +1 -0
  170. package/dest/queue/semaphore.d.ts +5 -1
  171. package/dest/queue/semaphore.d.ts.map +1 -1
  172. package/dest/retry/index.d.ts +31 -3
  173. package/dest/retry/index.d.ts.map +1 -1
  174. package/dest/retry/index.js +44 -2
  175. package/dest/schemas/api.d.ts +12 -10
  176. package/dest/schemas/api.d.ts.map +1 -1
  177. package/dest/schemas/api.js +7 -1
  178. package/dest/schemas/parse.d.ts +4 -4
  179. package/dest/schemas/parse.d.ts.map +1 -1
  180. package/dest/schemas/parse.js +6 -5
  181. package/dest/schemas/schemas.d.ts +15 -15
  182. package/dest/schemas/types.d.ts +3 -3
  183. package/dest/schemas/types.d.ts.map +1 -1
  184. package/dest/schemas/utils.d.ts +7 -11
  185. package/dest/schemas/utils.d.ts.map +1 -1
  186. package/dest/schemas/utils.js +2 -18
  187. package/dest/serialize/buffer_reader.d.ts +8 -1
  188. package/dest/serialize/buffer_reader.d.ts.map +1 -1
  189. package/dest/serialize/buffer_reader.js +13 -0
  190. package/dest/serialize/buffer_sink.d.ts +134 -0
  191. package/dest/serialize/buffer_sink.d.ts.map +1 -0
  192. package/dest/serialize/buffer_sink.js +297 -0
  193. package/dest/serialize/index.d.ts +2 -1
  194. package/dest/serialize/index.d.ts.map +1 -1
  195. package/dest/serialize/index.js +1 -0
  196. package/dest/serialize/serialize.d.ts +19 -1
  197. package/dest/serialize/serialize.d.ts.map +1 -1
  198. package/dest/serialize/serialize.js +31 -0
  199. package/dest/sleep/index.d.ts +2 -1
  200. package/dest/sleep/index.d.ts.map +1 -1
  201. package/dest/sleep/index.js +10 -1
  202. package/dest/string/index.js +1 -1
  203. package/dest/testing/files/index.d.ts +2 -3
  204. package/dest/testing/files/index.d.ts.map +1 -1
  205. package/dest/testing/files/index.js +1 -2
  206. package/dest/timer/date.d.ts +25 -1
  207. package/dest/timer/date.d.ts.map +1 -1
  208. package/dest/timer/date.js +33 -0
  209. package/dest/timer/index.d.ts +2 -2
  210. package/dest/timer/index.d.ts.map +1 -1
  211. package/dest/timer/index.js +1 -1
  212. package/dest/timer/timeout.d.ts +3 -1
  213. package/dest/timer/timeout.d.ts.map +1 -1
  214. package/dest/timer/timeout.js +26 -0
  215. package/dest/transport/dispatch/create_dispatch_proxy.d.ts +11 -2
  216. package/dest/transport/dispatch/create_dispatch_proxy.d.ts.map +1 -1
  217. package/dest/transport/index.d.ts +1 -2
  218. package/dest/transport/index.d.ts.map +1 -1
  219. package/dest/transport/index.js +0 -1
  220. package/dest/transport/transport_client.js +2 -2
  221. package/dest/trees/balanced_merkle_tree_root.d.ts +3 -5
  222. package/dest/trees/balanced_merkle_tree_root.d.ts.map +1 -1
  223. package/dest/trees/balanced_merkle_tree_root.js +3 -5
  224. package/dest/trees/hasher.d.ts +3 -3
  225. package/dest/trees/hasher.d.ts.map +1 -1
  226. package/dest/trees/hasher.js +5 -10
  227. package/dest/trees/indexed_merkle_tree_calculator.d.ts +1 -1
  228. package/dest/trees/indexed_merkle_tree_calculator.d.ts.map +1 -1
  229. package/dest/trees/indexed_merkle_tree_calculator.js +5 -1
  230. package/dest/trees/membership_witness.d.ts +2 -2
  231. package/dest/trees/membership_witness.d.ts.map +1 -1
  232. package/dest/trees/merkle_tree_calculator.d.ts +4 -2
  233. package/dest/trees/merkle_tree_calculator.d.ts.map +1 -1
  234. package/dest/trees/merkle_tree_calculator.js +1 -5
  235. package/dest/trees/sibling_path.d.ts +5 -4
  236. package/dest/trees/sibling_path.d.ts.map +1 -1
  237. package/dest/trees/sibling_path.js +10 -8
  238. package/dest/trees/unbalanced_merkle_tree_root.d.ts +2 -3
  239. package/dest/trees/unbalanced_merkle_tree_root.d.ts.map +1 -1
  240. package/dest/trees/unbalanced_merkle_tree_root.js +2 -3
  241. package/dest/types/index.d.ts +25 -1
  242. package/dest/types/index.d.ts.map +1 -1
  243. package/dest/types/index.js +18 -0
  244. package/package.json +27 -4
  245. package/src/array/sorted_array.ts +22 -17
  246. package/src/bigint-buffer/index.ts +6 -1
  247. package/src/branded-types/block_number.ts +20 -2
  248. package/src/branded-types/buffer32_hash.ts +38 -0
  249. package/src/branded-types/checkpoint_number.ts +16 -1
  250. package/src/branded-types/epoch.ts +1 -1
  251. package/src/branded-types/index.ts +1 -0
  252. package/src/branded-types/index_within_checkpoint.ts +1 -1
  253. package/src/branded-types/slot.ts +6 -1
  254. package/src/buffer/buffer16.ts +3 -0
  255. package/src/buffer/buffer32.ts +39 -68
  256. package/src/buffer/index.ts +1 -0
  257. package/src/buffer/utils.ts +8 -0
  258. package/src/collection/array.ts +86 -0
  259. package/src/collection/index.ts +2 -0
  260. package/src/collection/lru_map.ts +143 -0
  261. package/src/collection/lru_set.ts +115 -0
  262. package/src/committable/committable.ts +1 -1
  263. package/src/config/env_var.ts +97 -23
  264. package/src/config/index.ts +157 -121
  265. package/src/config/network_config.ts +3 -0
  266. package/src/config/network_name.ts +6 -6
  267. package/src/config/secret_value.ts +1 -1
  268. package/src/crypto/aes128/index.ts +11 -2
  269. package/src/crypto/bls/bn254_keystore.ts +33 -43
  270. package/src/crypto/keys/index.ts +20 -4
  271. package/src/crypto/poseidon/index.ts +42 -44
  272. package/src/crypto/random/randomness_singleton.ts +9 -5
  273. package/src/crypto/schnorr/index.ts +9 -8
  274. package/src/crypto/schnorr/signature.ts +17 -46
  275. package/src/crypto/secp256k1-signer/utils.ts +32 -0
  276. package/src/crypto/sync/poseidon/index.ts +0 -9
  277. package/src/curves/bls12/field.ts +0 -7
  278. package/src/curves/bn254/field.ts +41 -36
  279. package/src/curves/grumpkin/point.ts +23 -40
  280. package/src/eth-address/index.ts +0 -4
  281. package/src/eth-signature/eth_signature.ts +7 -1
  282. package/src/fifo/fifo_frame_reader.ts +113 -0
  283. package/src/fifo/index.ts +1 -0
  284. package/src/fifo_set/fifo_set.ts +52 -0
  285. package/src/fifo_set/index.ts +1 -0
  286. package/src/jest/setup.mjs +31 -1
  287. package/src/json-rpc/client/fetch.ts +4 -3
  288. package/src/json-rpc/client/safe_json_rpc_client.ts +4 -2
  289. package/src/json-rpc/client/undici.ts +23 -3
  290. package/src/json-rpc/fixtures/test_state.ts +10 -10
  291. package/src/json-rpc/server/api_key_auth.ts +63 -0
  292. package/src/json-rpc/server/index.ts +1 -0
  293. package/src/json-rpc/server/safe_json_rpc_server.ts +32 -14
  294. package/src/log/bigint-utils.ts +25 -0
  295. package/src/log/gcloud-logger-config.ts +5 -0
  296. package/src/log/libp2p_logger.ts +12 -5
  297. package/src/log/log-filters.ts +29 -11
  298. package/src/log/pino-logger-server.ts +25 -0
  299. package/src/log/pino-logger.ts +160 -39
  300. package/src/noir/noir_package_config.ts +32 -20
  301. package/src/promise/running-promise.ts +8 -5
  302. package/src/queue/base_memory_queue.ts +1 -1
  303. package/src/queue/batch_queue.ts +1 -0
  304. package/src/queue/semaphore.ts +5 -0
  305. package/src/retry/index.ts +66 -4
  306. package/src/schemas/api.ts +25 -25
  307. package/src/schemas/parse.ts +9 -6
  308. package/src/schemas/schemas.ts +4 -4
  309. package/src/schemas/types.ts +2 -2
  310. package/src/schemas/utils.ts +4 -38
  311. package/src/serialize/buffer_reader.ts +15 -0
  312. package/src/serialize/buffer_sink.ts +350 -0
  313. package/src/serialize/index.ts +1 -0
  314. package/src/serialize/serialize.ts +32 -0
  315. package/src/sleep/index.ts +10 -1
  316. package/src/string/index.ts +1 -1
  317. package/src/testing/files/index.ts +1 -2
  318. package/src/timer/date.ts +48 -0
  319. package/src/timer/index.ts +1 -1
  320. package/src/timer/timeout.ts +31 -0
  321. package/src/transport/dispatch/create_dispatch_proxy.ts +11 -1
  322. package/src/transport/index.ts +0 -1
  323. package/src/transport/transport_client.ts +2 -2
  324. package/src/trees/balanced_merkle_tree_root.ts +3 -9
  325. package/src/trees/hasher.ts +6 -7
  326. package/src/trees/indexed_merkle_tree_calculator.ts +5 -1
  327. package/src/trees/merkle_tree_calculator.ts +4 -10
  328. package/src/trees/sibling_path.ts +11 -6
  329. package/src/trees/unbalanced_merkle_tree_root.ts +2 -5
  330. package/src/types/index.ts +52 -0
  331. package/dest/crypto/serialize.d.ts +0 -51
  332. package/dest/crypto/serialize.d.ts.map +0 -1
  333. package/dest/crypto/serialize.js +0 -68
  334. package/dest/transport/dispatch/create_dispatch_fn.d.ts +0 -25
  335. package/dest/transport/dispatch/create_dispatch_fn.d.ts.map +0 -1
  336. package/dest/transport/dispatch/create_dispatch_fn.js +0 -17
  337. package/src/crypto/serialize.ts +0 -85
  338. package/src/transport/dispatch/create_dispatch_fn.ts +0 -35
@@ -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,11 +61,11 @@ 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
  /**
68
- * Generate a random Point instance.
68
+ * Generate a random Point instance that is on the curve.
69
69
  *
70
70
  * @returns A randomly generated Point instance.
71
71
  */
@@ -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
  /**
@@ -129,12 +129,13 @@ export class Point {
129
129
  * @returns The point as an array of 2 fields
130
130
  */
131
131
  toFields() {
132
- return [this.x, this.y, new Fr(this.isInfinite)];
132
+ return [this.x, this.y];
133
133
  }
134
134
 
135
135
  static fromFields(fields: Fr[] | FieldReader) {
136
136
  const reader = FieldReader.asReader(fields);
137
- return new this(reader.readField(), reader.readField(), reader.readBoolean());
137
+ const [x, y] = [reader.readField(), reader.readField()];
138
+ return new this(x, y);
138
139
  }
139
140
 
140
141
  /**
@@ -159,11 +160,12 @@ export class Point {
159
160
  const finalY = sign ? new Fr(yPositiveBigInt) : new Fr(yNegativeBigInt);
160
161
 
161
162
  // Create and return the new Point
162
- return new this(x, finalY, false);
163
+ return new this(x, finalY);
163
164
  }
164
165
 
165
166
  /**
166
- * @returns
167
+ * @param x - The x coordinate of the point
168
+ * @returns y^2 such that y^2 = x^3 - 17
167
169
  */
168
170
  static YFromX(x: Fr): Promise<Fr | null> {
169
171
  // Calculate y^2 = x^3 - 17 (i.e. the Grumpkin curve equation)
@@ -191,24 +193,15 @@ export class Point {
191
193
  return {
192
194
  x: this.x.toBigInt(),
193
195
  y: this.y.toBigInt(),
194
- isInfinite: this.isInfinite ? 1n : 0n,
195
196
  };
196
197
  }
197
198
 
198
199
  /**
199
200
  * Converts the Point instance to a Buffer representation of the coordinates.
200
201
  * @returns A Buffer representation of the Point instance.
201
- * @dev Note that toBuffer does not include the isInfinite flag and other serialization methods do (e.g. toFields).
202
- * This is because currently when we work with point as bytes we don't want to populate the extra bytes for
203
- * isInfinite flag because:
204
- * 1. Our Grumpkin BB API currently does not handle point at infinity,
205
- * 2. we use toBuffer when serializing notes and events and there we only work with public keys and point at infinity
206
- * 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).
207
203
  */
208
204
  toBuffer() {
209
- if (this.isInfinite) {
210
- throw new Error('Cannot serialize infinite point with isInfinite flag');
211
- }
212
205
  const buf = serializeToBuffer([this.x, this.y]);
213
206
  if (buf.length !== Point.SIZE_IN_BYTES) {
214
207
  throw new Error(`Invalid buffer length for Point: ${buf.length}`);
@@ -258,12 +251,10 @@ export class Point {
258
251
  }
259
252
 
260
253
  toNoirStruct() {
261
- /* eslint-disable camelcase */
262
- return { x: this.x, y: this.y, is_infinite: this.isInfinite };
263
- /* eslint-enable camelcase */
254
+ return { x: this.x, y: this.y };
264
255
  }
265
256
 
266
- // Used for IvpkM, OvpkM, NpkM and TpkM. TODO(#8124): Consider removing this method.
257
+ // Used for IvpkM. TODO(#8124): Consider removing this method.
267
258
  toWrappedNoirStruct() {
268
259
  return { inner: this.toNoirStruct() };
269
260
  }
@@ -283,21 +274,13 @@ export class Point {
283
274
  return this.x.isZero() && this.y.isZero();
284
275
  }
285
276
 
286
- hash() {
287
- return poseidon2Hash(this.toFields());
288
- }
289
-
290
277
  /**
291
- * Check if this is point at infinity.
292
- * 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
293
281
  */
294
- public get inf() {
295
- return this.isInfinite;
296
- }
297
-
298
- isOnGrumpkin() {
299
- // TODO: Check this against how bb handles curve check and infinity point check
300
- if (this.inf) {
282
+ isOnCurve() {
283
+ if (this.isInfinite) {
301
284
  return true;
302
285
  }
303
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);
@@ -1,8 +1,10 @@
1
1
  import { Buffer32 } from '@aztec/foundation/buffer';
2
2
  import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
3
3
 
4
+ import { secp256k1 } from '@noble/curves/secp256k1';
4
5
  import { z } from 'zod';
5
6
 
7
+ import { randomBytes } from '../crypto/random/index.js';
6
8
  import { hasHexPrefix, hexToBuffer } from '../string/index.js';
7
9
 
8
10
  /**
@@ -77,8 +79,12 @@ export class Signature {
77
79
  return new Signature(Buffer32.fromBuffer(hexToBuffer(sig.r)), Buffer32.fromBuffer(hexToBuffer(sig.s)), sig.yParity);
78
80
  }
79
81
 
82
+ /** Generates a random valid ECDSA signature with a low s-value by signing a random message with a random key. */
80
83
  static random(): Signature {
81
- return new Signature(Buffer32.random(), Buffer32.random(), 1);
84
+ const privateKey = randomBytes(32);
85
+ const message = randomBytes(32);
86
+ const { r, s, recovery } = secp256k1.sign(message, privateKey);
87
+ return new Signature(Buffer32.fromBigInt(r), Buffer32.fromBigInt(s), recovery ? 28 : 27);
82
88
  }
83
89
 
84
90
  static empty(): Signature {
@@ -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';
@@ -1,3 +1,4 @@
1
+ import { parseBooleanEnv } from '@aztec/foundation/config';
1
2
  import { overwriteLoggingStream, pinoPrettyOpts } from '@aztec/foundation/log';
2
3
 
3
4
  import pretty from 'pino-pretty';
@@ -6,4 +7,33 @@ import pretty from 'pino-pretty';
6
7
  // file so we don't mess up with dependencies in non-testing environments,
7
8
  // since pino-pretty messes up with browser bundles.
8
9
  // See also https://www.npmjs.com/package/pino-pretty?activeTab=readme#user-content-usage-with-jest
9
- overwriteLoggingStream(pretty(pinoPrettyOpts));
10
+ if (!parseBooleanEnv(process.env.LOG_JSON)) {
11
+ overwriteLoggingStream(pretty(pinoPrettyOpts));
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
+ }
@@ -43,17 +43,18 @@ export async function defaultFetch(
43
43
  }
44
44
 
45
45
  let responseJson;
46
+ const responseText = await resp.text();
46
47
  try {
47
- responseJson = await resp.json();
48
+ responseJson = JSON.parse(responseText);
48
49
  } catch {
49
50
  if (!resp.ok) {
50
51
  throw new Error(resp.statusText);
51
52
  }
52
- throw new Error(`Failed to parse body as JSON: ${await resp.text()}`);
53
+ throw new Error(`Failed to parse body as JSON: ${responseText}`);
53
54
  }
54
55
 
55
56
  if (!resp.ok) {
56
- const errorMessage = `Error ${resp.status} from server ${host}: ${responseJson.error.message}`;
57
+ const errorMessage = `Error ${resp.status} from server ${host}: ${responseJson?.error?.message ?? JSON.stringify(responseJson)}`;
57
58
  if (noRetry || (resp.status >= 400 && resp.status < 500)) {
58
59
  throw new NoRetryError(errorMessage);
59
60
  } else {
@@ -2,7 +2,7 @@ import { format } from 'util';
2
2
 
3
3
  import { type Logger, createLogger } from '../../log/pino-logger.js';
4
4
  import { type PromiseWithResolvers, promiseWithResolvers } from '../../promise/utils.js';
5
- import { type ApiSchema, type ApiSchemaFor, schemaHasMethod } from '../../schemas/api.js';
5
+ import { type ApiSchema, type ApiSchemaFor, getSchemaReturnType, schemaHasMethod } from '../../schemas/api.js';
6
6
  import { jsonStringify } from '../convert.js';
7
7
  import { type JsonRpcFetch, defaultFetch } from './fetch.js';
8
8
 
@@ -24,6 +24,7 @@ export type SafeJsonRpcClientOptions = {
24
24
  batchWindowMS?: number;
25
25
  maxBatchSize?: number;
26
26
  maxRequestBodySize?: number;
27
+ extraHeaders?: Record<string, string>;
27
28
  onResponse?: (res: {
28
29
  response: any;
29
30
  headers: { get: (header: string) => string | null | undefined };
@@ -129,6 +130,7 @@ export function createSafeJsonRpcClient<T extends object>(
129
130
  const { response, headers } = await fetch(
130
131
  host,
131
132
  rpcCalls.map(({ request }) => request),
133
+ config.extraHeaders,
132
134
  );
133
135
 
134
136
  if (config.onResponse) {
@@ -234,7 +236,7 @@ export function createSafeJsonRpcClient<T extends object>(
234
236
  if ([null, undefined, 'null', 'undefined'].includes(response.result)) {
235
237
  return;
236
238
  }
237
- return (schema as ApiSchema)[methodName].returnType().parseAsync(response.result);
239
+ return getSchemaReturnType((schema as ApiSchema)[methodName]).parseAsync(response.result);
238
240
  };
239
241
 
240
242
  const clientId = nextClientId++;
@@ -1,3 +1,5 @@
1
+ import { promisify } from 'node:util';
2
+ import { gunzip as gunzipCb, gzip as gzipCb } from 'node:zlib';
1
3
  import { Agent, type Dispatcher } from 'undici';
2
4
 
3
5
  import { createLogger } from '../../log/pino-logger.js';
@@ -5,8 +7,14 @@ import { NoRetryError } from '../../retry/index.js';
5
7
  import { jsonStringify } from '../convert.js';
6
8
  import type { JsonRpcFetch } from './fetch.js';
7
9
 
10
+ const gzip = promisify(gzipCb);
11
+ const gunzip = promisify(gunzipCb);
12
+
8
13
  const log = createLogger('json-rpc:json_rpc_client:undici');
9
14
 
15
+ /** Minimum request size in bytes to trigger compression. */
16
+ const COMPRESSION_THRESHOLD = 1024;
17
+
10
18
  export { Agent };
11
19
 
12
20
  export function makeUndiciFetch(client = new Agent()): JsonRpcFetch {
@@ -14,14 +22,18 @@ export function makeUndiciFetch(client = new Agent()): JsonRpcFetch {
14
22
  log.trace(`JsonRpcClient.fetch: ${host}`, { host, body });
15
23
  let resp: Dispatcher.ResponseData;
16
24
  try {
25
+ const jsonBody = Buffer.from(jsonStringify(body));
26
+ const shouldCompress = jsonBody.length >= COMPRESSION_THRESHOLD;
17
27
  resp = await client.request({
18
28
  method: 'POST',
19
29
  origin: new URL(host),
20
30
  path: '/',
21
- body: jsonStringify(body),
31
+ body: shouldCompress ? await gzip(jsonBody) : jsonBody,
22
32
  headers: {
23
33
  ...extraHeaders,
24
34
  'content-type': 'application/json',
35
+ ...(shouldCompress && { 'content-encoding': 'gzip' }),
36
+ 'accept-encoding': 'gzip',
25
37
  },
26
38
  });
27
39
  } catch (err) {
@@ -31,13 +43,21 @@ export function makeUndiciFetch(client = new Agent()): JsonRpcFetch {
31
43
 
32
44
  let responseJson: any;
33
45
  const responseOk = resp.statusCode >= 200 && resp.statusCode <= 299;
46
+ const contentEncoding = resp.headers['content-encoding'];
47
+ let responseText: string;
34
48
  try {
35
- responseJson = await resp.body.json();
49
+ if (contentEncoding === 'gzip') {
50
+ const jsonBuffer = await gunzip(await resp.body.arrayBuffer());
51
+ responseText = jsonBuffer.toString('utf-8');
52
+ } else {
53
+ responseText = await resp.body.text();
54
+ }
55
+ responseJson = JSON.parse(responseText);
36
56
  } catch {
37
57
  if (!responseOk) {
38
58
  throw new Error('HTTP ' + resp.statusCode);
39
59
  }
40
- throw new Error(`Failed to parse body as JSON: ${await resp.body.text()}`);
60
+ throw new Error(`Failed to parse body as JSON. encoding: ${contentEncoding}, body: ${responseText!}`);
41
61
  }
42
62
 
43
63
  if (!responseOk) {
@@ -130,14 +130,14 @@ export class TestState implements TestStateApi {
130
130
  }
131
131
 
132
132
  export const TestStateSchema: ApiSchemaFor<TestStateApi> = {
133
- getNote: z.function().args(z.number()).returns(TestNote.schema.optional()),
134
- getNotes: z.function().args(optional(schemas.Integer)).returns(z.array(TestNote.schema)),
135
- getNotes2: z.function().args(optional(schemas.BigInt)).returns(z.array(TestNote.schema)),
136
- getNotes3: z.function().args(optional(schemas.Integer)).returns(z.array(TestNote.schema)),
137
- clear: z.function().returns(z.void()),
138
- addNotes: z.function().args(z.array(TestNote.schema)).returns(z.array(TestNote.schema)),
139
- fail: z.function().returns(z.void()),
140
- count: z.function().returns(z.number()),
141
- getStatus: z.function().returns(z.object({ status: z.string(), count: schemas.BigInt })),
142
- getTuple: z.function().returns(z.tuple([z.string(), optional(z.string()), z.number()])),
133
+ getNote: z.function({ input: z.tuple([z.number()]), output: TestNote.schema.optional() }),
134
+ getNotes: z.function({ input: z.tuple([optional(schemas.Integer)]), output: z.array(TestNote.schema) }),
135
+ getNotes2: z.function({ input: z.tuple([optional(schemas.BigInt)]), output: z.array(TestNote.schema) }),
136
+ getNotes3: z.function({ input: z.tuple([optional(schemas.Integer)]), output: z.array(TestNote.schema) }),
137
+ clear: z.function({ input: z.tuple([]), output: z.void() }),
138
+ addNotes: z.function({ input: z.tuple([z.array(TestNote.schema)]), output: z.array(TestNote.schema) }),
139
+ fail: z.function({ input: z.tuple([]), output: z.void() }),
140
+ count: z.function({ input: z.tuple([]), output: z.number() }),
141
+ getStatus: z.function({ input: z.tuple([]), output: z.object({ status: z.string(), count: schemas.BigInt }) }),
142
+ getTuple: z.function({ input: z.tuple([]), output: z.tuple([z.string(), optional(z.string()), z.number()]) }),
143
143
  };
@@ -0,0 +1,63 @@
1
+ import { timingSafeEqual } from 'crypto';
2
+ import type Koa from 'koa';
3
+
4
+ import { sha256 } from '../../crypto/sha256/index.js';
5
+ import { createLogger } from '../../log/index.js';
6
+
7
+ const log = createLogger('json-rpc:api-key-auth');
8
+
9
+ /**
10
+ * Computes the SHA-256 hash of a string and returns it as a Buffer.
11
+ * @param input - The input string to hash.
12
+ * @returns The SHA-256 hash as a Buffer.
13
+ */
14
+ export function sha256Hash(input: string): Buffer {
15
+ return sha256(Buffer.from(input));
16
+ }
17
+
18
+ /**
19
+ * Creates a Koa middleware that enforces API key authentication on all requests
20
+ * except the health check endpoint (GET /status).
21
+ *
22
+ * The API key can be provided via the `x-api-key` header or the `Authorization: Bearer <key>` header.
23
+ * Comparison is done by hashing the provided key with SHA-256 and comparing against the stored hash.
24
+ *
25
+ * @param apiKeyHash - The SHA-256 hash of the expected API key as a Buffer.
26
+ * @returns A Koa middleware that rejects requests without a valid API key.
27
+ */
28
+ export function getApiKeyAuthMiddleware(
29
+ apiKeyHash: Buffer,
30
+ ): (ctx: Koa.Context, next: () => Promise<void>) => Promise<void> {
31
+ return async (ctx: Koa.Context, next: () => Promise<void>) => {
32
+ // Allow health check through without auth
33
+ if (ctx.path === '/status' && ctx.method === 'GET') {
34
+ return next();
35
+ }
36
+
37
+ const providedKey = ctx.get('x-api-key') || ctx.get('authorization')?.replace(/^Bearer\s+/i, '');
38
+ if (!providedKey) {
39
+ log.warn(`Rejected admin RPC request from ${ctx.ip}: missing API key`);
40
+ ctx.status = 401;
41
+ ctx.body = {
42
+ jsonrpc: '2.0',
43
+ id: null,
44
+ error: { code: -32000, message: 'Unauthorized: invalid or missing API key' },
45
+ };
46
+ return;
47
+ }
48
+
49
+ const providedHashBuf = sha256Hash(providedKey);
50
+ if (!timingSafeEqual(apiKeyHash, providedHashBuf)) {
51
+ log.warn(`Rejected admin RPC request from ${ctx.ip}: invalid API key`);
52
+ ctx.status = 401;
53
+ ctx.body = {
54
+ jsonrpc: '2.0',
55
+ id: null,
56
+ error: { code: -32000, message: 'Unauthorized: invalid or missing API key' },
57
+ };
58
+ return;
59
+ }
60
+
61
+ await next();
62
+ };
63
+ }
@@ -1 +1,2 @@
1
+ export * from './api_key_auth.js';
1
2
  export * from './safe_json_rpc_server.js';