@aztec/foundation 0.0.1-commit.c2595eba → 0.0.1-commit.c2eed6949

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 (115) 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/branded-types/slot.d.ts +4 -1
  5. package/dest/branded-types/slot.d.ts.map +1 -1
  6. package/dest/branded-types/slot.js +3 -0
  7. package/dest/buffer/index.d.ts +2 -1
  8. package/dest/buffer/index.d.ts.map +1 -1
  9. package/dest/buffer/index.js +1 -0
  10. package/dest/buffer/utils.d.ts +3 -0
  11. package/dest/buffer/utils.d.ts.map +1 -0
  12. package/dest/buffer/utils.js +7 -0
  13. package/dest/config/env_var.d.ts +2 -2
  14. package/dest/config/env_var.d.ts.map +1 -1
  15. package/dest/config/index.d.ts +1 -1
  16. package/dest/config/index.d.ts.map +1 -1
  17. package/dest/config/index.js +15 -0
  18. package/dest/config/network_config.d.ts +19 -1
  19. package/dest/config/network_config.d.ts.map +1 -1
  20. package/dest/config/network_config.js +4 -1
  21. package/dest/config/network_name.d.ts +2 -2
  22. package/dest/config/network_name.d.ts.map +1 -1
  23. package/dest/config/network_name.js +2 -0
  24. package/dest/crypto/poseidon/index.d.ts +1 -1
  25. package/dest/crypto/poseidon/index.d.ts.map +1 -1
  26. package/dest/crypto/poseidon/index.js +40 -33
  27. package/dest/crypto/secp256k1-signer/utils.d.ts +12 -1
  28. package/dest/crypto/secp256k1-signer/utils.d.ts.map +1 -1
  29. package/dest/crypto/secp256k1-signer/utils.js +26 -0
  30. package/dest/curves/bn254/field.d.ts +2 -1
  31. package/dest/curves/bn254/field.d.ts.map +1 -1
  32. package/dest/curves/bn254/field.js +5 -2
  33. package/dest/eth-signature/eth_signature.d.ts +2 -1
  34. package/dest/eth-signature/eth_signature.d.ts.map +1 -1
  35. package/dest/eth-signature/eth_signature.js +7 -2
  36. package/dest/fifo/fifo_frame_reader.d.ts +41 -0
  37. package/dest/fifo/fifo_frame_reader.d.ts.map +1 -0
  38. package/dest/fifo/fifo_frame_reader.js +74 -0
  39. package/dest/fifo/index.d.ts +2 -0
  40. package/dest/fifo/index.d.ts.map +1 -0
  41. package/dest/fifo/index.js +1 -0
  42. package/dest/jest/setup.js +24 -0
  43. package/dest/json-rpc/client/safe_json_rpc_client.d.ts +2 -1
  44. package/dest/json-rpc/client/safe_json_rpc_client.d.ts.map +1 -1
  45. package/dest/json-rpc/client/safe_json_rpc_client.js +1 -1
  46. package/dest/json-rpc/server/api_key_auth.d.ts +19 -0
  47. package/dest/json-rpc/server/api_key_auth.d.ts.map +1 -0
  48. package/dest/json-rpc/server/api_key_auth.js +57 -0
  49. package/dest/json-rpc/server/index.d.ts +2 -1
  50. package/dest/json-rpc/server/index.d.ts.map +1 -1
  51. package/dest/json-rpc/server/index.js +1 -0
  52. package/dest/log/bigint-utils.d.ts +5 -0
  53. package/dest/log/bigint-utils.d.ts.map +1 -0
  54. package/dest/log/bigint-utils.js +21 -0
  55. package/dest/log/gcloud-logger-config.d.ts +1 -1
  56. package/dest/log/gcloud-logger-config.d.ts.map +1 -1
  57. package/dest/log/gcloud-logger-config.js +3 -0
  58. package/dest/log/log-filters.d.ts +17 -4
  59. package/dest/log/log-filters.d.ts.map +1 -1
  60. package/dest/log/log-filters.js +26 -12
  61. package/dest/log/pino-logger.d.ts +1 -1
  62. package/dest/log/pino-logger.d.ts.map +1 -1
  63. package/dest/log/pino-logger.js +6 -2
  64. package/dest/queue/base_memory_queue.d.ts +2 -2
  65. package/dest/queue/base_memory_queue.d.ts.map +1 -1
  66. package/dest/serialize/buffer_reader.d.ts +8 -1
  67. package/dest/serialize/buffer_reader.d.ts.map +1 -1
  68. package/dest/serialize/buffer_reader.js +13 -0
  69. package/dest/serialize/serialize.d.ts +19 -1
  70. package/dest/serialize/serialize.d.ts.map +1 -1
  71. package/dest/serialize/serialize.js +31 -0
  72. package/dest/sleep/index.d.ts +2 -1
  73. package/dest/sleep/index.d.ts.map +1 -1
  74. package/dest/sleep/index.js +10 -1
  75. package/dest/timer/date.d.ts +25 -1
  76. package/dest/timer/date.d.ts.map +1 -1
  77. package/dest/timer/date.js +33 -0
  78. package/dest/transport/transport_client.js +2 -2
  79. package/dest/trees/indexed_merkle_tree_calculator.d.ts +1 -1
  80. package/dest/trees/indexed_merkle_tree_calculator.d.ts.map +1 -1
  81. package/dest/trees/indexed_merkle_tree_calculator.js +5 -1
  82. package/dest/types/index.d.ts +3 -1
  83. package/dest/types/index.d.ts.map +1 -1
  84. package/dest/types/index.js +3 -0
  85. package/package.json +23 -2
  86. package/src/array/sorted_array.ts +22 -17
  87. package/src/branded-types/slot.ts +5 -0
  88. package/src/buffer/index.ts +1 -0
  89. package/src/buffer/utils.ts +8 -0
  90. package/src/config/env_var.ts +52 -6
  91. package/src/config/index.ts +15 -0
  92. package/src/config/network_config.ts +3 -0
  93. package/src/config/network_name.ts +4 -1
  94. package/src/crypto/poseidon/index.ts +42 -34
  95. package/src/crypto/secp256k1-signer/utils.ts +32 -0
  96. package/src/curves/bn254/field.ts +6 -2
  97. package/src/eth-signature/eth_signature.ts +7 -1
  98. package/src/fifo/fifo_frame_reader.ts +98 -0
  99. package/src/fifo/index.ts +1 -0
  100. package/src/jest/setup.mjs +27 -0
  101. package/src/json-rpc/client/safe_json_rpc_client.ts +2 -0
  102. package/src/json-rpc/server/api_key_auth.ts +63 -0
  103. package/src/json-rpc/server/index.ts +1 -0
  104. package/src/log/bigint-utils.ts +25 -0
  105. package/src/log/gcloud-logger-config.ts +5 -0
  106. package/src/log/log-filters.ts +29 -11
  107. package/src/log/pino-logger.ts +6 -2
  108. package/src/queue/base_memory_queue.ts +1 -1
  109. package/src/serialize/buffer_reader.ts +15 -0
  110. package/src/serialize/serialize.ts +32 -0
  111. package/src/sleep/index.ts +10 -1
  112. package/src/timer/date.ts +48 -0
  113. package/src/transport/transport_client.ts +2 -2
  114. package/src/trees/indexed_merkle_tree_calculator.ts +5 -1
  115. package/src/types/index.ts +5 -0
