@aztec/stdlib 0.0.1-commit.cd76b27 → 0.0.1-commit.d117d021b

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 (234) hide show
  1. package/dest/abi/decoder.d.ts +2 -2
  2. package/dest/abi/decoder.d.ts.map +1 -1
  3. package/dest/abi/decoder.js +7 -5
  4. package/dest/abi/encoder.d.ts +1 -1
  5. package/dest/abi/encoder.d.ts.map +1 -1
  6. package/dest/abi/encoder.js +37 -6
  7. package/dest/abi/event_metadata_definition.d.ts +3 -1
  8. package/dest/abi/event_metadata_definition.d.ts.map +1 -1
  9. package/dest/abi/event_metadata_definition.js +1 -1
  10. package/dest/abi/utils.d.ts +14 -1
  11. package/dest/abi/utils.d.ts.map +1 -1
  12. package/dest/abi/utils.js +15 -0
  13. package/dest/avm/avm.d.ts +300 -300
  14. package/dest/avm/avm_proving_request.d.ts +166 -166
  15. package/dest/avm/revert_code.d.ts +16 -1
  16. package/dest/avm/revert_code.d.ts.map +1 -1
  17. package/dest/avm/revert_code.js +15 -5
  18. package/dest/block/l2_block.d.ts +9 -1
  19. package/dest/block/l2_block.d.ts.map +1 -1
  20. package/dest/block/l2_block.js +12 -2
  21. package/dest/block/l2_block_source.d.ts +6 -1
  22. package/dest/block/l2_block_source.d.ts.map +1 -1
  23. package/dest/block/l2_block_stream/l2_block_stream.d.ts +1 -1
  24. package/dest/block/l2_block_stream/l2_block_stream.d.ts.map +1 -1
  25. package/dest/block/l2_block_stream/l2_block_stream.js +10 -0
  26. package/dest/checkpoint/checkpoint.d.ts +2 -1
  27. package/dest/checkpoint/checkpoint.d.ts.map +1 -1
  28. package/dest/checkpoint/checkpoint.js +9 -4
  29. package/dest/checkpoint/index.d.ts +2 -1
  30. package/dest/checkpoint/index.d.ts.map +1 -1
  31. package/dest/checkpoint/index.js +1 -0
  32. package/dest/checkpoint/validate.d.ts +36 -0
  33. package/dest/checkpoint/validate.d.ts.map +1 -0
  34. package/dest/checkpoint/validate.js +120 -0
  35. package/dest/config/sequencer-config.d.ts +4 -2
  36. package/dest/config/sequencer-config.d.ts.map +1 -1
  37. package/dest/config/sequencer-config.js +6 -0
  38. package/dest/contract/contract_class.d.ts +2 -3
  39. package/dest/contract/contract_class.d.ts.map +1 -1
  40. package/dest/gas/gas_fees.d.ts +1 -1
  41. package/dest/gas/gas_fees.d.ts.map +1 -1
  42. package/dest/gas/gas_fees.js +4 -1
  43. package/dest/ha-signing/config.d.ts +136 -0
  44. package/dest/ha-signing/config.d.ts.map +1 -0
  45. package/dest/ha-signing/config.js +97 -0
  46. package/dest/ha-signing/index.d.ts +4 -0
  47. package/dest/ha-signing/index.d.ts.map +1 -0
  48. package/dest/ha-signing/index.js +3 -0
  49. package/dest/ha-signing/local_config.d.ts +63 -0
  50. package/dest/ha-signing/local_config.d.ts.map +1 -0
  51. package/dest/ha-signing/local_config.js +24 -0
  52. package/dest/ha-signing/types.d.ts +85 -0
  53. package/dest/ha-signing/types.d.ts.map +1 -0
  54. package/dest/ha-signing/types.js +32 -0
  55. package/dest/interfaces/allowed_element.d.ts +26 -20
  56. package/dest/interfaces/allowed_element.d.ts.map +1 -1
  57. package/dest/interfaces/allowed_element.js +8 -8
  58. package/dest/interfaces/archiver.d.ts +1 -1
  59. package/dest/interfaces/archiver.d.ts.map +1 -1
  60. package/dest/interfaces/archiver.js +1 -0
  61. package/dest/interfaces/aztec-node-admin.d.ts +70 -30
  62. package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
  63. package/dest/interfaces/aztec-node.d.ts +10 -5
  64. package/dest/interfaces/aztec-node.d.ts.map +1 -1
  65. package/dest/interfaces/aztec-node.js +3 -2
  66. package/dest/interfaces/block-builder.d.ts +11 -5
  67. package/dest/interfaces/block-builder.d.ts.map +1 -1
  68. package/dest/interfaces/block-builder.js +7 -2
  69. package/dest/interfaces/configs.d.ts +57 -32
  70. package/dest/interfaces/configs.d.ts.map +1 -1
  71. package/dest/interfaces/configs.js +5 -2
  72. package/dest/interfaces/p2p.d.ts +3 -8
  73. package/dest/interfaces/p2p.d.ts.map +1 -1
  74. package/dest/interfaces/validator.d.ts +103 -41
  75. package/dest/interfaces/validator.d.ts.map +1 -1
  76. package/dest/interfaces/validator.js +8 -4
  77. package/dest/kernel/hints/build_note_hash_read_request_hints.d.ts +3 -3
  78. package/dest/kernel/hints/build_note_hash_read_request_hints.d.ts.map +1 -1
  79. package/dest/kernel/hints/build_note_hash_read_request_hints.js +13 -10
  80. package/dest/kernel/hints/build_nullifier_read_request_hints.d.ts +3 -3
  81. package/dest/kernel/hints/build_nullifier_read_request_hints.d.ts.map +1 -1
  82. package/dest/kernel/hints/build_nullifier_read_request_hints.js +13 -10
  83. package/dest/kernel/hints/build_transient_data_hints.d.ts +5 -2
  84. package/dest/kernel/hints/build_transient_data_hints.d.ts.map +1 -1
  85. package/dest/kernel/hints/build_transient_data_hints.js +9 -3
  86. package/dest/kernel/private_kernel_tail_circuit_public_inputs.d.ts +2 -1
  87. package/dest/kernel/private_kernel_tail_circuit_public_inputs.d.ts.map +1 -1
  88. package/dest/kernel/private_kernel_tail_circuit_public_inputs.js +4 -0
  89. package/dest/kv-store/config.d.ts +17 -0
  90. package/dest/kv-store/config.d.ts.map +1 -0
  91. package/dest/kv-store/config.js +26 -0
  92. package/dest/kv-store/index.d.ts +2 -0
  93. package/dest/kv-store/index.d.ts.map +1 -0
  94. package/dest/kv-store/index.js +1 -0
  95. package/dest/logs/debug_log_store.d.ts +30 -0
  96. package/dest/logs/debug_log_store.d.ts.map +1 -0
  97. package/dest/logs/debug_log_store.js +30 -0
  98. package/dest/logs/extended_directional_app_tagging_secret.d.ts +47 -0
  99. package/dest/logs/extended_directional_app_tagging_secret.d.ts.map +1 -0
  100. package/dest/logs/{directional_app_tagging_secret.js → extended_directional_app_tagging_secret.js} +23 -15
  101. package/dest/logs/index.d.ts +3 -2
  102. package/dest/logs/index.d.ts.map +1 -1
  103. package/dest/logs/index.js +2 -1
  104. package/dest/logs/pre_tag.d.ts +16 -11
  105. package/dest/logs/pre_tag.d.ts.map +1 -1
  106. package/dest/logs/pre_tag.js +2 -2
  107. package/dest/logs/public_log.d.ts +4 -3
  108. package/dest/logs/public_log.d.ts.map +1 -1
  109. package/dest/logs/public_log.js +2 -1
  110. package/dest/logs/siloed_tag.d.ts +5 -3
  111. package/dest/logs/siloed_tag.d.ts.map +1 -1
  112. package/dest/logs/siloed_tag.js +6 -1
  113. package/dest/logs/tag.js +1 -1
  114. package/dest/p2p/attestation_utils.d.ts +11 -1
  115. package/dest/p2p/attestation_utils.d.ts.map +1 -1
  116. package/dest/p2p/attestation_utils.js +45 -0
  117. package/dest/p2p/block_proposal.d.ts +2 -2
  118. package/dest/p2p/block_proposal.d.ts.map +1 -1
  119. package/dest/p2p/block_proposal.js +1 -1
  120. package/dest/p2p/checkpoint_proposal.d.ts +2 -7
  121. package/dest/p2p/checkpoint_proposal.d.ts.map +1 -1
  122. package/dest/p2p/checkpoint_proposal.js +1 -13
  123. package/dest/p2p/client_type.d.ts +2 -5
  124. package/dest/p2p/client_type.d.ts.map +1 -1
  125. package/dest/p2p/client_type.js +0 -7
  126. package/dest/p2p/index.d.ts +1 -2
  127. package/dest/p2p/index.d.ts.map +1 -1
  128. package/dest/p2p/index.js +0 -1
  129. package/dest/p2p/peer_error.d.ts +3 -1
  130. package/dest/p2p/peer_error.d.ts.map +1 -1
  131. package/dest/p2p/peer_error.js +5 -0
  132. package/dest/p2p/topic_type.d.ts +3 -4
  133. package/dest/p2p/topic_type.d.ts.map +1 -1
  134. package/dest/p2p/topic_type.js +7 -24
  135. package/dest/slashing/tally.d.ts +7 -2
  136. package/dest/slashing/tally.d.ts.map +1 -1
  137. package/dest/slashing/tally.js +30 -2
  138. package/dest/tests/factories.d.ts +3 -1
  139. package/dest/tests/factories.d.ts.map +1 -1
  140. package/dest/tests/factories.js +8 -0
  141. package/dest/tests/mocks.d.ts +5 -3
  142. package/dest/tests/mocks.d.ts.map +1 -1
  143. package/dest/tests/mocks.js +18 -13
  144. package/dest/tx/block_header.d.ts +3 -1
  145. package/dest/tx/block_header.d.ts.map +1 -1
  146. package/dest/tx/block_header.js +4 -0
  147. package/dest/tx/public_simulation_output.d.ts +4 -2
  148. package/dest/tx/public_simulation_output.d.ts.map +1 -1
  149. package/dest/tx/public_simulation_output.js +7 -3
  150. package/dest/tx/simulated_tx.d.ts +5 -2
  151. package/dest/tx/simulated_tx.d.ts.map +1 -1
  152. package/dest/tx/simulated_tx.js +4 -1
  153. package/dest/tx/tx.d.ts +6 -5
  154. package/dest/tx/tx.d.ts.map +1 -1
  155. package/dest/tx/tx.js +18 -6
  156. package/dest/tx/tx_receipt.d.ts +16 -2
  157. package/dest/tx/tx_receipt.d.ts.map +1 -1
  158. package/dest/tx/tx_receipt.js +11 -3
  159. package/dest/tx/validator/error_texts.d.ts +5 -1
  160. package/dest/tx/validator/error_texts.d.ts.map +1 -1
  161. package/dest/tx/validator/error_texts.js +4 -0
  162. package/dest/update-checker/index.d.ts +3 -2
  163. package/dest/update-checker/index.d.ts.map +1 -1
  164. package/dest/update-checker/index.js +2 -1
  165. package/dest/update-checker/package_version.d.ts +3 -0
  166. package/dest/update-checker/package_version.d.ts.map +1 -0
  167. package/dest/update-checker/package_version.js +11 -0
  168. package/dest/update-checker/version_checker.d.ts +25 -0
  169. package/dest/update-checker/version_checker.d.ts.map +1 -0
  170. package/dest/update-checker/version_checker.js +50 -0
  171. package/package.json +12 -11
  172. package/src/abi/decoder.ts +15 -6
  173. package/src/abi/encoder.ts +49 -6
  174. package/src/abi/event_metadata_definition.ts +2 -0
  175. package/src/abi/utils.ts +25 -0
  176. package/src/avm/revert_code.ts +15 -0
  177. package/src/block/l2_block.ts +13 -1
  178. package/src/block/l2_block_source.ts +6 -0
  179. package/src/block/l2_block_stream/l2_block_stream.ts +21 -0
  180. package/src/checkpoint/checkpoint.ts +12 -3
  181. package/src/checkpoint/index.ts +1 -0
  182. package/src/checkpoint/validate.ts +230 -0
  183. package/src/config/sequencer-config.ts +9 -1
  184. package/src/contract/contract_class.ts +3 -3
  185. package/src/gas/gas_fees.ts +7 -1
  186. package/src/ha-signing/config.ts +156 -0
  187. package/src/ha-signing/index.ts +27 -0
  188. package/src/ha-signing/local_config.ts +46 -0
  189. package/src/ha-signing/types.ts +112 -0
  190. package/src/interfaces/allowed_element.ts +29 -9
  191. package/src/interfaces/archiver.ts +1 -0
  192. package/src/interfaces/aztec-node.ts +14 -4
  193. package/src/interfaces/block-builder.ts +25 -5
  194. package/src/interfaces/configs.ts +22 -8
  195. package/src/interfaces/p2p.ts +2 -13
  196. package/src/interfaces/validator.ts +50 -28
  197. package/src/kernel/hints/build_note_hash_read_request_hints.ts +14 -18
  198. package/src/kernel/hints/build_nullifier_read_request_hints.ts +15 -18
  199. package/src/kernel/hints/build_transient_data_hints.ts +17 -2
  200. package/src/kernel/private_kernel_tail_circuit_public_inputs.ts +9 -0
  201. package/src/kv-store/config.ts +36 -0
  202. package/src/kv-store/index.ts +1 -0
  203. package/src/logs/debug_log_store.ts +54 -0
  204. package/src/logs/{directional_app_tagging_secret.ts → extended_directional_app_tagging_secret.ts} +24 -16
  205. package/src/logs/index.ts +2 -1
  206. package/src/logs/pre_tag.ts +5 -5
  207. package/src/logs/public_log.ts +4 -2
  208. package/src/logs/siloed_tag.ts +8 -2
  209. package/src/logs/tag.ts +1 -1
  210. package/src/p2p/attestation_utils.ts +56 -0
  211. package/src/p2p/block_proposal.ts +1 -1
  212. package/src/p2p/checkpoint_proposal.ts +1 -18
  213. package/src/p2p/client_type.ts +0 -6
  214. package/src/p2p/index.ts +0 -1
  215. package/src/p2p/peer_error.ts +7 -0
  216. package/src/p2p/topic_type.ts +8 -15
  217. package/src/slashing/tally.ts +34 -1
  218. package/src/tests/factories.ts +9 -0
  219. package/src/tests/mocks.ts +25 -10
  220. package/src/tx/block_header.ts +6 -0
  221. package/src/tx/public_simulation_output.ts +4 -0
  222. package/src/tx/simulated_tx.ts +8 -1
  223. package/src/tx/tx.ts +20 -11
  224. package/src/tx/tx_receipt.ts +10 -0
  225. package/src/tx/validator/error_texts.ts +4 -0
  226. package/src/update-checker/index.ts +2 -1
  227. package/src/update-checker/package_version.ts +17 -0
  228. package/src/update-checker/version_checker.ts +65 -0
  229. package/dest/logs/directional_app_tagging_secret.d.ts +0 -40
  230. package/dest/logs/directional_app_tagging_secret.d.ts.map +0 -1
  231. package/dest/update-checker/update-checker.d.ts +0 -49
  232. package/dest/update-checker/update-checker.d.ts.map +0 -1
  233. package/dest/update-checker/update-checker.js +0 -130
  234. package/src/update-checker/update-checker.ts +0 -166
