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

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 (229) 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 +12 -5
  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 +2 -2
  36. package/dest/config/sequencer-config.d.ts.map +1 -1
  37. package/dest/config/sequencer-config.js +5 -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/epoch-helpers/index.d.ts +5 -1
  41. package/dest/epoch-helpers/index.d.ts.map +1 -1
  42. package/dest/epoch-helpers/index.js +4 -2
  43. package/dest/interfaces/allowed_element.d.ts +26 -20
  44. package/dest/interfaces/allowed_element.d.ts.map +1 -1
  45. package/dest/interfaces/allowed_element.js +8 -8
  46. package/dest/interfaces/archiver.d.ts +1 -1
  47. package/dest/interfaces/archiver.d.ts.map +1 -1
  48. package/dest/interfaces/archiver.js +3 -2
  49. package/dest/interfaces/aztec-node-admin.d.ts +61 -27
  50. package/dest/interfaces/aztec-node-admin.d.ts.map +1 -1
  51. package/dest/interfaces/aztec-node.d.ts +11 -6
  52. package/dest/interfaces/aztec-node.d.ts.map +1 -1
  53. package/dest/interfaces/aztec-node.js +5 -2
  54. package/dest/interfaces/block-builder.d.ts +17 -9
  55. package/dest/interfaces/block-builder.d.ts.map +1 -1
  56. package/dest/interfaces/block-builder.js +13 -6
  57. package/dest/interfaces/configs.d.ts +57 -32
  58. package/dest/interfaces/configs.d.ts.map +1 -1
  59. package/dest/interfaces/configs.js +5 -2
  60. package/dest/interfaces/merkle_tree_operations.d.ts +9 -19
  61. package/dest/interfaces/merkle_tree_operations.d.ts.map +1 -1
  62. package/dest/interfaces/p2p.d.ts +3 -8
  63. package/dest/interfaces/p2p.d.ts.map +1 -1
  64. package/dest/interfaces/prover-client.d.ts +6 -1
  65. package/dest/interfaces/prover-client.d.ts.map +1 -1
  66. package/dest/interfaces/prover-client.js +7 -1
  67. package/dest/interfaces/validator.d.ts +67 -25
  68. package/dest/interfaces/validator.d.ts.map +1 -1
  69. package/dest/interfaces/validator.js +6 -2
  70. package/dest/kernel/hints/build_note_hash_read_request_hints.d.ts +3 -3
  71. package/dest/kernel/hints/build_note_hash_read_request_hints.d.ts.map +1 -1
  72. package/dest/kernel/hints/build_note_hash_read_request_hints.js +13 -10
  73. package/dest/kernel/hints/build_nullifier_read_request_hints.d.ts +3 -3
  74. package/dest/kernel/hints/build_nullifier_read_request_hints.d.ts.map +1 -1
  75. package/dest/kernel/hints/build_nullifier_read_request_hints.js +13 -10
  76. package/dest/kernel/hints/build_transient_data_hints.d.ts +5 -2
  77. package/dest/kernel/hints/build_transient_data_hints.d.ts.map +1 -1
  78. package/dest/kernel/hints/build_transient_data_hints.js +9 -3
  79. package/dest/kernel/private_kernel_tail_circuit_public_inputs.d.ts +2 -1
  80. package/dest/kernel/private_kernel_tail_circuit_public_inputs.d.ts.map +1 -1
  81. package/dest/kernel/private_kernel_tail_circuit_public_inputs.js +4 -0
  82. package/dest/logs/debug_log_store.d.ts +30 -0
  83. package/dest/logs/debug_log_store.d.ts.map +1 -0
  84. package/dest/logs/debug_log_store.js +30 -0
  85. package/dest/logs/extended_directional_app_tagging_secret.d.ts +47 -0
  86. package/dest/logs/extended_directional_app_tagging_secret.d.ts.map +1 -0
  87. package/dest/logs/{directional_app_tagging_secret.js → extended_directional_app_tagging_secret.js} +23 -15
  88. package/dest/logs/index.d.ts +3 -2
  89. package/dest/logs/index.d.ts.map +1 -1
  90. package/dest/logs/index.js +2 -1
  91. package/dest/logs/log_filter.d.ts +4 -1
  92. package/dest/logs/log_filter.d.ts.map +1 -1
  93. package/dest/logs/log_filter.js +2 -1
  94. package/dest/logs/pre_tag.d.ts +16 -11
  95. package/dest/logs/pre_tag.d.ts.map +1 -1
  96. package/dest/logs/pre_tag.js +2 -2
  97. package/dest/logs/public_log.d.ts +4 -3
  98. package/dest/logs/public_log.d.ts.map +1 -1
  99. package/dest/logs/public_log.js +2 -1
  100. package/dest/logs/siloed_tag.d.ts +5 -3
  101. package/dest/logs/siloed_tag.d.ts.map +1 -1
  102. package/dest/logs/siloed_tag.js +6 -1
  103. package/dest/logs/tag.js +1 -1
  104. package/dest/messaging/l2_to_l1_membership.d.ts +32 -6
  105. package/dest/messaging/l2_to_l1_membership.d.ts.map +1 -1
  106. package/dest/messaging/l2_to_l1_membership.js +69 -26
  107. package/dest/p2p/attestation_utils.d.ts +11 -1
  108. package/dest/p2p/attestation_utils.d.ts.map +1 -1
  109. package/dest/p2p/attestation_utils.js +45 -0
  110. package/dest/p2p/checkpoint_proposal.d.ts +1 -6
  111. package/dest/p2p/checkpoint_proposal.d.ts.map +1 -1
  112. package/dest/p2p/checkpoint_proposal.js +0 -12
  113. package/dest/p2p/client_type.d.ts +2 -5
  114. package/dest/p2p/client_type.d.ts.map +1 -1
  115. package/dest/p2p/client_type.js +0 -7
  116. package/dest/p2p/index.d.ts +1 -2
  117. package/dest/p2p/index.d.ts.map +1 -1
  118. package/dest/p2p/index.js +0 -1
  119. package/dest/p2p/peer_error.d.ts +3 -1
  120. package/dest/p2p/peer_error.d.ts.map +1 -1
  121. package/dest/p2p/peer_error.js +5 -0
  122. package/dest/p2p/topic_type.d.ts +3 -4
  123. package/dest/p2p/topic_type.d.ts.map +1 -1
  124. package/dest/p2p/topic_type.js +7 -24
  125. package/dest/slashing/tally.d.ts +7 -2
  126. package/dest/slashing/tally.d.ts.map +1 -1
  127. package/dest/slashing/tally.js +30 -2
  128. package/dest/tests/factories.d.ts +3 -1
  129. package/dest/tests/factories.d.ts.map +1 -1
  130. package/dest/tests/factories.js +8 -0
  131. package/dest/tests/mocks.d.ts +5 -3
  132. package/dest/tests/mocks.d.ts.map +1 -1
  133. package/dest/tests/mocks.js +18 -13
  134. package/dest/tx/block_header.d.ts +3 -1
  135. package/dest/tx/block_header.d.ts.map +1 -1
  136. package/dest/tx/block_header.js +4 -0
  137. package/dest/tx/public_simulation_output.d.ts +4 -2
  138. package/dest/tx/public_simulation_output.d.ts.map +1 -1
  139. package/dest/tx/public_simulation_output.js +7 -3
  140. package/dest/tx/simulated_tx.d.ts +5 -2
  141. package/dest/tx/simulated_tx.d.ts.map +1 -1
  142. package/dest/tx/simulated_tx.js +4 -1
  143. package/dest/tx/tx.d.ts +6 -5
  144. package/dest/tx/tx.d.ts.map +1 -1
  145. package/dest/tx/tx.js +18 -6
  146. package/dest/tx/tx_receipt.d.ts +22 -3
  147. package/dest/tx/tx_receipt.d.ts.map +1 -1
  148. package/dest/tx/tx_receipt.js +15 -4
  149. package/dest/tx/validator/error_texts.d.ts +5 -1
  150. package/dest/tx/validator/error_texts.d.ts.map +1 -1
  151. package/dest/tx/validator/error_texts.js +4 -0
  152. package/dest/update-checker/index.d.ts +3 -2
  153. package/dest/update-checker/index.d.ts.map +1 -1
  154. package/dest/update-checker/index.js +2 -1
  155. package/dest/update-checker/package_version.d.ts +3 -0
  156. package/dest/update-checker/package_version.d.ts.map +1 -0
  157. package/dest/update-checker/package_version.js +24 -0
  158. package/dest/update-checker/version_checker.d.ts +25 -0
  159. package/dest/update-checker/version_checker.d.ts.map +1 -0
  160. package/dest/update-checker/version_checker.js +50 -0
  161. package/dest/validators/errors.d.ts +6 -1
  162. package/dest/validators/errors.d.ts.map +1 -1
  163. package/dest/validators/errors.js +7 -0
  164. package/dest/versioning/versioning.d.ts +4 -2
  165. package/dest/versioning/versioning.d.ts.map +1 -1
  166. package/dest/versioning/versioning.js +4 -1
  167. package/package.json +10 -10
  168. package/src/abi/decoder.ts +15 -6
  169. package/src/abi/encoder.ts +49 -6
  170. package/src/abi/event_metadata_definition.ts +2 -0
  171. package/src/abi/utils.ts +25 -0
  172. package/src/avm/revert_code.ts +15 -0
  173. package/src/block/l2_block.ts +13 -1
  174. package/src/block/l2_block_source.ts +12 -4
  175. package/src/block/l2_block_stream/l2_block_stream.ts +21 -0
  176. package/src/checkpoint/checkpoint.ts +12 -3
  177. package/src/checkpoint/index.ts +1 -0
  178. package/src/checkpoint/validate.ts +230 -0
  179. package/src/config/sequencer-config.ts +6 -1
  180. package/src/contract/contract_class.ts +3 -3
  181. package/src/epoch-helpers/index.ts +3 -0
  182. package/src/interfaces/allowed_element.ts +29 -9
  183. package/src/interfaces/archiver.ts +3 -2
  184. package/src/interfaces/aztec-node.ts +23 -5
  185. package/src/interfaces/block-builder.ts +34 -12
  186. package/src/interfaces/configs.ts +22 -8
  187. package/src/interfaces/merkle_tree_operations.ts +8 -18
  188. package/src/interfaces/p2p.ts +2 -13
  189. package/src/interfaces/prover-client.ts +8 -0
  190. package/src/interfaces/validator.ts +18 -2
  191. package/src/kernel/hints/build_note_hash_read_request_hints.ts +14 -18
  192. package/src/kernel/hints/build_nullifier_read_request_hints.ts +15 -18
  193. package/src/kernel/hints/build_transient_data_hints.ts +17 -2
  194. package/src/kernel/private_kernel_tail_circuit_public_inputs.ts +9 -0
  195. package/src/logs/debug_log_store.ts +54 -0
  196. package/src/logs/{directional_app_tagging_secret.ts → extended_directional_app_tagging_secret.ts} +24 -16
  197. package/src/logs/index.ts +2 -1
  198. package/src/logs/log_filter.ts +5 -0
  199. package/src/logs/pre_tag.ts +5 -5
  200. package/src/logs/public_log.ts +4 -2
  201. package/src/logs/siloed_tag.ts +8 -2
  202. package/src/logs/tag.ts +1 -1
  203. package/src/messaging/l2_to_l1_membership.ts +98 -33
  204. package/src/p2p/attestation_utils.ts +56 -0
  205. package/src/p2p/checkpoint_proposal.ts +0 -17
  206. package/src/p2p/client_type.ts +0 -6
  207. package/src/p2p/index.ts +0 -1
  208. package/src/p2p/peer_error.ts +7 -0
  209. package/src/p2p/topic_type.ts +8 -15
  210. package/src/slashing/tally.ts +34 -1
  211. package/src/tests/factories.ts +9 -0
  212. package/src/tests/mocks.ts +25 -10
  213. package/src/tx/block_header.ts +6 -0
  214. package/src/tx/public_simulation_output.ts +4 -0
  215. package/src/tx/simulated_tx.ts +8 -1
  216. package/src/tx/tx.ts +20 -11
  217. package/src/tx/tx_receipt.ts +16 -1
  218. package/src/tx/validator/error_texts.ts +4 -0
  219. package/src/update-checker/index.ts +2 -1
  220. package/src/update-checker/package_version.ts +30 -0
  221. package/src/update-checker/version_checker.ts +65 -0
  222. package/src/validators/errors.ts +9 -0
  223. package/src/versioning/versioning.ts +4 -1
  224. package/dest/logs/directional_app_tagging_secret.d.ts +0 -40
  225. package/dest/logs/directional_app_tagging_secret.d.ts.map +0 -1
  226. package/dest/update-checker/update-checker.d.ts +0 -49
  227. package/dest/update-checker/update-checker.d.ts.map +0 -1
  228. package/dest/update-checker/update-checker.js +0 -130
  229. package/src/update-checker/update-checker.ts +0 -166
