@aztec/stdlib 0.0.1-commit.cf93bcc56 → 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 (238) 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 +12 -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 +73 -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 +62 -32
  70. package/dest/interfaces/configs.d.ts.map +1 -1
  71. package/dest/interfaces/configs.js +6 -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/profiling.d.ts +4 -4
  148. package/dest/tx/profiling.d.ts.map +1 -1
  149. package/dest/tx/profiling.js +3 -3
  150. package/dest/tx/public_simulation_output.d.ts +4 -2
  151. package/dest/tx/public_simulation_output.d.ts.map +1 -1
  152. package/dest/tx/public_simulation_output.js +7 -3
  153. package/dest/tx/simulated_tx.d.ts +5 -2
  154. package/dest/tx/simulated_tx.d.ts.map +1 -1
  155. package/dest/tx/simulated_tx.js +4 -1
  156. package/dest/tx/tx.d.ts +6 -5
  157. package/dest/tx/tx.d.ts.map +1 -1
  158. package/dest/tx/tx.js +18 -6
  159. package/dest/tx/tx_receipt.d.ts +16 -2
  160. package/dest/tx/tx_receipt.d.ts.map +1 -1
  161. package/dest/tx/tx_receipt.js +11 -3
  162. package/dest/tx/validator/error_texts.d.ts +5 -1
  163. package/dest/tx/validator/error_texts.d.ts.map +1 -1
  164. package/dest/tx/validator/error_texts.js +4 -0
  165. package/dest/update-checker/index.d.ts +3 -2
  166. package/dest/update-checker/index.d.ts.map +1 -1
  167. package/dest/update-checker/index.js +2 -1
  168. package/dest/update-checker/package_version.d.ts +3 -0
  169. package/dest/update-checker/package_version.d.ts.map +1 -0
  170. package/dest/update-checker/package_version.js +11 -0
  171. package/dest/update-checker/version_checker.d.ts +25 -0
  172. package/dest/update-checker/version_checker.d.ts.map +1 -0
  173. package/dest/update-checker/version_checker.js +50 -0
  174. package/package.json +12 -11
  175. package/src/abi/decoder.ts +15 -6
  176. package/src/abi/encoder.ts +49 -6
  177. package/src/abi/event_metadata_definition.ts +2 -0
  178. package/src/abi/utils.ts +25 -0
  179. package/src/avm/revert_code.ts +15 -0
  180. package/src/block/l2_block.ts +13 -1
  181. package/src/block/l2_block_source.ts +6 -0
  182. package/src/block/l2_block_stream/l2_block_stream.ts +21 -0
  183. package/src/checkpoint/checkpoint.ts +12 -3
  184. package/src/checkpoint/index.ts +1 -0
  185. package/src/checkpoint/validate.ts +230 -0
  186. package/src/config/sequencer-config.ts +19 -1
  187. package/src/contract/contract_class.ts +3 -3
  188. package/src/gas/gas_fees.ts +7 -1
  189. package/src/ha-signing/config.ts +156 -0
  190. package/src/ha-signing/index.ts +27 -0
  191. package/src/ha-signing/local_config.ts +46 -0
  192. package/src/ha-signing/types.ts +112 -0
  193. package/src/interfaces/allowed_element.ts +29 -9
  194. package/src/interfaces/archiver.ts +1 -0
  195. package/src/interfaces/aztec-node.ts +14 -4
  196. package/src/interfaces/block-builder.ts +25 -5
  197. package/src/interfaces/configs.ts +26 -8
  198. package/src/interfaces/p2p.ts +2 -13
  199. package/src/interfaces/validator.ts +50 -28
  200. package/src/kernel/hints/build_note_hash_read_request_hints.ts +14 -18
  201. package/src/kernel/hints/build_nullifier_read_request_hints.ts +15 -18
  202. package/src/kernel/hints/build_transient_data_hints.ts +17 -2
  203. package/src/kernel/private_kernel_tail_circuit_public_inputs.ts +9 -0
  204. package/src/kv-store/config.ts +36 -0
  205. package/src/kv-store/index.ts +1 -0
  206. package/src/logs/debug_log_store.ts +54 -0
  207. package/src/logs/{directional_app_tagging_secret.ts → extended_directional_app_tagging_secret.ts} +24 -16
  208. package/src/logs/index.ts +2 -1
  209. package/src/logs/pre_tag.ts +5 -5
  210. package/src/logs/public_log.ts +4 -2
  211. package/src/logs/siloed_tag.ts +8 -2
  212. package/src/logs/tag.ts +1 -1
  213. package/src/p2p/attestation_utils.ts +56 -0
  214. package/src/p2p/block_proposal.ts +1 -1
  215. package/src/p2p/checkpoint_proposal.ts +1 -18
  216. package/src/p2p/client_type.ts +0 -6
  217. package/src/p2p/index.ts +0 -1
  218. package/src/p2p/peer_error.ts +7 -0
  219. package/src/p2p/topic_type.ts +8 -15
  220. package/src/slashing/tally.ts +34 -1
  221. package/src/tests/factories.ts +9 -0
  222. package/src/tests/mocks.ts +25 -10
  223. package/src/tx/block_header.ts +6 -0
  224. package/src/tx/profiling.ts +5 -5
  225. package/src/tx/public_simulation_output.ts +4 -0
  226. package/src/tx/simulated_tx.ts +8 -1
  227. package/src/tx/tx.ts +20 -11
  228. package/src/tx/tx_receipt.ts +10 -0
  229. package/src/tx/validator/error_texts.ts +4 -0
  230. package/src/update-checker/index.ts +2 -1
  231. package/src/update-checker/package_version.ts +17 -0
  232. package/src/update-checker/version_checker.ts +65 -0
  233. package/dest/logs/directional_app_tagging_secret.d.ts +0 -40
  234. package/dest/logs/directional_app_tagging_secret.d.ts.map +0 -1
  235. package/dest/update-checker/update-checker.d.ts +0 -49
  236. package/dest/update-checker/update-checker.d.ts.map +0 -1
  237. package/dest/update-checker/update-checker.js +0 -130
  238. package/src/update-checker/update-checker.ts +0 -166