@@ -0,0 +1,230 @@
1
+ import { BLOBS_PER_CHECKPOINT, FIELDS_PER_BLOB, MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT } from '@aztec/constants';
2
+ import type { CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
3
+ import { sum } from '@aztec/foundation/collection';
4
+
5
+ import { MAX_BLOCKS_PER_CHECKPOINT } from '../deserialization/index.js';
6
+ import type { Checkpoint } from './checkpoint.js';
7
+
8
+ export class CheckpointValidationError extends Error {
9
+ constructor(
10
+ message: string,
11
+ public readonly checkpointNumber: CheckpointNumber,
12
+ public readonly slot: SlotNumber,
13
+ ) {
14
+ super(message);
15
+ this.name = 'CheckpointValidationError';
16
+ }
17
+ }
18
+
19
+ /**
20
+ * Validates a checkpoint. Throws a CheckpointValidationError if any validation fails.
21
+ * - Validates structural integrity (non-empty, block count, sequential numbers, archive chaining, slot consistency)
22
+ * - Validates checkpoint blob field count against maxBlobFields limit
23
+ * - Validates total L2 gas used by checkpoint blocks against the Rollup contract mana limit
24
+ * - Validates total DA gas used by checkpoint blocks against MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT
25
+ * - Validates individual block L2 gas and DA gas against maxL2BlockGas and maxDABlockGas limits
26
+ */
27
+ export function validateCheckpoint(
28
+ checkpoint: Checkpoint,
29
+ opts: {
30
+ rollupManaLimit?: number;
31
+ maxL2BlockGas?: number;
32
+ maxDABlockGas?: number;
33
+ maxTxsPerCheckpoint?: number;
34
+ maxTxsPerBlock?: number;
35
+ },
36
+ ): void {
37
+ validateCheckpointStructure(checkpoint);
38
+ validateCheckpointLimits(checkpoint, opts);
39
+ validateCheckpointBlocksGasLimits(checkpoint, opts);
40
+ }
41
+
42
+ /**
43
+ * Validates structural integrity of a checkpoint.
44
+ * - Non-empty block list
45
+ * - Block count within MAX_BLOCKS_PER_CHECKPOINT
46
+ * - Checkpoint slot matches the first block's slot
47
+ * - Checkpoint lastArchiveRoot matches the first block's lastArchive root
48
+ * - Sequential block numbers without gaps
49
+ * - Sequential indexWithinCheckpoint starting at 0
50
+ * - Archive root chaining between consecutive blocks
51
+ * - Consistent slot number across all blocks
52
+ * - Global variables (slot, timestamp, coinbase, feeRecipient, gasFees) match checkpoint header for each block
53
+ */
54
+ export function validateCheckpointStructure(checkpoint: Checkpoint): void {
55
+ const { blocks, number, slot } = checkpoint;
56
+
57
+ if (blocks.length === 0) {
58
+ throw new CheckpointValidationError('Checkpoint has no blocks', number, slot);
59
+ }
60
+
61
+ if (blocks.length > MAX_BLOCKS_PER_CHECKPOINT) {
62
+ throw new CheckpointValidationError(
63
+ `Checkpoint has ${blocks.length} blocks, exceeding limit of ${MAX_BLOCKS_PER_CHECKPOINT}`,
64
+ number,
65
+ slot,
66
+ );
67
+ }
68
+
69
+ const firstBlock = blocks[0];
70
+
71
+ if (!checkpoint.header.lastArchiveRoot.equals(firstBlock.header.lastArchive.root)) {
72
+ throw new CheckpointValidationError(
73
+ `Checkpoint lastArchiveRoot does not match first block's lastArchive root`,
74
+ number,
75
+ slot,
76
+ );
77
+ }
78
+
79
+ for (let i = 0; i < blocks.length; i++) {
80
+ const block = blocks[i];
81
+
82
+ if (block.indexWithinCheckpoint !== i) {
83
+ throw new CheckpointValidationError(
84
+ `Block at index ${i} has indexWithinCheckpoint ${block.indexWithinCheckpoint}, expected ${i}`,
85
+ number,
86
+ slot,
87
+ );
88
+ }
89
+
90
+ if (block.slot !== slot) {
91
+ throw new CheckpointValidationError(
92
+ `Block ${block.number} has slot ${block.slot}, expected ${slot} (all blocks must share the same slot)`,
93
+ number,
94
+ slot,
95
+ );
96
+ }
97
+
98
+ if (!checkpoint.header.matchesGlobalVariables(block.header.globalVariables)) {
99
+ throw new CheckpointValidationError(
100
+ `Block ${block.number} global variables (slot, timestamp, coinbase, feeRecipient, gasFees) do not match checkpoint header`,
101
+ number,
102
+ slot,
103
+ );
104
+ }
105
+
106
+ if (i > 0) {
107
+ const prev = blocks[i - 1];
108
+ if (block.number !== prev.number + 1) {
109
+ throw new CheckpointValidationError(
110
+ `Block numbers are not sequential: block at index ${i - 1} has number ${prev.number}, block at index ${i} has number ${block.number}`,
111
+ number,
112
+ slot,
113
+ );
114
+ }
115
+
116
+ if (!block.header.lastArchive.root.equals(prev.archive.root)) {
117
+ throw new CheckpointValidationError(
118
+ `Block ${block.number} lastArchive root does not match archive root of block ${prev.number}`,
119
+ number,
120
+ slot,
121
+ );
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ /** Validates checkpoint blocks gas limits */
128
+ function validateCheckpointBlocksGasLimits(
129
+ checkpoint: Checkpoint,
130
+ opts: {
131
+ maxL2BlockGas?: number;
132
+ maxDABlockGas?: number;
133
+ maxTxsPerBlock?: number;
134
+ },
135
+ ): void {
136
+ const { maxL2BlockGas, maxDABlockGas, maxTxsPerBlock } = opts;
137
+
138
+ if (maxL2BlockGas !== undefined) {
139
+ for (const block of checkpoint.blocks) {
140
+ const blockL2Gas = block.header.totalManaUsed.toNumber();
141
+ if (blockL2Gas > maxL2BlockGas) {
142
+ throw new CheckpointValidationError(
143
+ `Block ${block.number} in checkpoint has L2 gas used ${blockL2Gas} exceeding limit of ${maxL2BlockGas}`,
144
+ checkpoint.number,
145
+ checkpoint.slot,
146
+ );
147
+ }
148
+ }
149
+ }
150
+
151
+ if (maxDABlockGas !== undefined) {
152
+ for (const block of checkpoint.blocks) {
153
+ const blockDAGas = block.computeDAGasUsed();
154
+ if (blockDAGas > maxDABlockGas) {
155
+ throw new CheckpointValidationError(
156
+ `Block ${block.number} in checkpoint has DA gas used ${blockDAGas} exceeding limit of ${maxDABlockGas}`,
157
+ checkpoint.number,
158
+ checkpoint.slot,
159
+ );
160
+ }
161
+ }
162
+ }
163
+
164
+ if (maxTxsPerBlock !== undefined) {
165
+ for (const block of checkpoint.blocks) {
166
+ const blockTxCount = block.body.txEffects.length;
167
+ if (blockTxCount > maxTxsPerBlock) {
168
+ throw new CheckpointValidationError(
169
+ `Block ${block.number} in checkpoint has ${blockTxCount} txs exceeding limit of ${maxTxsPerBlock}`,
170
+ checkpoint.number,
171
+ checkpoint.slot,
172
+ );
173
+ }
174
+ }
175
+ }
176
+ }
177
+
178
+ /** Validates checkpoint max blob fields, gas limits, and tx limits */
179
+ function validateCheckpointLimits(
180
+ checkpoint: Checkpoint,
181
+ opts: {
182
+ rollupManaLimit?: number;
183
+ maxTxsPerCheckpoint?: number;
184
+ },
185
+ ): void {
186
+ const { rollupManaLimit, maxTxsPerCheckpoint } = opts;
187
+
188
+ const maxBlobFields = BLOBS_PER_CHECKPOINT * FIELDS_PER_BLOB;
189
+ const maxDAGas = MAX_PROCESSABLE_DA_GAS_PER_CHECKPOINT;
190
+
191
+ if (rollupManaLimit !== undefined) {
192
+ const checkpointMana = sum(checkpoint.blocks.map(block => block.header.totalManaUsed.toNumber()));
193
+ if (checkpointMana > rollupManaLimit) {
194
+ throw new CheckpointValidationError(
195
+ `Checkpoint mana cost ${checkpointMana} exceeds rollup limit of ${rollupManaLimit}`,
196
+ checkpoint.number,
197
+ checkpoint.slot,
198
+ );
199
+ }
200
+ }
201
+
202
+ const checkpointDAGas = sum(checkpoint.blocks.map(block => block.computeDAGasUsed()));
203
+ if (checkpointDAGas > maxDAGas) {
204
+ throw new CheckpointValidationError(
205
+ `Checkpoint DA gas cost ${checkpointDAGas} exceeds limit of ${maxDAGas}`,
206
+ checkpoint.number,
207
+ checkpoint.slot,
208
+ );
209
+ }
210
+
211
+ const checkpointBlobFields = checkpoint.toBlobFields().length;
212
+ if (checkpointBlobFields > maxBlobFields) {
213
+ throw new CheckpointValidationError(
214
+ `Checkpoint blob field count ${checkpointBlobFields} exceeds limit of ${maxBlobFields}`,
215
+ checkpoint.number,
216
+ checkpoint.slot,
217
+ );
218
+ }
219
+
220
+ if (maxTxsPerCheckpoint !== undefined) {
221
+ const checkpointTxCount = sum(checkpoint.blocks.map(block => block.body.txEffects.length));
222
+ if (checkpointTxCount > maxTxsPerCheckpoint) {
223
+ throw new CheckpointValidationError(
224
+ `Checkpoint tx count ${checkpointTxCount} exceeds limit of ${maxTxsPerCheckpoint}`,
225
+ checkpoint.number,
226
+ checkpoint.slot,
227
+ );
228
+ }
229
+ }
230
+ }
@@ -2,6 +2,9 @@ import type { ConfigMappingsType } from '@aztec/foundation/config';
2
2
 
3
3
  import type { SequencerConfig } from '../interfaces/configs.js';
4
4
 
5
+ /** Default maximum number of transactions per block. */
6
+ export const DEFAULT_MAX_TXS_PER_BLOCK = 32;
7
+
5
8
  /**
6
9
  * Partial sequencer config mappings for fields that need to be shared across packages.
7
10
  * The full sequencer config mappings remain in sequencer-client, but shared fields
@@ -9,7 +12,7 @@ import type { SequencerConfig } from '../interfaces/configs.js';
9
12
  * to avoid duplication.
10
13
  */
11
14
  export const sharedSequencerConfigMappings: ConfigMappingsType<
12
- Pick<SequencerConfig, 'blockDurationMs' | 'expectedBlockProposalsPerSlot'>
15
+ Pick<SequencerConfig, 'blockDurationMs' | 'expectedBlockProposalsPerSlot' | 'maxTxsPerBlock'>
13
16
  > = {
14
17
  blockDurationMs: {
15
18
  env: 'SEQ_BLOCK_DURATION_MS',
@@ -26,4 +29,9 @@ export const sharedSequencerConfigMappings: ConfigMappingsType<
26
29
  parseEnv: (val: string) => (val ? parseInt(val, 10) : 0),
27
30
  defaultValue: 0,
28
31
  },
32
+ maxTxsPerBlock: {
33
+ env: 'SEQ_MAX_TX_PER_BLOCK',
34
+ description: 'The maximum number of txs to include in a block.',
35
+ parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined),
36
+ },
29
37
  };
@@ -8,7 +8,7 @@ import { type ContractClassIdPreimage, computeContractClassIdWithPreimage } from
8
8
  import type { ContractClass, ContractClassWithId } from './interfaces/index.js';
9
9
 
10
10
  /** Contract artifact including its artifact hash */
11
- type ContractArtifactWithHash = ContractArtifact & { artifactHash: Fr };
11
+ export type ContractArtifactWithHash = ContractArtifact & { artifactHash: Fr };
12
12
 
13
13
  const cmpFunctionArtifacts = <T extends { selector: FunctionSelector }>(a: T, b: T) =>
14
14
  a.selector.toField().cmp(b.selector.toField());
@@ -35,8 +35,8 @@ export async function getContractClassFromArtifact(
35
35
 
36
36
  privateArtifactFunctions.sort(cmpFunctionArtifacts);
37
37
 
38
- const contractClass: ContractClass = {
39
- version: 1,
38
+ const contractClass = {
39
+ version: 1 as const,
40
40
  artifactHash,
41
41
  packedBytecode,
42
42
  privateFunctions: privateArtifactFunctions,
@@ -56,8 +56,14 @@ export class GasFees {
56
56
  return this.clone();
57
57
  } else if (typeof scalar === 'bigint') {
58
58
  return new GasFees(this.feePerDaGas * scalar, this.feePerL2Gas * scalar);
59
+ } else if (Number.isInteger(scalar)) {
60
+ const s = BigInt(scalar);
61
+ return new GasFees(this.feePerDaGas * s, this.feePerL2Gas * s);
59
62
  } else {
60
- return new GasFees(Number(this.feePerDaGas) * scalar, Number(this.feePerL2Gas) * scalar);
63
+ return new GasFees(
64
+ BigInt(Math.ceil(Number(this.feePerDaGas) * scalar)),
65
+ BigInt(Math.ceil(Number(this.feePerL2Gas) * scalar)),
66
+ );
61
67
  }
62
68
  }
63
69
 
@@ -0,0 +1,156 @@
1
+ import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
2
+ import {
3
+ type ConfigMappingsType,
4
+ booleanConfigHelper,
5
+ getConfigFromMappings,
6
+ getDefaultConfig,
7
+ numberConfigHelper,
8
+ optionalNumberConfigHelper,
9
+ } from '@aztec/foundation/config';
10
+ import { EthAddress } from '@aztec/foundation/eth-address';
11
+ import type { ZodFor } from '@aztec/foundation/schemas';
12
+
13
+ import { z } from 'zod';
14
+
15
+ /**
16
+ * Base signing protection configuration shared by both HA (Postgres) and local (LMDB) signers.
17
+ */
18
+ export interface BaseSignerConfig {
19
+ /** L1 contract addresses (rollup address required) */
20
+ l1Contracts: Pick<L1ContractAddresses, 'rollupAddress'>;
21
+ /** Unique identifier for this node */
22
+ nodeId: string;
23
+ /** How long to wait between polls when a duty is being signed (ms) */
24
+ pollingIntervalMs: number;
25
+ /** Maximum time to wait for a duty being signed to complete (ms) */
26
+ signingTimeoutMs: number;
27
+ /** Maximum age of a stuck duty in ms (defaults to 2x hardcoded Aztec slot duration if not set) */
28
+ maxStuckDutiesAgeMs?: number;
29
+ /** Optional: clean up old duties after this many hours (disabled if not set) */
30
+ cleanupOldDutiesAfterHours?: number;
31
+ }
32
+
33
+ export const baseSignerConfigMappings: ConfigMappingsType<BaseSignerConfig> = {
34
+ l1Contracts: {
35
+ description: 'L1 contract addresses (rollup address required)',
36
+ nested: {
37
+ rollupAddress: {
38
+ description: 'The Ethereum address of the rollup contract (must be set programmatically)',
39
+ parseEnv: (val: string) => EthAddress.fromString(val),
40
+ },
41
+ },
42
+ },
43
+ nodeId: {
44
+ env: 'VALIDATOR_HA_NODE_ID',
45
+ description: 'The unique identifier for this node',
46
+ defaultValue: '',
47
+ },
48
+ pollingIntervalMs: {
49
+ env: 'VALIDATOR_HA_POLLING_INTERVAL_MS',
50
+ description: 'The number of ms to wait between polls when a duty is being signed',
51
+ ...numberConfigHelper(100),
52
+ },
53
+ signingTimeoutMs: {
54
+ env: 'VALIDATOR_HA_SIGNING_TIMEOUT_MS',
55
+ description: 'The maximum time to wait for a duty being signed to complete',
56
+ ...numberConfigHelper(3_000),
57
+ },
58
+ maxStuckDutiesAgeMs: {
59
+ env: 'VALIDATOR_HA_MAX_STUCK_DUTIES_AGE_MS',
60
+ description: 'The maximum age of a stuck duty in ms (defaults to 2x Aztec slot duration)',
61
+ ...optionalNumberConfigHelper(),
62
+ },
63
+ cleanupOldDutiesAfterHours: {
64
+ env: 'VALIDATOR_HA_OLD_DUTIES_MAX_AGE_H',
65
+ description: 'Optional: clean up old duties after this many hours (disabled if not set)',
66
+ ...optionalNumberConfigHelper(),
67
+ },
68
+ };
69
+
70
+ export const BaseSignerConfigSchema = z.object({
71
+ l1Contracts: z.object({ rollupAddress: z.instanceof(EthAddress) }),
72
+ nodeId: z.string(),
73
+ pollingIntervalMs: z.number().min(0),
74
+ signingTimeoutMs: z.number().min(0),
75
+ maxStuckDutiesAgeMs: z.number().min(0).optional(),
76
+ cleanupOldDutiesAfterHours: z.number().min(0).optional(),
77
+ }) satisfies ZodFor<BaseSignerConfig>;
78
+
79
+ /**
80
+ * Configuration for the Validator HA Signer.
81
+ *
82
+ * Extends BaseSignerConfig with a flag to enable HA mode and Postgres connection settings.
83
+ */
84
+ export interface ValidatorHASignerConfig extends BaseSignerConfig {
85
+ /** Whether HA signing / slashing protection is enabled */
86
+ haSigningEnabled: boolean;
87
+ /**
88
+ * PostgreSQL connection string
89
+ * Format: postgresql://user:password@host:port/database
90
+ */
91
+ databaseUrl?: string;
92
+ /** Maximum number of clients in the pool (default: 10) */
93
+ poolMaxCount?: number;
94
+ /** Minimum number of clients in the pool (default: 0) */
95
+ poolMinCount?: number;
96
+ /** Idle timeout in milliseconds (default: 10000) */
97
+ poolIdleTimeoutMs?: number;
98
+ /** Connection timeout in milliseconds (default: 0, no timeout) */
99
+ poolConnectionTimeoutMs?: number;
100
+ }
101
+
102
+ export const validatorHASignerConfigMappings: ConfigMappingsType<ValidatorHASignerConfig> = {
103
+ ...baseSignerConfigMappings,
104
+ haSigningEnabled: {
105
+ env: 'VALIDATOR_HA_SIGNING_ENABLED',
106
+ description: 'Whether HA signing / slashing protection is enabled',
107
+ ...booleanConfigHelper(false),
108
+ },
109
+ databaseUrl: {
110
+ env: 'VALIDATOR_HA_DATABASE_URL',
111
+ description:
112
+ 'PostgreSQL connection string for validator HA signer (format: postgresql://user:password@host:port/database)',
113
+ },
114
+ poolMaxCount: {
115
+ env: 'VALIDATOR_HA_POOL_MAX',
116
+ description: 'Maximum number of clients in the pool',
117
+ ...numberConfigHelper(10),
118
+ },
119
+ poolMinCount: {
120
+ env: 'VALIDATOR_HA_POOL_MIN',
121
+ description: 'Minimum number of clients in the pool',
122
+ ...numberConfigHelper(0),
123
+ },
124
+ poolIdleTimeoutMs: {
125
+ env: 'VALIDATOR_HA_POOL_IDLE_TIMEOUT_MS',
126
+ description: 'Idle timeout in milliseconds',
127
+ ...numberConfigHelper(10_000),
128
+ },
129
+ poolConnectionTimeoutMs: {
130
+ env: 'VALIDATOR_HA_POOL_CONNECTION_TIMEOUT_MS',
131
+ description: 'Connection timeout in milliseconds (0 means no timeout)',
132
+ ...numberConfigHelper(0),
133
+ },
134
+ };
135
+
136
+ export const defaultValidatorHASignerConfig: ValidatorHASignerConfig = getDefaultConfig(
137
+ validatorHASignerConfigMappings,
138
+ );
139
+
140
+ /**
141
+ * Returns the validator HA signer configuration from environment variables.
142
+ * Note: If an environment variable is not set, the default value is used.
143
+ * @returns The validator HA signer configuration.
144
+ */
145
+ export function getConfigEnvVars(): ValidatorHASignerConfig {
146
+ return getConfigFromMappings<ValidatorHASignerConfig>(validatorHASignerConfigMappings);
147
+ }
148
+
149
+ export const ValidatorHASignerConfigSchema = BaseSignerConfigSchema.extend({
150
+ haSigningEnabled: z.boolean(),
151
+ databaseUrl: z.string().optional(),
152
+ poolMaxCount: z.number().min(0).optional(),
153
+ poolMinCount: z.number().min(0).optional(),
154
+ poolIdleTimeoutMs: z.number().min(0).optional(),
155
+ poolConnectionTimeoutMs: z.number().min(0).optional(),
156
+ }) satisfies ZodFor<ValidatorHASignerConfig>;
@@ -0,0 +1,27 @@
1
+ export {
2
+ type BaseSignerConfig,
3
+ BaseSignerConfigSchema,
4
+ baseSignerConfigMappings,
5
+ type ValidatorHASignerConfig,
6
+ ValidatorHASignerConfigSchema,
7
+ defaultValidatorHASignerConfig,
8
+ getConfigEnvVars,
9
+ validatorHASignerConfigMappings,
10
+ } from './config.js';
11
+ export {
12
+ type LocalSignerConfig,
13
+ LocalSignerConfigSchema,
14
+ getLocalSignerConfigEnvVars,
15
+ localSignerConfigMappings,
16
+ } from './local_config.js';
17
+ export {
18
+ DutyType,
19
+ type BlockProposalSigningContext,
20
+ type HAProtectedSigningContext,
21
+ type NoHAProtectionSigningContext,
22
+ type OtherSigningContext,
23
+ type SigningContext,
24
+ type VoteSigningContext,
25
+ getBlockNumberFromSigningContext,
26
+ isHAProtectedContext,
27
+ } from './types.js';
@@ -0,0 +1,46 @@
1
+ import { type ConfigMappingsType, getConfigFromMappings } from '@aztec/foundation/config';
2
+ import { zodFor } from '@aztec/foundation/schemas';
3
+ import { type DataStoreConfig, dataConfigMappings } from '@aztec/stdlib/kv-store';
4
+
5
+ import { z } from 'zod';
6
+
7
+ import { type BaseSignerConfig, BaseSignerConfigSchema, baseSignerConfigMappings } from './config.js';
8
+
9
+ /**
10
+ * Configuration for local (single-node) slashing protection.
11
+ *
12
+ * Combines the base signing protection fields (shared with HA mode) with
13
+ * DataStoreConfig for the local LMDB backing store, plus a per-store map-size
14
+ * override. Used when HA signing is disabled.
15
+ */
16
+ export type LocalSignerConfig = BaseSignerConfig &
17
+ DataStoreConfig & {
18
+ /** Maximum size of the local signing-protection LMDB store in KB. Overwrites the general dataStoreMapSizeKb. */
19
+ signingProtectionMapSizeKb?: number;
20
+ };
21
+
22
+ export const localSignerConfigMappings: ConfigMappingsType<LocalSignerConfig> = {
23
+ ...baseSignerConfigMappings,
24
+ ...dataConfigMappings,
25
+ signingProtectionMapSizeKb: {
26
+ env: 'SIGNING_PROTECTION_MAP_SIZE_KB',
27
+ description:
28
+ 'Maximum size of the local signing-protection LMDB store in KB. Overwrites the general dataStoreMapSizeKb.',
29
+ parseEnv: (val: string | undefined) => (val ? +val : undefined),
30
+ },
31
+ };
32
+
33
+ export const LocalSignerConfigSchema = zodFor<LocalSignerConfig>()(
34
+ BaseSignerConfigSchema.extend({
35
+ dataDirectory: z.string().optional(),
36
+ dataStoreMapSizeKb: z.number(),
37
+ signingProtectionMapSizeKb: z.number().optional(),
38
+ }),
39
+ );
40
+
41
+ /**
42
+ * Returns the local signer configuration from environment variables.
43
+ */
44
+ export function getLocalSignerConfigEnvVars(): LocalSignerConfig {
45
+ return getConfigFromMappings<LocalSignerConfig>(localSignerConfigMappings);
46
+ }
@@ -0,0 +1,112 @@
1
+ import {
2
+ BlockNumber,
3
+ type CheckpointNumber,
4
+ type IndexWithinCheckpoint,
5
+ type SlotNumber,
6
+ } from '@aztec/foundation/branded-types';
7
+
8
+ /**
9
+ * Type of validator duty being performed
10
+ */
11
+ export enum DutyType {
12
+ BLOCK_PROPOSAL = 'BLOCK_PROPOSAL',
13
+ CHECKPOINT_PROPOSAL = 'CHECKPOINT_PROPOSAL',
14
+ ATTESTATION = 'ATTESTATION',
15
+ ATTESTATIONS_AND_SIGNERS = 'ATTESTATIONS_AND_SIGNERS',
16
+ GOVERNANCE_VOTE = 'GOVERNANCE_VOTE',
17
+ SLASHING_VOTE = 'SLASHING_VOTE',
18
+ AUTH_REQUEST = 'AUTH_REQUEST',
19
+ TXS = 'TXS',
20
+ }
21
+
22
+ /**
23
+ * Base context for signing operations
24
+ */
25
+ interface BaseSigningContext {
26
+ /** Slot number for this duty */
27
+ slot: SlotNumber;
28
+ /**
29
+ * Block or checkpoint number for this duty.
30
+ * For block proposals, this is the block number.
31
+ * For checkpoint proposals, this is the checkpoint number.
32
+ */
33
+ blockNumber: BlockNumber | CheckpointNumber;
34
+ }
35
+
36
+ /**
37
+ * Signing context for block proposals.
38
+ * blockIndexWithinCheckpoint is REQUIRED and must be >= 0.
39
+ */
40
+ export interface BlockProposalSigningContext extends BaseSigningContext {
41
+ /** Block index within checkpoint (0, 1, 2...). Required for block proposals. */
42
+ blockIndexWithinCheckpoint: IndexWithinCheckpoint;
43
+ dutyType: DutyType.BLOCK_PROPOSAL;
44
+ }
45
+
46
+ /**
47
+ * Signing context for non-block-proposal duties that require HA protection.
48
+ * blockIndexWithinCheckpoint is not applicable (internally always -1).
49
+ */
50
+ export interface OtherSigningContext extends BaseSigningContext {
51
+ dutyType: DutyType.CHECKPOINT_PROPOSAL | DutyType.ATTESTATION | DutyType.ATTESTATIONS_AND_SIGNERS;
52
+ }
53
+
54
+ /**
55
+ * Signing context for governance/slashing votes which only need slot for HA protection.
56
+ * blockNumber is not applicable (internally always 0).
57
+ */
58
+ export interface VoteSigningContext {
59
+ slot: SlotNumber;
60
+ dutyType: DutyType.GOVERNANCE_VOTE | DutyType.SLASHING_VOTE;
61
+ }
62
+
63
+ /**
64
+ * Signing context for duties which don't require slot/blockNumber
65
+ * as they don't need HA protection (AUTH_REQUEST, TXS).
66
+ */
67
+ export interface NoHAProtectionSigningContext {
68
+ dutyType: DutyType.AUTH_REQUEST | DutyType.TXS;
69
+ }
70
+
71
+ /**
72
+ * Signing contexts that require HA protection (excludes AUTH_REQUEST).
73
+ * Used by the HA signer's signWithProtection method.
74
+ */
75
+ export type HAProtectedSigningContext = BlockProposalSigningContext | OtherSigningContext | VoteSigningContext;
76
+
77
+ /**
78
+ * Context required for slashing protection during signing operations.
79
+ * Uses discriminated union to enforce type safety:
80
+ * - BLOCK_PROPOSAL duties MUST have blockIndexWithinCheckpoint >= 0
81
+ * - Other duty types do NOT have blockIndexWithinCheckpoint (internally -1)
82
+ * - Vote duties only need slot (blockNumber is internally 0)
83
+ * - AUTH_REQUEST and TXS duties don't need slot/blockNumber (no HA protection needed)
84
+ */
85
+ export type SigningContext = HAProtectedSigningContext | NoHAProtectionSigningContext;
86
+
87
+ /**
88
+ * Type guard to check if a SigningContext requires HA protection.
89
+ * Returns true for contexts that need HA protection, false for AUTH_REQUEST and TXS.
90
+ */
91
+ export function isHAProtectedContext(context: SigningContext): context is HAProtectedSigningContext {
92
+ return context.dutyType !== DutyType.AUTH_REQUEST && context.dutyType !== DutyType.TXS;
93
+ }
94
+
95
+ /**
96
+ * Gets the block number from a signing context.
97
+ * - Vote duties (GOVERNANCE_VOTE, SLASHING_VOTE): returns BlockNumber(0)
98
+ * - Other duties: returns the blockNumber from the context
99
+ */
100
+ export function getBlockNumberFromSigningContext(context: HAProtectedSigningContext): BlockNumber | CheckpointNumber {
101
+ // Check for duty types that have blockNumber
102
+ if (
103
+ context.dutyType === DutyType.BLOCK_PROPOSAL ||
104
+ context.dutyType === DutyType.CHECKPOINT_PROPOSAL ||
105
+ context.dutyType === DutyType.ATTESTATION ||
106
+ context.dutyType === DutyType.ATTESTATIONS_AND_SIGNERS
107
+ ) {
108
+ return context.blockNumber;
109
+ }
110
+ // Vote duties (GOVERNANCE_VOTE, SLASHING_VOTE) don't have blockNumber
111
+ return BlockNumber(0);
112
+ }
@@ -6,18 +6,38 @@ import type { FunctionSelector } from '../abi/function_selector.js';
6
6
  import type { AztecAddress } from '../aztec-address/index.js';
7
7
  import { schemas, zodFor } from '../schemas/index.js';
8
8
 
9
- type AllowedInstance = { address: AztecAddress };
10
- type AllowedInstanceFunction = { address: AztecAddress; selector: FunctionSelector };
11
- type AllowedClass = { classId: Fr };
12
- type AllowedClassFunction = { classId: Fr; selector: FunctionSelector };
9
+ type AllowedInstanceFunction = {
10
+ address: AztecAddress;
11
+ selector: FunctionSelector;
12
+ onlySelf?: boolean;
13
+ rejectNullMsgSender?: boolean;
14
+ calldataLength?: number;
15
+ };
16
+ type AllowedClassFunction = {
17
+ classId: Fr;
18
+ selector: FunctionSelector;
19
+ onlySelf?: boolean;
20
+ rejectNullMsgSender?: boolean;
21
+ calldataLength?: number;
22
+ };
13
23
 
14
- export type AllowedElement = AllowedInstance | AllowedInstanceFunction | AllowedClass | AllowedClassFunction;
24
+ export type AllowedElement = AllowedInstanceFunction | AllowedClassFunction;
15
25
 
16
26
  export const AllowedElementSchema = zodFor<AllowedElement>()(
17
27
  z.union([
18
- z.object({ address: schemas.AztecAddress, selector: schemas.FunctionSelector }),
19
- z.object({ address: schemas.AztecAddress }),
20
- z.object({ classId: schemas.Fr, selector: schemas.FunctionSelector }),
21
- z.object({ classId: schemas.Fr }),
28
+ z.object({
29
+ address: schemas.AztecAddress,
30
+ selector: schemas.FunctionSelector,
31
+ onlySelf: z.boolean().optional(),
32
+ rejectNullMsgSender: z.boolean().optional(),
33
+ calldataLength: z.number().optional(),
34
+ }),
35
+ z.object({
36
+ classId: schemas.Fr,
37
+ selector: schemas.FunctionSelector,
38
+ onlySelf: z.boolean().optional(),
39
+ rejectNullMsgSender: z.boolean().optional(),
40
+ calldataLength: z.number().optional(),
41
+ }),
22
42
  ]),
23
43
  );