@@ -21,34 +21,39 @@ export function dedupeSortedArray<T>(arr: T[], cmp: Cmp<T>): void {
21
21
  }
22
22
 
23
23
  export function insertIntoSortedArray<T>(arr: T[], item: T, cmp: Cmp<T>, allowDuplicates = true): boolean {
24
+ const index = findInsertionIndexInSortedArray(arr, item, cmp);
25
+
26
+ if (!allowDuplicates) {
27
+ // Check element before insertion point (upper bound returns index after equal elements)
28
+ if (index > 0 && cmp(arr[index - 1], item) === 0) {
29
+ return false;
30
+ }
31
+ }
32
+
33
+ arr.splice(index, 0, item);
34
+ return true;
35
+ }
36
+
37
+ /**
38
+ * Finds the index where needle would be inserted to maintain sorted order.
39
+ * Returns the count of elements less than or equal to needle.
40
+ */
41
+ export function findInsertionIndexInSortedArray<T, N>(values: T[], needle: N, cmp: (a: T, b: N) => number): number {
24
42
  let start = 0;
25
- let end = arr.length;
43
+ let end = values.length;
26
44
 
27
45
  while (start < end) {
28
46
  const mid = start + (((end - start) / 2) | 0);
29
- const comparison = cmp(arr[mid], item);
47
+ const comparison = cmp(values[mid], needle);
30
48
 
31
- if (comparison < 0) {
49
+ if (comparison <= 0) {
32
50
  start = mid + 1;
33
51
  } else {
34
52
  end = mid;
35
53
  }
36
54
  }
37
55
 
38
- if (!allowDuplicates) {
39
- // Check element at insertion point
40
- if (start < arr.length && cmp(arr[start], item) === 0) {
41
- return false;
42
- }
43
-
44
- // Check element before insertion point (in case we landed after duplicates)
45
- if (start > 0 && cmp(arr[start - 1], item) === 0) {
46
- return false;
47
- }
48
- }
49
-
50
- arr.splice(start, 0, item);
51
- return true;
56
+ return start;
52
57
  }
53
58
 
54
59
  export function findIndexInSortedArray<T, N>(values: T[], needle: N, cmp: (a: T, b: N) => number): number {
@@ -73,6 +73,11 @@ SlotNumber.isValid = function (value: unknown): value is SlotNumber {
73
73
  return typeof value === 'number' && Number.isInteger(value) && value >= 0;
74
74
  };
75
75
 
76
+ /** Increments a SlotNumber by a given value. */
77
+ SlotNumber.add = function (sn: SlotNumber, increment: number): SlotNumber {
78
+ return SlotNumber(sn + increment);
79
+ };
80
+
76
81
  /**
77
82
  * The zero slot value.
78
83
  */
@@ -1,2 +1,3 @@
1
1
  export * from './buffer32.js';
2
2
  export * from './buffer16.js';
3
+ export * from './utils.js';
@@ -0,0 +1,8 @@
1
+ /** Returns the number of bytes in the buffer, excluding any trailing zero bytes. */
2
+ export function trimmedBytesLength(buf: Uint8Array): number {
3
+ let end = buf.length;
4
+ while (end > 0 && buf[end - 1] === 0) {
5
+ end--;
6
+ }
7
+ return end;
8
+ }
@@ -12,6 +12,9 @@ export type EnvVar =
12
12
  | 'ARCHIVER_VIEM_POLLING_INTERVAL_MS'
13
13
  | 'ARCHIVER_BATCH_SIZE'
14
14
  | 'AZTEC_ADMIN_PORT'
15
+ | 'AZTEC_ADMIN_API_KEY_HASH'
16
+ | 'AZTEC_DISABLE_ADMIN_API_KEY'
17
+ | 'AZTEC_RESET_ADMIN_API_KEY'
15
18
  | 'AZTEC_NODE_ADMIN_URL'
16
19
  | 'AZTEC_NODE_URL'
17
20
  | 'AZTEC_PORT'
@@ -20,6 +23,8 @@ export type EnvVar =
20
23
  | 'BB_WORKING_DIRECTORY'
21
24
  | 'BB_NUM_IVC_VERIFIERS'
22
25
  | 'BB_IVC_CONCURRENCY'
26
+ | 'BB_CHONK_VERIFY_MAX_BATCH'
27
+ | 'BB_CHONK_VERIFY_BATCH_CONCURRENCY'
23
28
  | 'BOOTSTRAP_NODES'
24
29
  | 'BLOB_ARCHIVE_API_URL'
25
30
  | 'BLOB_FILE_STORE_URLS'
@@ -47,7 +52,10 @@ export type EnvVar =
47
52
  | 'BOT_TX_MINED_WAIT_SECONDS'
48
53
  | 'BOT_MAX_CONSECUTIVE_ERRORS'
49
54
  | 'BOT_STOP_WHEN_UNHEALTHY'
50
- | 'BOT_AMM_TXS'
55
+ | 'BOT_MODE'
56
+ | 'BOT_L2_TO_L1_MESSAGES_PER_TX'
57
+ | 'BOT_L1_TO_L2_SEED_COUNT'
58
+ | 'BOT_L1_TO_L2_SEED_INTERVAL'
51
59
  | 'COINBASE'
52
60
  | 'CRS_PATH'
53
61
  | 'DATA_DIRECTORY'
@@ -56,6 +64,7 @@ export type EnvVar =
56
64
  | 'BLOB_SINK_MAP_SIZE_KB'
57
65
  | 'P2P_STORE_MAP_SIZE_KB'
58
66
  | 'PROVER_BROKER_STORE_MAP_SIZE_KB'
67
+ | 'SIGNING_PROTECTION_MAP_SIZE_KB'
59
68
  | 'WS_DB_MAP_SIZE_KB'
60
69
  | 'ARCHIVE_TREE_MAP_SIZE_KB'
61
70
  | 'NULLIFIER_TREE_MAP_SIZE_KB'
@@ -64,6 +73,7 @@ export type EnvVar =
64
73
  | 'PUBLIC_DATA_TREE_MAP_SIZE_KB'
65
74
  | 'DEBUG'
66
75
  | 'DEBUG_P2P_DISABLE_COLOCATION_PENALTY'
76
+ | 'ENABLE_PROVER_NODE'
67
77
  | 'ETHEREUM_HOSTS'
68
78
  | 'ETHEREUM_DEBUG_HOSTS'
69
79
  | 'ETHEREUM_ALLOW_NO_DEBUG_HOSTS'
@@ -73,8 +83,10 @@ export type EnvVar =
73
83
  | 'KEY_STORE_DIRECTORY'
74
84
  | 'L1_CHAIN_ID'
75
85
  | 'L1_CONSENSUS_HOST_URLS'
86
+ | 'ETHEREUM_HTTP_TIMEOUT_MS'
76
87
  | 'L1_CONSENSUS_HOST_API_KEYS'
77
88
  | 'L1_CONSENSUS_HOST_API_KEY_HEADERS'
89
+ | 'L1_TX_FAILED_STORE'
78
90
  | 'LOG_JSON'
79
91
  | 'LOG_MULTILINE'
80
92
  | 'LOG_NO_COLOR_PER_ACTOR'
@@ -100,6 +112,7 @@ export type EnvVar =
100
112
  | 'P2P_BATCH_TX_REQUESTER_TX_BATCH_SIZE'
101
113
  | 'P2P_BATCH_TX_REQUESTER_BAD_PEER_THRESHOLD'
102
114
  | 'P2P_BLOCK_CHECK_INTERVAL_MS'
115
+ | 'P2P_SLOT_CHECK_INTERVAL_MS'
103
116
  | 'P2P_BLOCK_REQUEST_BATCH_SIZE'
104
117
  | 'P2P_BOOTSTRAP_NODE_ENR_VERSION_CHECK'
105
118
  | 'P2P_BOOTSTRAP_NODES_AS_FULL_PEERS'
@@ -120,6 +133,7 @@ export type EnvVar =
120
133
  | 'P2P_L2_QUEUE_SIZE'
121
134
  | 'P2P_MAX_PEERS'
122
135
  | 'P2P_PEER_CHECK_INTERVAL_MS'
136
+ | 'P2P_PEER_FAILED_BAN_TIME_MS'
123
137
  | 'P2P_PEER_PENALTY_VALUES'
124
138
  | 'P2P_QUERY_FOR_IP'
125
139
  | 'P2P_REQRESP_INDIVIDUAL_REQUEST_TIMEOUT_MS'
@@ -140,9 +154,10 @@ export type EnvVar =
140
154
  | 'P2P_PREFERRED_PEERS'
141
155
  | 'P2P_MAX_PENDING_TX_COUNT'
142
156
  | 'P2P_SEEN_MSG_CACHE_SIZE'
143
- | 'P2P_DROP_TX'
144
157
  | 'P2P_DROP_TX_CHANCE'
145
158
  | 'P2P_TX_POOL_DELETE_TXS_AFTER_REORG'
159
+ | 'P2P_MIN_TX_POOL_AGE_MS'
160
+ | 'P2P_RPC_PRICE_BUMP_PERCENTAGE'
146
161
  | 'DEBUG_P2P_INSTRUMENT_MESSAGES'
147
162
  | 'PEER_ID_PRIVATE_KEY'
148
163
  | 'PEER_ID_PRIVATE_KEY_PATH'
@@ -156,8 +171,11 @@ export type EnvVar =
156
171
  | 'PROVER_BROKER_BATCH_INTERVAL_MS'
157
172
  | 'PROVER_BROKER_BATCH_SIZE'
158
173
  | 'PROVER_BROKER_MAX_EPOCHS_TO_KEEP_RESULTS_FOR'
174
+ | 'PROVER_BROKER_DEBUG_REPLAY_ENABLED'
159
175
  | 'PROVER_CANCEL_JOBS_ON_STOP'
176
+ | 'PROVER_ENQUEUE_CONCURRENCY'
160
177
  | 'PROVER_COORDINATION_NODE_URLS'
178
+ | 'PROVER_PROOF_STORE'
161
179
  | 'PROVER_FAILED_PROOF_STORE'
162
180
  | 'PROVER_NODE_FAILED_EPOCH_STORE'
163
181
  | 'PROVER_NODE_DISABLE_PROOF_PUBLISH'
@@ -189,25 +207,32 @@ export type EnvVar =
189
207
  | 'SENTINEL_ENABLED'
190
208
  | 'SENTINEL_HISTORY_LENGTH_IN_EPOCHS'
191
209
  | 'SENTINEL_HISTORIC_PROVEN_PERFORMANCE_LENGTH_IN_EPOCHS'
192
- | 'SEQ_MAX_BLOCK_SIZE_IN_BYTES'
210
+ | 'SEQ_ENABLE_PROPOSER_PIPELINING'
193
211
  | 'SEQ_MAX_TX_PER_BLOCK'
212
+ | 'SEQ_MAX_TX_PER_CHECKPOINT'
194
213
  | 'SEQ_MIN_TX_PER_BLOCK'
195
214
  | 'SEQ_PUBLISH_TXS_WITH_PROPOSALS'
196
215
  | 'SEQ_MAX_DA_BLOCK_GAS'
197
216
  | 'SEQ_MAX_L2_BLOCK_GAS'
217
+ | 'SEQ_PER_BLOCK_ALLOCATION_MULTIPLIER'
218
+ | 'SEQ_REDISTRIBUTE_CHECKPOINT_BUDGET'
198
219
  | 'SEQ_PUBLISHER_PRIVATE_KEY'
199
220
  | 'SEQ_PUBLISHER_PRIVATE_KEYS'
200
221
  | 'SEQ_PUBLISHER_ADDRESSES'
201
222
  | 'SEQ_PUBLISHER_ALLOW_INVALID_STATES'
202
223
  | 'SEQ_PUBLISHER_FORWARDER_ADDRESS'
224
+ | 'PUBLISHER_FUNDING_THRESHOLD'
225
+ | 'PUBLISHER_FUNDING_AMOUNT'
203
226
  | 'SEQ_POLLING_INTERVAL_MS'
204
227
  | 'SEQ_ENFORCE_TIME_TABLE'
205
228
  | 'SEQ_L1_PUBLISHING_TIME_ALLOWANCE_IN_SLOT'
206
229
  | 'SEQ_ATTESTATION_PROPAGATION_TIME'
207
230
  | 'SEQ_BLOCK_DURATION_MS'
231
+ | 'SEQ_EXPECTED_BLOCK_PROPOSALS_PER_SLOT'
208
232
  | 'SEQ_BUILD_CHECKPOINT_IF_EMPTY'
209
233
  | 'SEQ_SECONDS_BEFORE_INVALIDATING_BLOCK_AS_COMMITTEE_MEMBER'
210
234
  | 'SEQ_SECONDS_BEFORE_INVALIDATING_BLOCK_AS_NON_COMMITTEE_MEMBER'
235
+ | 'SEQ_SKIP_CHECKPOINT_PUBLISH_PERCENT'
211
236
  | 'SLASH_MIN_PENALTY_PERCENTAGE'
212
237
  | 'SLASH_MAX_PENALTY_PERCENTAGE'
213
238
  | 'SLASH_VALIDATORS_ALWAYS'
@@ -218,6 +243,8 @@ export type EnvVar =
218
243
  | 'SLASH_INACTIVITY_TARGET_PERCENTAGE'
219
244
  | 'SLASH_INACTIVITY_CONSECUTIVE_EPOCH_THRESHOLD'
220
245
  | 'SLASH_INVALID_BLOCK_PENALTY'
246
+ | 'SLASH_DUPLICATE_PROPOSAL_PENALTY'
247
+ | 'SLASH_DUPLICATE_ATTESTATION_PENALTY'
221
248
  | 'SLASH_OVERRIDE_PAYLOAD'
222
249
  | 'SLASH_PROPOSE_INVALID_ATTESTATIONS_PENALTY'
223
250
  | 'SLASH_ATTEST_DESCENDANT_OF_INVALID_PENALTY'
@@ -232,6 +259,7 @@ export type EnvVar =
232
259
  | 'TELEMETRY'
233
260
  | 'TEST_ACCOUNTS'
234
261
  | 'SPONSORED_FPC'
262
+ | 'PREFUND_ADDRESSES'
235
263
  | 'TX_COLLECTION_FAST_NODES_TIMEOUT_BEFORE_REQ_RESP_MS'
236
264
  | 'TX_COLLECTION_SLOW_NODES_INTERVAL_MS'
237
265
  | 'TX_COLLECTION_SLOW_REQ_RESP_INTERVAL_MS'
@@ -242,12 +270,29 @@ export type EnvVar =
242
270
  | 'TX_COLLECTION_FAST_MAX_PARALLEL_REQUESTS_PER_NODE'
243
271
  | 'TX_COLLECTION_NODE_RPC_MAX_BATCH_SIZE'
244
272
  | 'TX_COLLECTION_NODE_RPC_URLS'
245
- | 'TX_COLLECTION_PROPOSAL_TX_COLLECTOR_TYPE'
273
+ | 'TX_COLLECTION_MISSING_TXS_COLLECTOR_TYPE'
274
+ | 'TX_COLLECTION_FILE_STORE_URLS'
275
+ | 'TX_COLLECTION_FILE_STORE_SLOW_DELAY_MS'
276
+ | 'TX_COLLECTION_FILE_STORE_FAST_DELAY_MS'
277
+ | 'TX_COLLECTION_FILE_STORE_FAST_WORKER_COUNT'
278
+ | 'TX_COLLECTION_FILE_STORE_SLOW_WORKER_COUNT'
279
+ | 'TX_COLLECTION_FILE_STORE_FAST_BACKOFF_BASE_MS'
280
+ | 'TX_COLLECTION_FILE_STORE_SLOW_BACKOFF_BASE_MS'
281
+ | 'TX_COLLECTION_FILE_STORE_FAST_BACKOFF_MAX_MS'
282
+ | 'TX_COLLECTION_FILE_STORE_SLOW_BACKOFF_MAX_MS'
283
+ | 'TX_FILE_STORE_URL'
284
+ | 'TX_FILE_STORE_UPLOAD_CONCURRENCY'
285
+ | 'TX_FILE_STORE_MAX_QUEUE_SIZE'
286
+ | 'TX_FILE_STORE_ENABLED'
246
287
  | 'TX_PUBLIC_SETUP_ALLOWLIST'
247
288
  | 'TXE_PORT'
248
289
  | 'TRANSACTIONS_DISABLED'
249
290
  | 'VALIDATOR_ATTESTATIONS_POLLING_INTERVAL_MS'
250
291
  | 'VALIDATOR_DISABLED'
292
+ | 'VALIDATOR_MAX_DA_BLOCK_GAS'
293
+ | 'VALIDATOR_MAX_L2_BLOCK_GAS'
294
+ | 'VALIDATOR_MAX_TX_PER_BLOCK'
295
+ | 'VALIDATOR_MAX_TX_PER_CHECKPOINT'
251
296
  | 'VALIDATOR_PRIVATE_KEYS'
252
297
  | 'VALIDATOR_PRIVATE_KEY'
253
298
  | 'VALIDATOR_REEXECUTE'
@@ -257,6 +302,7 @@ export type EnvVar =
257
302
  | 'WS_BLOCK_REQUEST_BATCH_SIZE'
258
303
  | 'L1_READER_VIEM_POLLING_INTERVAL_MS'
259
304
  | 'WS_DATA_DIRECTORY'
305
+ | 'WS_NUM_HISTORIC_CHECKPOINTS'
260
306
  | 'WS_NUM_HISTORIC_BLOCKS'
261
307
  | 'ETHEREUM_SLOT_DURATION'
262
308
  | 'AZTEC_SLOT_DURATION'
@@ -311,9 +357,8 @@ export type EnvVar =
311
357
  | 'K8S_POD_NAME'
312
358
  | 'K8S_POD_UID'
313
359
  | 'K8S_NAMESPACE_NAME'
360
+ | 'ENABLE_VERSION_CHECK'
314
361
  | 'VALIDATOR_REEXECUTE_DEADLINE_MS'
315
- | 'AUTO_UPDATE'
316
- | 'AUTO_UPDATE_URL'
317
362
  | 'WEB3_SIGNER_URL'
318
363
  | 'SKIP_ARCHIVER_INITIAL_SYNC'
319
364
  | 'BLOB_ALLOW_EMPTY_SOURCES'
@@ -326,6 +371,7 @@ export type EnvVar =
326
371
  | 'VALIDATOR_HA_POLLING_INTERVAL_MS'
327
372
  | 'VALIDATOR_HA_SIGNING_TIMEOUT_MS'
328
373
  | 'VALIDATOR_HA_MAX_STUCK_DUTIES_AGE_MS'
374
+ | 'VALIDATOR_HA_OLD_DUTIES_MAX_AGE_H'
329
375
  | 'VALIDATOR_HA_DATABASE_URL'
330
376
  | 'VALIDATOR_HA_RUN_MIGRATIONS'
331
377
  | 'VALIDATOR_HA_POOL_MAX'
@@ -177,6 +177,21 @@ export function bigintConfigHelper(defaultVal?: bigint): Pick<ConfigMapping, 'pa
177
177
  if (val === '') {
178
178
  return defaultVal;
179
179
  }
180
+ // Handle scientific notation (e.g. "1e+23", "2E23") which BigInt() doesn't accept directly.
181
+ // We parse it losslessly using bigint arithmetic instead of going through float64.
182
+ if (/[eE]/.test(val)) {
183
+ const match = val.match(/^(-?\d+(?:\.(\d+))?)[eE]([+-]?\d+)$/);
184
+ if (!match) {
185
+ throw new Error(`Cannot convert '${val}' to a BigInt`);
186
+ }
187
+ const digits = match[1].replace('.', '');
188
+ const decimalPlaces = match[2]?.length ?? 0;
189
+ const exponent = parseInt(match[3], 10) - decimalPlaces;
190
+ if (exponent < 0) {
191
+ throw new Error(`Cannot convert '${val}' to a BigInt: result is not an integer`);
192
+ }
193
+ return BigInt(digits) * 10n ** BigInt(exponent);
194
+ }
180
195
  return BigInt(val);
181
196
  },
182
197
  defaultValue: defaultVal,
@@ -5,10 +5,13 @@ export const NetworkConfigSchema = z
5
5
  bootnodes: z.array(z.string()),
6
6
  snapshots: z.array(z.string()),
7
7
  blobFileStoreUrls: z.array(z.string()).optional(),
8
+ txCollectionFileStoreUrls: z.array(z.string()).optional(),
8
9
  registryAddress: z.string(),
9
10
  feeAssetHandlerAddress: z.string().optional(),
10
11
  l1ChainId: z.number(),
11
12
  blockDurationMs: z.number().positive().optional(),
13
+ txPublicSetupAllowListExtend: z.string().optional(),
14
+ nodeVersion: z.string().optional(),
12
15
  })