@@ -5,10 +5,25 @@ import { BufferReader, FieldReader } from '@aztec/foundation/serialize';
5
5
  import { inspect } from 'util';
6
6
  import { z } from 'zod';
7
7
 
8
+ /**
9
+ * Tracks which revertible phases of a transaction's public execution reverted.
10
+ *
11
+ * A transaction executes in three sequential phases:
12
+ * 1. SETUP – non-revertible; if this fails the entire transaction is rejected.
13
+ * 2. APP_LOGIC – revertible; its state changes are rolled back on failure.
14
+ * 3. TEARDOWN – revertible; always runs (even after app-logic revert) so the fee-payment contract can clean up.
15
+ *
16
+ * Only APP_LOGIC and TEARDOWN can produce a revert code. SETUP failures throw instead and discard the transaction
17
+ * entirely.
18
+ */
8
19
  export enum RevertCodeEnum {
20
+ /** All phases completed successfully; no state was rolled back. */
9
21
  OK = 0,
22
+ /** APP_LOGIC reverted; its state changes were discarded. If present, TEARDOWN still ran and succeeded. */
10
23
  APP_LOGIC_REVERTED = 1,
24
+ /** TEARDOWN reverted; its state changes were discarded. APP_LOGIC succeeded. */
11
25
  TEARDOWN_REVERTED = 2,
26
+ /** Both APP_LOGIC and TEARDOWN reverted; only SETUP effects are kept. */
12
27
  BOTH_REVERTED = 3,
13
28
  }
