@aztec/prover-node 3.0.0-nightly.20251202 → 3.0.0-nightly.20251203

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.
@@ -87,15 +87,15 @@ export class ProverNodePublisher {
87
87
 
88
88
  public async submitEpochProof(args: {
89
89
  epochNumber: EpochNumber;
90
- fromBlock: number;
91
- toBlock: number;
90
+ fromCheckpoint: CheckpointNumber;
91
+ toCheckpoint: CheckpointNumber;
92
92
  publicInputs: RootRollupPublicInputs;
93
93
  proof: Proof;
94
94
  batchedBlobInputs: BatchedBlob;
95
95
  attestations: ViemCommitteeAttestation[];
96
96
  }): Promise<boolean> {
97
- const { epochNumber, fromBlock, toBlock } = args;
98
- const ctx = { epochNumber, fromBlock, toBlock };
97
+ const { epochNumber, fromCheckpoint, toCheckpoint } = args;
98
+ const ctx = { epochNumber, fromCheckpoint, toCheckpoint };
99
99
 
100
100
  if (!this.interrupted) {
101
101
  const timer = new Timer();
@@ -139,45 +139,48 @@ export class ProverNodePublisher {
139
139
  this.log.error(`Rollup.submitEpochProof tx status failed ${txReceipt.transactionHash}`, undefined, ctx);
140
140
  }
141
141
 
142
- this.log.verbose('L2 block data syncing interrupted', ctx);
142
+ this.log.verbose('Checkpoint data syncing interrupted', ctx);
143
143
  return false;
144
144
  }
145
145
 
146
146
  private async validateEpochProofSubmission(args: {
147
- fromBlock: number;
148
- toBlock: number;
147
+ fromCheckpoint: CheckpointNumber;
148
+ toCheckpoint: CheckpointNumber;
149
149
  publicInputs: RootRollupPublicInputs;
150
150
  proof: Proof;
151
151
  batchedBlobInputs: BatchedBlob;
152
152
  attestations: ViemCommitteeAttestation[];
153
153
  }) {
154
- const { fromBlock, toBlock, publicInputs, batchedBlobInputs } = args;
154
+ const { fromCheckpoint, toCheckpoint, publicInputs, batchedBlobInputs } = args;
155
155
 
156
- // Check that the block numbers match the expected epoch to be proven
157
- // TODO: These are checkpoint numbers, not block numbers. Fix when we decouple them properly.
156
+ // Check that the checkpoint numbers match the expected epoch to be proven
158
157
  const { pending, proven } = await this.rollupContract.getTips();
159
- // Don't publish if proven is beyond our toBlock, pointless to do so
160
- if (proven > BigInt(toBlock)) {
161
- throw new Error(`Cannot submit epoch proof for ${fromBlock}-${toBlock} as proven block is ${proven}`);
158
+ // Don't publish if proven is beyond our toCheckpoint, pointless to do so
159
+ if (proven > BigInt(toCheckpoint)) {
160
+ throw new Error(
161
+ `Cannot submit epoch proof for ${fromCheckpoint}-${toCheckpoint} as proven checkpoint is ${proven}`,
162
+ );
162
163
  }
163
- // toBlock can't be greater than pending
164
- if (toBlock > pending) {
165
- throw new Error(`Cannot submit epoch proof for ${fromBlock}-${toBlock} as pending block is ${pending}`);
164
+ // toCheckpoint can't be greater than pending
165
+ if (toCheckpoint > pending) {
166
+ throw new Error(
167
+ `Cannot submit epoch proof for ${fromCheckpoint}-${toCheckpoint} as pending checkpoint is ${pending}`,
168
+ );
166
169
  }
167
170
 
168
- // Check the archive for the immediate block before the epoch
169
- const blockLog = await this.rollupContract.getCheckpoint(CheckpointNumber.fromBlockNumber(fromBlock - 1));
170
- if (publicInputs.previousArchiveRoot.toString() !== blockLog.archive) {
171
+ // Check the archive for the immediate checkpoint before the epoch
172
+ const checkpointLog = await this.rollupContract.getCheckpoint(CheckpointNumber(fromCheckpoint - 1));
173
+ if (publicInputs.previousArchiveRoot.toString() !== checkpointLog.archive) {
171
174
  throw new Error(
172
- `Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${blockLog.archive}`,
175
+ `Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${checkpointLog.archive}`,
173
176
  );
174
177
  }
175
178
 
176
- // Check the archive for the last block in the epoch
177
- const endBlockLog = await this.rollupContract.getCheckpoint(CheckpointNumber.fromBlockNumber(toBlock));
178
- if (publicInputs.endArchiveRoot.toString() !== endBlockLog.archive) {
179
+ // Check the archive for the last checkpoint in the epoch
180
+ const endCheckpointLog = await this.rollupContract.getCheckpoint(toCheckpoint);
181
+ if (publicInputs.endArchiveRoot.toString() !== endCheckpointLog.archive) {
179
182
  throw new Error(
180
- `End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${endBlockLog.archive}`,
183
+ `End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${endCheckpointLog.archive}`,
181
184
  );
182
185
  }
183
186
 
@@ -204,8 +207,8 @@ export class ProverNodePublisher {
204
207
  }
205
208
 
206
209
  private async sendSubmitEpochProofTx(args: {
207
- fromBlock: number;
208
- toBlock: number;
210
+ fromCheckpoint: CheckpointNumber;
211
+ toCheckpoint: CheckpointNumber;
209
212
  publicInputs: RootRollupPublicInputs;
210
213
  proof: Proof;
211
214
  batchedBlobInputs: BatchedBlob;
@@ -215,8 +218,8 @@ export class ProverNodePublisher {
215
218
 
216
219
  this.log.info(`Submitting epoch proof to L1 rollup contract`, {
217
220
  proofSize: args.proof.withoutPublicInputs().length,
218
- fromBlock: args.fromBlock,
219
- toBlock: args.toBlock,
221
+ fromCheckpoint: args.fromCheckpoint,
222
+ toCheckpoint: args.toCheckpoint,
220
223
  });
221
224
  const data = encodeFunctionData({
222
225
  abi: RollupAbi,
@@ -245,16 +248,16 @@ export class ProverNodePublisher {
245
248
  }
246
249
 
247
250
  private getEpochProofPublicInputsArgs(args: {
248
- fromBlock: number;
249
- toBlock: number;
251
+ fromCheckpoint: CheckpointNumber;
252
+ toCheckpoint: CheckpointNumber;
250
253
  publicInputs: RootRollupPublicInputs;
251
254
  batchedBlobInputs: BatchedBlob;
252
255
  attestations: ViemCommitteeAttestation[];
253
256
  }) {
254
257
  // Returns arguments for EpochProofLib.sol -> getEpochProofPublicInputs()
255
258
  return [
256
- BigInt(args.fromBlock) /*_start*/,
257
- BigInt(args.toBlock) /*_end*/,
259
+ BigInt(args.fromCheckpoint) /*_start*/,
260
+ BigInt(args.toCheckpoint) /*_end*/,
258
261
  {
259
262
  previousArchive: args.publicInputs.previousArchiveRoot.toString(),
260
263
  endArchive: args.publicInputs.endArchiveRoot.toString(),
@@ -270,8 +273,8 @@ export class ProverNodePublisher {
270
273
  }
271
274
 
272
275
  private getSubmitEpochProofArgs(args: {
273
- fromBlock: number;
274
- toBlock: number;
276
+ fromCheckpoint: CheckpointNumber;
277
+ toCheckpoint: CheckpointNumber;
275
278
  publicInputs: RootRollupPublicInputs;
276
279
  proof: Proof;
277
280
  batchedBlobInputs: BatchedBlob;
@@ -1,6 +1,6 @@
1
1
  import type { Archiver } from '@aztec/archiver';
2
2
  import type { RollupContract } from '@aztec/ethereum';
3
- import { EpochNumber } from '@aztec/foundation/branded-types';
3
+ import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
4
4
  import { assertRequired, compact, pick, sum } from '@aztec/foundation/collection';
5
5
  import { memoize } from '@aztec/foundation/decorators';
6
6
  import type { Fr } from '@aztec/foundation/fields';
@@ -9,7 +9,8 @@ import { DateProvider } from '@aztec/foundation/timer';
9
9
  import type { DataStoreConfig } from '@aztec/kv-store/config';
10
10
  import type { P2PClient } from '@aztec/p2p';
11
11
  import { PublicProcessorFactory } from '@aztec/simulator/server';
12
- import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
12
+ import type { L2BlockSource } from '@aztec/stdlib/block';
13
+ import type { Checkpoint } from '@aztec/stdlib/checkpoint';
13
14
  import type { ChainConfig } from '@aztec/stdlib/config';
14
15
  import type { ContractDataSource } from '@aztec/stdlib/contract';
15
16
  import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
@@ -271,10 +272,13 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
271
272
 
272
273
  // Gather all data for this epoch
273
274
  const epochData = await this.gatherEpochData(epochNumber);
274
-
275
- const fromBlock = epochData.blocks[0].number;
276
- const toBlock = epochData.blocks.at(-1)!.number;
277
- this.log.verbose(`Creating proving job for epoch ${epochNumber} for block range ${fromBlock} to ${toBlock}`);
275
+ const fromCheckpoint = epochData.checkpoints[0].number;
276
+ const toCheckpoint = epochData.checkpoints.at(-1)!.number;
277
+ const fromBlock = epochData.checkpoints[0].blocks[0].number;
278
+ const toBlock = epochData.checkpoints.at(-1)!.blocks.at(-1)!.number;
279
+ this.log.verbose(
280
+ `Creating proving job for epoch ${epochNumber} for checkpoint range ${fromCheckpoint} to ${toCheckpoint} and block range ${fromBlock} to ${toBlock}`,
281
+ );
278
282
 
279
283
  // Fast forward world state to right before the target block and get a fork
280
284
  await this.worldState.syncImmediate(toBlock);
@@ -289,7 +293,6 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
289
293
  // Set deadline for this job to run. It will abort if it takes too long.
290
294
  const deadlineTs = getProofSubmissionDeadlineTimestamp(epochNumber, await this.getL1Constants());
291
295
  const deadline = new Date(Number(deadlineTs) * 1000);
292
-
293
296
  const job = this.doCreateEpochProvingJob(epochData, deadline, publicProcessorFactory, this.publisher, opts);
294
297
  this.jobs.set(job.getId(), job);
295
298
  return job;
@@ -302,28 +305,30 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
302
305
 
303
306
  @trackSpan('ProverNode.gatherEpochData', epochNumber => ({ [Attributes.EPOCH_NUMBER]: epochNumber }))
304
307
  private async gatherEpochData(epochNumber: EpochNumber): Promise<EpochProvingJobData> {
305
- const blocks = await this.gatherBlocks(epochNumber);
306
- const txArray = await this.gatherTxs(epochNumber, blocks);
308
+ const checkpoints = await this.gatherCheckpoints(epochNumber);
309
+ const txArray = await this.gatherTxs(epochNumber, checkpoints);
307
310
  const txs = new Map<string, Tx>(txArray.map(tx => [tx.getTxHash().toString(), tx]));
308
- const l1ToL2Messages = await this.gatherMessages(epochNumber, blocks);
309
- const previousBlockHeader = await this.gatherPreviousBlockHeader(epochNumber, blocks[0]);
310
- const [lastBlock] = await this.l2BlockSource.getPublishedBlocks(blocks.at(-1)!.number, 1);
311
- const attestations = lastBlock?.attestations ?? [];
311
+ const l1ToL2Messages = await this.gatherMessages(epochNumber, checkpoints);
312
+ const [firstBlock] = checkpoints[0].blocks;
313
+ const previousBlockHeader = await this.gatherPreviousBlockHeader(epochNumber, firstBlock.number - 1);
314
+ const [lastPublishedCheckpoint] = await this.l2BlockSource.getPublishedCheckpoints(checkpoints.at(-1)!.number, 1);
315
+ const attestations = lastPublishedCheckpoint?.attestations ?? [];
312
316
 
313
- return { blocks, txs, l1ToL2Messages, epochNumber, previousBlockHeader, attestations };
317
+ return { checkpoints, txs, l1ToL2Messages, epochNumber, previousBlockHeader, attestations };
314
318
  }
315
319
 
316
- private async gatherBlocks(epochNumber: EpochNumber) {
317
- const blocks = await this.l2BlockSource.getBlocksForEpoch(epochNumber);
318
- if (blocks.length === 0) {
320
+ private async gatherCheckpoints(epochNumber: EpochNumber) {
321
+ const checkpoints = await this.l2BlockSource.getCheckpointsForEpoch(epochNumber);
322
+ if (checkpoints.length === 0) {
319
323
  throw new EmptyEpochError(epochNumber);
320
324
  }
321
- return blocks;
325
+ return checkpoints;
322
326
  }
323
327
 
324
- private async gatherTxs(epochNumber: EpochNumber, blocks: L2Block[]) {
328
+ private async gatherTxs(epochNumber: EpochNumber, checkpoints: Checkpoint[]) {
325
329
  const deadline = new Date(this.dateProvider.now() + this.config.txGatheringTimeoutMs);
326
330
  const txProvider = this.p2pClient.getTxProvider();
331
+ const blocks = checkpoints.flatMap(checkpoint => checkpoint.blocks);
327
332
  const txsByBlock = await Promise.all(blocks.map(block => txProvider.getTxsForBlock(block, { deadline })));
328
333
  const txs = txsByBlock.map(({ txs }) => txs).flat();
329
334
  const missingTxs = txsByBlock.map(({ missingTxs }) => missingTxs).flat();
@@ -336,25 +341,26 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable
336
341
  throw new Error(`Txs not found for epoch ${epochNumber}: ${missingTxs.map(hash => hash.toString()).join(', ')}`);
337
342
  }
338
343
 
339
- private async gatherMessages(epochNumber: EpochNumber, blocks: L2Block[]) {
340
- const messages = await Promise.all(blocks.map(b => this.l1ToL2MessageSource.getL1ToL2Messages(b.number)));
344
+ private async gatherMessages(epochNumber: EpochNumber, checkpoints: Checkpoint[]) {
345
+ const messages = await Promise.all(
346
+ checkpoints.map(c => this.l1ToL2MessageSource.getL1ToL2MessagesForCheckpoint(c.number)),
347
+ );
341
348
  const messageCount = sum(messages.map(m => m.length));
342
349
  this.log.verbose(`Gathered all ${messageCount} messages for epoch ${epochNumber}`, { epochNumber });
343
- const messagesByBlock: Record<number, Fr[]> = {};
344
- for (let i = 0; i < blocks.length; i++) {
345
- messagesByBlock[blocks[i].number] = messages[i];
350
+ const messagesByCheckpoint: Record<CheckpointNumber, Fr[]> = {};
351
+ for (let i = 0; i < checkpoints.length; i++) {
352
+ messagesByCheckpoint[checkpoints[i].number] = messages[i];
346
353
  }
347
- return messagesByBlock;
354
+ return messagesByCheckpoint;
348
355
  }
349
356
 
350
- private async gatherPreviousBlockHeader(epochNumber: EpochNumber, initialBlock: L2Block) {
351
- const previousBlockNumber = initialBlock.number - 1;
357
+ private async gatherPreviousBlockHeader(epochNumber: EpochNumber, previousBlockNumber: number) {
352
358
  const header = await (previousBlockNumber === 0
353
359
  ? this.worldState.getCommitted().getInitialHeader()
354
360
  : this.l2BlockSource.getBlockHeader(previousBlockNumber));
355
361
 
356
362
  if (!header) {
357
- throw new Error(`Previous block header ${initialBlock.number} not found for proving epoch ${epochNumber}`);
363
+ throw new Error(`Previous block header ${previousBlockNumber} not found for proving epoch ${epochNumber}`);
358
364
  }
359
365
 
360
366
  this.log.verbose(`Gathered previous block header ${header.getBlockNumber()} for epoch ${epochNumber}`);