13
16
  .passthrough(); // Allow additional unknown fields to pass through
14
17
 
@@ -5,7 +5,8 @@ export type NetworkNames =
5
5
  | 'testnet'
6
6
  | 'mainnet'
7
7
  | 'next-net'
8
- | 'devnet';
8
+ | 'devnet'
9
+ | `v${number}-devnet-${number}`;
9
10
 
10
11
  export function getActiveNetworkName(name?: string): NetworkNames {
11
12
  const network = name || process.env.NETWORK;
@@ -23,6 +24,8 @@ export function getActiveNetworkName(name?: string): NetworkNames {
23
24
  return 'next-net';
24
25
  } else if (network === 'devnet') {
25
26
  return 'devnet';
27
+ } else if (/^v\d+-devnet-\d+$/.test(network)) {
28
+ return network as `v${number}-devnet-${number}`;
26
29
  }
27
30
  throw new Error(`Unknown network: ${network}`);
28
31
  }
@@ -1,21 +1,35 @@
1
- import { BarretenbergSync } from '@aztec/bb.js';
1
+ import { Barretenberg, BarretenbergSync } from '@aztec/bb.js';
2
2
 
3
3
  import { Fr } from '../../curves/bn254/field.js';
4
4
  import { type Fieldable, serializeToFields } from '../../serialize/serialize.js';