14
29
 
@@ -1,4 +1,5 @@
1
1
  import { type BlockBlobData, encodeBlockBlobData } from '@aztec/blob-lib/encoding';
2
+ import { DA_GAS_PER_FIELD } from '@aztec/constants';
2
3
  import {
3
4
  BlockNumber,
4
5
  CheckpointNumber,
@@ -175,7 +176,7 @@ export class L2Block {
175
176
  } & Partial<Parameters<typeof BlockHeader.random>[0]> = {},
176
177
  ): Promise<L2Block> {
177
178
  const archive = new AppendOnlyTreeSnapshot(Fr.random(), blockNumber + 1);
178
- const header = BlockHeader.random({ blockNumber, ...blockHeaderOverrides });
179
+ const header = BlockHeader.random({ ...blockHeaderOverrides, blockNumber });
179
180
  const body = await Body.random({ txsPerBlock, makeTxOptions, ...txOptions });
180
181
  return new L2Block(archive, header, body, checkpointNumber, indexWithinCheckpoint);
181
182
  }
@@ -221,4 +222,15 @@ export class L2Block {
221
222
  timestamp: this.header.globalVariables.timestamp,
222
223
  };
223
224
  }
225
+
226
+ /**
227
+ * Compute how much DA gas this block uses.
228
+ *
229
+ * @remarks This assumes DA gas is computed solely based on the number of blob fields in transactions.
230
+ * This may change in the future, but we cannot access the actual DA gas used in a block since it's not exposed
231
+ * in the L2BlockHeader, so we have to rely on recomputing it.
232
+ */
233
+ computeDAGasUsed(): number {
234
+ return this.body.txEffects.reduce((total, txEffect) => total + txEffect.getNumBlobFields(), 0) * DA_GAS_PER_FIELD;
235
+ }
224
236
  }