@@ -6,7 +6,7 @@ import {
6
6
  IndexWithinCheckpoint,
7
7
  SlotNumber,
8
8
  } from '@aztec/foundation/branded-types';
9
- import { sum } from '@aztec/foundation/collection';
9
+ import { pick, sum } from '@aztec/foundation/collection';
10
10
  import { Fr } from '@aztec/foundation/curves/bn254';
11
11
  import { BufferReader, serializeSignedBigInt, serializeToBuffer } from '@aztec/foundation/serialize';
12
12
  import type { FieldsOf } from '@aztec/foundation/types';
@@ -152,10 +152,12 @@ export class Checkpoint {
152
152
  startBlockNumber?: number;
153
153
  previousArchive?: AppendOnlyTreeSnapshot;
154
154
  feeAssetPriceModifier?: bigint;
155
+ archive?: AppendOnlyTreeSnapshot;
155
156
  } & Partial<Parameters<typeof CheckpointHeader.random>[0]> &
156
157
  Partial<Parameters<typeof L2Block.random>[1]> = {},
157
158
  ) {
158
- const header = CheckpointHeader.random(options);
159
+ const headerOptions = previousArchive ? { lastArchiveRoot: previousArchive.root, ...options } : options;
160
+ const header = CheckpointHeader.random(headerOptions);
159
161
 
160
162
  // Create blocks sequentially to chain archive roots properly.
161
163
  // Each block's header.lastArchive must equal the previous block's archive.
@@ -166,11 +168,18 @@ export class Checkpoint {
166
168
  indexWithinCheckpoint: IndexWithinCheckpoint(i),
167
169
  ...options,
168
170
  ...(lastArchive ? { lastArchive } : {}),
171
+ ...pick(header, 'slotNumber', 'timestamp', 'coinbase', 'feeRecipient', 'gasFees'),
169
172
  });
170
173
  lastArchive = block.archive;
171
174
  blocks.push(block);
172
175
  }
173
176
 
174
- return new Checkpoint(AppendOnlyTreeSnapshot.random(), header, blocks, checkpointNumber, feeAssetPriceModifier);
177
+ return new Checkpoint(
178
+ options.archive ?? AppendOnlyTreeSnapshot.random(),
179
+ header,
180
+ blocks,
181
+ checkpointNumber,
182
+ feeAssetPriceModifier,
183
+ );
175
184
  }
176
185
  }
@@ -2,3 +2,4 @@ export * from './checkpoint.js';
2
2
  export * from './checkpoint_data.js';
3
3
  export * from './checkpoint_info.js';
4
4
  export * from './published_checkpoint.js';
5
+ export * from './validate.js';
@@ -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,13 +2,18 @@ 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
8
11
  * (like blockDurationMs needed by both p2p and sequencer-client) are defined here
9
12
  * to avoid duplication.
10
13
  */
11
- export const sharedSequencerConfigMappings: ConfigMappingsType<Pick<SequencerConfig, 'blockDurationMs'>> = {
14
+ export const sharedSequencerConfigMappings: ConfigMappingsType<
15
+ Pick<SequencerConfig, 'blockDurationMs' | 'expectedBlockProposalsPerSlot' | 'maxTxsPerBlock'>
16
+ > = {
12
17
  blockDurationMs: {
13
18
  env: 'SEQ_BLOCK_DURATION_MS',
14
19
  description:
@@ -16,4 +21,17 @@ export const sharedSequencerConfigMappings: ConfigMappingsType<Pick<SequencerCon
16
21
  'If undefined (default), builds a single block per slot using the full slot duration.',
17
22
  parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined),
18
23
  },
24
+ expectedBlockProposalsPerSlot: {
25
+ env: 'SEQ_EXPECTED_BLOCK_PROPOSALS_PER_SLOT',
26
+ description:
27
+ 'Expected number of block proposals per slot for P2P peer scoring. ' +
28
+ '0 (default) disables block proposal scoring. Set to a positive value to enable.',
29
+ parseEnv: (val: string) => (val ? parseInt(val, 10) : 0),
30
+ defaultValue: 0,
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
+ },
19
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
+ }