5
5
 
6
+ const IS_BROWSER = typeof self !== 'undefined';
7
+
8
+ async function poseidon2HashFields(inputFields: Fr[]): Promise<Fr> {
9
+ if (IS_BROWSER) {
10
+ await BarretenbergSync.initSingleton();
11
+ const api = BarretenbergSync.getSingleton();
12
+ const response = api.poseidon2Hash({
13
+ inputs: inputFields.map(i => i.toBuffer()),
14
+ });
15
+ return Fr.fromBuffer(Buffer.from(response.hash));
16
+ } else {
17
+ await Barretenberg.initSingleton();
18
+ const api = Barretenberg.getSingleton();
19
+ const response = await api.poseidon2Hash({
20
+ inputs: inputFields.map(i => i.toBuffer()),
21
+ });
22
+ return Fr.fromBuffer(Buffer.from(response.hash));
23
+ }
24
+ }
25
+
6
26
  /**
7
27
  * Create a poseidon hash (field) from an array of input fields.
8
28
  * @param input - The input fields to hash.
9
29
  * @returns The poseidon hash.
10
30
  */
11
- export async function poseidon2Hash(input: Fieldable[]): Promise<Fr> {
12
- const inputFields = serializeToFields(input);
13
- await BarretenbergSync.initSingleton();
14
- const api = BarretenbergSync.getSingleton();
15
- const response = api.poseidon2Hash({
16
- inputs: inputFields.map(i => i.toBuffer()),
17
- });
18
- return Fr.fromBuffer(Buffer.from(response.hash));
31
+ export function poseidon2Hash(input: Fieldable[]): Promise<Fr> {
32
+ return poseidon2HashFields(serializeToFields(input));
19
33
  }
20
34
 
21
35
  /**
@@ -24,15 +38,10 @@ export async function poseidon2Hash(input: Fieldable[]): Promise<Fr> {
24
38
  * @param separator - The domain separator.
25
39
  * @returns The poseidon hash.
26
40
  */
27
- export async function poseidon2HashWithSeparator(input: Fieldable[], separator: number): Promise<Fr> {
41
+ export function poseidon2HashWithSeparator(input: Fieldable[], separator: number): Promise<Fr> {
28
42
  const inputFields = serializeToFields(input);
29
43
  inputFields.unshift(new Fr(separator));
30
- await BarretenbergSync.initSingleton();
31
- const api = BarretenbergSync.getSingleton();
32
- const response = api.poseidon2Hash({
33
- inputs: inputFields.map(i => i.toBuffer()),
34
- });
35
- return Fr.fromBuffer(Buffer.from(response.hash));
44
+ return poseidon2HashFields(inputFields);
36
45
  }
37
46
 
38
47
  /**
@@ -42,19 +51,24 @@ export async function poseidon2HashWithSeparator(input: Fieldable[], separator:
42
51
  */
43
52
  export async function poseidon2Permutation(input: Fieldable[]): Promise<Fr[]> {
44
53
  const inputFields = serializeToFields(input);
45
- // We'd like this assertion but it's not possible to use it in the browser.
46
- // assert(input.length === 4, 'Input state must be of size 4');
47
- await BarretenbergSync.initSingleton();
48
- const api = BarretenbergSync.getSingleton();
49
- const response = api.poseidon2Permutation({
50
- inputs: inputFields.map(i => i.toBuffer()),
51
- });
52
- // We'd like this assertion but it's not possible to use it in the browser.
53
- // assert(response.outputs.length === 4, 'Output state must be of size 4');
54
- return response.outputs.map(o => Fr.fromBuffer(Buffer.from(o)));
54
+ if (IS_BROWSER) {
55
+ await BarretenbergSync.initSingleton();
56
+ const api = BarretenbergSync.getSingleton();
57
+ const response = api.poseidon2Permutation({
58
+ inputs: inputFields.map(i => i.toBuffer()),
59
+ });
60
+ return response.outputs.map(o => Fr.fromBuffer(Buffer.from(o)));
61
+ } else {
62
+ await Barretenberg.initSingleton();
63
+ const api = Barretenberg.getSingleton();
64
+ const response = await api.poseidon2Permutation({
65
+ inputs: inputFields.map(i => i.toBuffer()),
66
+ });
67
+ return response.outputs.map(o => Fr.fromBuffer(Buffer.from(o)));
68
+ }
55
69
  }
56
70
 
57
- export async function poseidon2HashBytes(input: Buffer): Promise<Fr> {
71
+ export function poseidon2HashBytes(input: Buffer): Promise<Fr> {
58
72
  const inputFields = [];
59
73
  for (let i = 0; i < input.length; i += 31) {
60
74
  const fieldBytes = Buffer.alloc(32, 0);
@@ -65,11 +79,5 @@ export async function poseidon2HashBytes(input: Buffer): Promise<Fr> {
65
79
  inputFields.push(Fr.fromBuffer(fieldBytes));
66
80
  }
67
81
 
68
- await BarretenbergSync.initSingleton();
69
- const api = BarretenbergSync.getSingleton();
70
- const response = api.poseidon2Hash({
71
- inputs: inputFields.map(i => i.toBuffer()),
72
- });
73
-
74
- return Fr.fromBuffer(Buffer.from(response.hash));
82
+ return poseidon2HashFields(inputFields);
75
83
  }
@@ -210,3 +210,35 @@ export function recoverPublicKey(hash: Buffer32, signature: Signature, opts: Rec
210
210
  const publicKey = sig.recoverPublicKey(hash.buffer).toHex(false);
211
211
  return Buffer.from(publicKey, 'hex');
212
212
  }
213
+
214
+ /** Arbitrary hash used for testing signature recoverability. */
215
+ const PROBE_HASH = Buffer32.fromBuffer(keccak256(Buffer.from('signature-recoverability-probe')));
216
+
217
+ /**
218
+ * Generates a random valid ECDSA signature that is recoverable to some address.
219
+ * Since Signature.random() produces real signatures via secp256k1 signing, the result is always
220
+ * recoverable, but we verify defensively by checking tryRecoverAddress.
221
+ */
222
+ export function generateRecoverableSignature(): Signature {
223
+ for (let i = 0; i < 100; i++) {
224
+ const sig = Signature.random();
225
+ if (tryRecoverAddress(PROBE_HASH, sig) !== undefined) {
226
+ return sig;
227
+ }
228
+ }
229
+ throw new Secp256k1Error('Failed to generate a recoverable signature after 100 attempts');
230
+ }
231
+
232
+ /**
233
+ * Generates a random signature where ECDSA address recovery fails.
234
+ * Uses random r/s values (not from real signing) so that r is unlikely to be a valid secp256k1 x-coordinate.
235
+ */
236
+ export function generateUnrecoverableSignature(): Signature {
237
+ for (let i = 0; i < 100; i++) {
238
+ const sig = new Signature(Buffer32.random(), Buffer32.random(), 27);
239
+ if (tryRecoverAddress(PROBE_HASH, sig) === undefined) {
240
+ return sig;
241
+ }
242
+ }
243
+ throw new Secp256k1Error('Failed to generate an unrecoverable signature after 100 attempts');
244
+ }
@@ -118,14 +118,18 @@ abstract class BaseField {
118
118
  }
119
119
 
120
120
  cmp(rhs: BaseField): -1 | 0 | 1 {
121
- const rhsBigInt = rhs.asBigInt;
122
- return this.asBigInt === rhsBigInt ? 0 : this.asBigInt < rhsBigInt ? -1 : 1;
121
+ return BaseField.cmpAsBigInt(this.asBigInt, rhs.asBigInt);
123
122
  }
124
123
 
125
124
  static cmp(lhs: BaseField, rhs: BaseField): -1 | 0 | 1 {
126
125
  return lhs.cmp(rhs);
127
126
  }
128
127
 
128
+ // Actual bigint comparison. Arguments must have been validated previously.
129
+ static cmpAsBigInt(lhs: bigint, rhs: bigint): -1 | 0 | 1 {
130
+ return lhs === rhs ? 0 : lhs < rhs ? -1 : 1;
131
+ }
132
+
129
133
  isZero(): boolean {
130
134
  return this.asBigInt === 0n;
131
135
  }
@@ -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,98 @@
1
+ import EventEmitter from 'node:events';
2
+ import * as fs from 'node:fs';
3
+ import type { Readable } from 'node:stream';
4
+
5
+ /**
6
+ * Events emitted by FifoFrameReader.
7
+ *
8
+ * - `frame`: A complete frame payload (without the 4-byte length header).
9
+ * - `error`: An unrecoverable error (invalid frame length, stream error).
10
+ * - `end`: The underlying stream has ended.
11
+ */
12
+ export interface FifoFrameReaderEvents {
13
+ frame: [payload: Buffer];
14
+ error: [error: Error];
15
+ end: [];
16
+ }
17
+
18
+ /**
19
+ * Reads length-delimited frames from a readable stream (typically a named FIFO pipe).
20
+ *
21
+ * Wire format: `[4-byte big-endian payload length][payload bytes]`
22
+ *
23
+ * Emits a `frame` event for each complete frame with the raw payload buffer.
24
+ * Callers are responsible for deserializing the payload (e.g., via msgpack).
25
+ *
26
+ * On encountering an invalid payload length (0 or >maxPayloadSize), emits `error`
27
+ * and destroys the stream.
28
+ */
29
+ export class FifoFrameReader extends EventEmitter<FifoFrameReaderEvents> {
30
+ private stream: Readable | null = null;
31
+ private pendingBuf: Buffer = Buffer.alloc(0);
32
+ private running = false;
33
+
34
+ constructor(private readonly maxPayloadSize = 10 * 1024 * 1024) {
35
+ super();
36
+ }
37
+
38
+ /** Open a FIFO at the given path and start reading frames. */
39
+ start(fifoPath: string, highWaterMark = 64 * 1024): void {
40
+ this.startFromStream(fs.createReadStream(fifoPath, { highWaterMark }));
41
+ }
42
+
43
+ /** Start reading frames from an existing readable stream. */
44
+ startFromStream(stream: Readable): void {
45
+ if (this.running) {
46
+ throw new Error('FifoFrameReader is already running');
47
+ }
48
+ this.running = true;
49
+ this.pendingBuf = Buffer.alloc(0);
50
+ this.stream = stream;
51
+
52
+ stream.on('data', (chunk: Buffer | string) => {
53
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
54
+ this.pendingBuf = this.pendingBuf.length > 0 ? Buffer.concat([this.pendingBuf, buf]) : buf;
55
+ this.drainFrames();
56
+ });
57
+
58
+ stream.on('error', (err: Error) => {
59
+ if (this.running) {
60
+ this.emit('error', err);
61
+ }
62
+ });
63
+
64
+ stream.on('end', () => {
65
+ this.emit('end');
66
+ });
67
+ }
68
+
69
+ /** Stop reading and destroy the underlying stream. */
70
+ stop(): void {
71
+ this.running = false;
72
+ if (this.stream) {
73
+ this.stream.destroy();
74
+ this.stream = null;
75
+ }
76
+ }
77
+
78
+ /** Parse complete frames out of the pending buffer. */
79
+ private drainFrames(): void {
80
+ while (this.pendingBuf.length >= 4) {
81
+ const payloadLen = this.pendingBuf.readUInt32BE(0);
82
+ if (payloadLen === 0 || payloadLen > this.maxPayloadSize) {
83
+ this.emit('error', new Error(`Invalid payload length: ${payloadLen}`));
84
+ this.stop();
85
+ return;
86
+ }
87
+
88
+ const frameLen = 4 + payloadLen;
89
+ if (this.pendingBuf.length < frameLen) {
90
+ break; // Wait for more data
91
+ }
92
+
93
+ const payload = this.pendingBuf.subarray(4, frameLen);
94
+ this.pendingBuf = this.pendingBuf.subarray(frameLen);
95
+ this.emit('frame', Buffer.from(payload));
96
+ }
97
+ }
98
+ }
@@ -0,0 +1 @@
1
+ export { FifoFrameReader } from './fifo_frame_reader.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
+ }