@@ -49,6 +49,12 @@ export interface L2BlockSource {
49
49
  */
50
50
  getBlockNumber(): Promise<BlockNumber>;
51
51
 
52
+ /**
53
+ * Gets the number of the latest L2 checkpoint processed by the block source implementation.
54
+ * @returns The number of the latest L2 checkpoint processed by the block source implementation.
55
+ */
56
+ getCheckpointNumber(): Promise<CheckpointNumber>;
57
+
52
58
  /**
53
59
  * Gets the number of the latest L2 block proven seen by the block source implementation.
54
60
  * @returns The number of the latest L2 block proven seen by the block source implementation.
@@ -170,14 +176,16 @@ export interface L2BlockSource {
170
176
  getSettledTxReceipt(txHash: TxHash): Promise<TxReceipt | undefined>;
171
177
 
172
178
  /**
173
- * Returns the current L2 slot number based on the currently synced L1 timestamp.
179
+ * Returns the last L2 slot number that has been fully synchronized from L1.
180
+ * An L2 slot is fully synced when all L1 blocks that fall within its time range have been processed.
174
181
  */
175
- getL2SlotNumber(): Promise<SlotNumber | undefined>;
182
+ getSyncedL2SlotNumber(): Promise<SlotNumber | undefined>;
176
183
 
177
184
  /**
178
- * Returns the current L2 epoch number based on the currently synced L1 timestamp.
185
+ * Returns the last L2 epoch number that has been fully synchronized from L1.
186
+ * An epoch is fully synced when all its L2 slots have been fully synced.
179
187
  */
180
- getL2EpochNumber(): Promise<EpochNumber | undefined>;
188
+ getSyncedL2EpochNumber(): Promise<EpochNumber | undefined>;
181
189
 
182
190
  /**
183
191
  * Returns all checkpointed block headers for a given epoch.
@@ -109,6 +109,27 @@ export class L2BlockStream {
109
109
 
110
110
  let nextBlockNumber = latestBlockNumber + 1;
111
111
  let nextCheckpointToEmit = CheckpointNumber(localTips.checkpointed.checkpoint.number + 1);
112
+
113
+ // When startingBlock is set, also skip ahead for checkpoints.
114
+ if (
115
+ this.opts.startingBlock !== undefined &&
116
+ this.opts.startingBlock >= 1 &&
117
+ nextCheckpointToEmit <= sourceTips.checkpointed.checkpoint.number
118
+ ) {
119
+ const startingBlockCheckpoints = await this.l2BlockSource.getCheckpointedBlocks(
120
+ BlockNumber(this.opts.startingBlock),
121
+ 1,
122
+ );
123
+ if (startingBlockCheckpoints.length > 0) {
124
+ nextCheckpointToEmit = CheckpointNumber(
125
+ Math.max(nextCheckpointToEmit, startingBlockCheckpoints[0].checkpointNumber),
126
+ );
127
+ } else {
128
+ // startingBlock is past all checkpointed blocks; skip Loop 1 entirely.
129
+ nextCheckpointToEmit = CheckpointNumber(sourceTips.checkpointed.checkpoint.number + 1);
130
+ }
131
+ }
132
+
112
133
  if (this.opts.skipFinalized) {
113
134
  // When skipping finalized blocks we need to provide reliable reorg detection while fetching as few blocks as
114
135
  // possible. Finalized blocks cannot be reorged by definition, so we can skip most of them. We do need the very
@@ -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
+ }
@@ -9,7 +9,7 @@ import type { SequencerConfig } from '../interfaces/configs.js';
9
9
  * to avoid duplication.
10
10
  */
11
11
  export const sharedSequencerConfigMappings: ConfigMappingsType<
12
- Pick<SequencerConfig, 'blockDurationMs' | 'expectedBlockProposalsPerSlot'>
12
+ Pick<SequencerConfig, 'blockDurationMs' | 'expectedBlockProposalsPerSlot' | 'maxTxsPerBlock'>
13
13
  > = {
14
14
  blockDurationMs: {
15
15
  env: 'SEQ_BLOCK_DURATION_MS',
@@ -26,4 +26,9 @@ export const sharedSequencerConfigMappings: ConfigMappingsType<
26
26
  parseEnv: (val: string) => (val ? parseInt(val, 10) : 0),
27
27
  defaultValue: 0,
28
28
  },
29
+ maxTxsPerBlock: {
30
+ env: 'SEQ_MAX_TX_PER_BLOCK',
31
+ description: 'The maximum number of txs to include in a block.',
32
+ parseEnv: (val: string) => (val ? parseInt(val, 10) : undefined),
33
+ },
29
34
  };
@@ -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,
@@ -12,6 +12,7 @@ export type L1RollupConstants = {
12
12
  ethereumSlotDuration: number;
13
13
  proofSubmissionEpochs: number;
14
14
  targetCommitteeSize: number;
15
+ rollupManaLimit: number;
15
16
  };
16
17
 
17
18
  export const EmptyL1RollupConstants: L1RollupConstants = {
@@ -22,6 +23,7 @@ export const EmptyL1RollupConstants: L1RollupConstants = {
22
23
  ethereumSlotDuration: 1,
23
24
  proofSubmissionEpochs: 1,
24
25
  targetCommitteeSize: 48,
26
+ rollupManaLimit: Number.MAX_SAFE_INTEGER,
25
27
  };
26
28
 
27
29
  export const L1RollupConstantsSchema = zodFor<L1RollupConstants>()(
@@ -33,6 +35,7 @@ export const L1RollupConstantsSchema = zodFor<L1RollupConstants>()(
33
35
  ethereumSlotDuration: z.number(),
34
36
  proofSubmissionEpochs: z.number(),
35
37
  targetCommitteeSize: z.number(),
38
+ rollupManaLimit: z.number(),
36
39
  }),
37
40
  );
38
41
 
@@ -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
  );
@@ -86,6 +86,7 @@ export const ArchiverApiSchema: ApiSchemaFor<ArchiverApi> = {
86
86
  getBlockNumber: z.function().args().returns(BlockNumberSchema),
87
87
  getProvenBlockNumber: z.function().args().returns(BlockNumberSchema),
88
88
  getCheckpointedL2BlockNumber: z.function().args().returns(BlockNumberSchema),
89
+ getCheckpointNumber: z.function().args().returns(CheckpointNumberSchema),
89
90
  getFinalizedL2BlockNumber: z.function().args().returns(BlockNumberSchema),
90
91
  getBlock: z.function().args(BlockNumberSchema).returns(L2Block.schema.optional()),
91
92
  getBlockHeader: z
@@ -113,8 +114,8 @@ export const ArchiverApiSchema: ApiSchemaFor<ArchiverApi> = {
113
114
  getL2BlockByArchive: z.function().args(schemas.Fr).returns(L2Block.schema.optional()),
114
115
  getTxEffect: z.function().args(TxHash.schema).returns(indexedTxSchema().optional()),
115
116
  getSettledTxReceipt: z.function().args(TxHash.schema).returns(TxReceipt.schema.optional()),
116
- getL2SlotNumber: z.function().args().returns(schemas.SlotNumber.optional()),
117
- getL2EpochNumber: z.function().args().returns(EpochNumberSchema.optional()),
117
+ getSyncedL2SlotNumber: z.function().args().returns(schemas.SlotNumber.optional()),
118
+ getSyncedL2EpochNumber: z.function().args().returns(EpochNumberSchema.optional()),
118
119
  getCheckpointsForEpoch: z.function().args(EpochNumberSchema).returns(z.array(Checkpoint.schema)),
119
120
  getCheckpointsDataForEpoch: z.function().args(EpochNumberSchema).returns(z.array(CheckpointDataSchema)),
120
121
  getCheckpointedBlocksForEpoch: z.function().args(EpochNumberSchema).returns(z.array(CheckpointedL2Block.schema)),
@@ -4,7 +4,9 @@ import {
4
4
  BlockNumber,
5
5
  BlockNumberPositiveSchema,
6
6
  BlockNumberSchema,
7
+ CheckpointNumber,
7
8
  CheckpointNumberPositiveSchema,
9
+ CheckpointNumberSchema,
8
10
  EpochNumber,
9
11
  EpochNumberSchema,
10
12
  type SlotNumber,
@@ -23,6 +25,7 @@ import { CheckpointedL2Block } from '../block/checkpointed_l2_block.js';
23
25
  import { type DataInBlock, dataInBlockSchemaFor } from '../block/in_block.js';
24
26
  import { L2Block } from '../block/l2_block.js';
25
27
  import { type L2BlockSource, type L2Tips, L2TipsSchema } from '../block/l2_block_source.js';
28
+ import { CheckpointDataSchema } from '../checkpoint/checkpoint_data.js';
26
29
  import { PublishedCheckpoint } from '../checkpoint/published_checkpoint.js';
27
30
  import {
28
31
  type ContractClassPublic,
@@ -72,7 +75,12 @@ import { type WorldStateSyncStatus, WorldStateSyncStatusSchema } from './world_s
72
75
  export interface AztecNode
73
76
  extends Pick<
74
77
  L2BlockSource,
75
- 'getBlocks' | 'getCheckpoints' | 'getBlockHeader' | 'getL2Tips' | 'getCheckpointedBlocks'
78
+ | 'getBlocks'
79
+ | 'getCheckpoints'
80
+ | 'getBlockHeader'
81
+ | 'getL2Tips'
82
+ | 'getCheckpointedBlocks'
83
+ | 'getCheckpointsDataForEpoch'
76
84
  > {
77
85
  /**
78
86
  * Returns the tips of the L2 chain.
@@ -172,14 +180,14 @@ export interface AztecNode
172
180
  l1ToL2Message: Fr,
173
181
  ): Promise<[bigint, SiblingPath<typeof L1_TO_L2_MSG_TREE_HEIGHT>] | undefined>;
174
182
 
175
- /** Returns the L2 block number in which this L1 to L2 message becomes available, or undefined if not found. */
176
- getL1ToL2MessageBlock(l1ToL2Message: Fr): Promise<BlockNumber | undefined>;
183
+ /** Returns the L2 checkpoint number in which this L1 to L2 message becomes available, or undefined if not found. */
184
+ getL1ToL2MessageCheckpoint(l1ToL2Message: Fr): Promise<CheckpointNumber | undefined>;
177
185
 
178
186
  /**
179
187
  * Returns whether an L1 to L2 message is synced by archiver.
180
188
  * @param l1ToL2Message - The L1 to L2 message to check.
181
189
  * @returns Whether the message is synced.
182
- * @deprecated Use `getL1ToL2MessageBlock` instead. This method may return true even if the message is not ready to use.
190
+ * @deprecated Use `getL1ToL2MessageCheckpoint` instead. This method may return true even if the message is not ready to use.
183
191
  */
184
192
  isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise<boolean>;
185
193
 
@@ -230,6 +238,12 @@ export interface AztecNode
230
238
  */
231
239
  getCheckpointedBlockNumber(): Promise<BlockNumber>;
232
240
 
241
+ /**
242
+ * Method to fetch the latest checkpoint number synchronized by the node.
243
+ * @returns The checkpoint number.
244
+ */
245
+ getCheckpointNumber(): Promise<CheckpointNumber>;
246
+
233
247
  /**
234
248
  * Method to determine if the node is ready to accept transactions.
235
249
  * @returns - Flag indicating the readiness for tx submission.
@@ -517,7 +531,7 @@ export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
517
531
  .args(BlockParameterSchema, schemas.Fr)
518
532
  .returns(z.tuple([schemas.BigInt, SiblingPath.schemaFor(L1_TO_L2_MSG_TREE_HEIGHT)]).optional()),
519
533
 
520
- getL1ToL2MessageBlock: z.function().args(schemas.Fr).returns(BlockNumberSchema.optional()),
534
+ getL1ToL2MessageCheckpoint: z.function().args(schemas.Fr).returns(CheckpointNumberSchema.optional()),
521
535
 
522
536
  isL1ToL2MessageSynced: z.function().args(schemas.Fr).returns(z.boolean()),
523
537
 
@@ -534,6 +548,8 @@ export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
534
548
 
535
549
  getBlockNumber: z.function().returns(BlockNumberSchema),
536
550
 
551
+ getCheckpointNumber: z.function().returns(CheckpointNumberSchema),
552
+
537
553
  getProvenBlockNumber: z.function().returns(BlockNumberSchema),
538
554
 
539
555
  getCheckpointedBlockNumber: z.function().returns(BlockNumberSchema),
@@ -557,6 +573,8 @@ export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
557
573
  .args(BlockNumberPositiveSchema, z.number().gt(0).lte(MAX_RPC_BLOCKS_LEN))
558
574
  .returns(z.array(CheckpointedL2Block.schema)),
559
575
 
576
+ getCheckpointsDataForEpoch: z.function().args(EpochNumberSchema).returns(z.array(CheckpointDataSchema)),
577
+
560
578
  getCurrentMinFees: z.function().returns(GasFees.schema),
561
579
 
562
580
  getMaxPriorityFees: z.function().returns(GasFees.schema),