@aztec/prover-node 0.0.0-test.1 → 0.0.1-fake-ceab37513c

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 (81) hide show
  1. package/dest/actions/download-epoch-proving-job.d.ts +18 -0
  2. package/dest/actions/download-epoch-proving-job.d.ts.map +1 -0
  3. package/dest/actions/download-epoch-proving-job.js +37 -0
  4. package/dest/actions/index.d.ts +3 -0
  5. package/dest/actions/index.d.ts.map +1 -0
  6. package/dest/actions/index.js +2 -0
  7. package/dest/actions/rerun-epoch-proving-job.d.ts +11 -0
  8. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -0
  9. package/dest/actions/rerun-epoch-proving-job.js +40 -0
  10. package/dest/actions/upload-epoch-proof-failure.d.ts +15 -0
  11. package/dest/actions/upload-epoch-proof-failure.d.ts.map +1 -0
  12. package/dest/actions/upload-epoch-proof-failure.js +78 -0
  13. package/dest/bin/run-failed-epoch.d.ts +2 -0
  14. package/dest/bin/run-failed-epoch.d.ts.map +1 -0
  15. package/dest/bin/run-failed-epoch.js +67 -0
  16. package/dest/config.d.ts +12 -9
  17. package/dest/config.d.ts.map +1 -1
  18. package/dest/config.js +81 -14
  19. package/dest/factory.d.ts +12 -8
  20. package/dest/factory.d.ts.map +1 -1
  21. package/dest/factory.js +94 -31
  22. package/dest/index.d.ts +1 -1
  23. package/dest/index.d.ts.map +1 -1
  24. package/dest/index.js +1 -1
  25. package/dest/job/epoch-proving-job-data.d.ts +16 -0
  26. package/dest/job/epoch-proving-job-data.d.ts.map +1 -0
  27. package/dest/job/epoch-proving-job-data.js +52 -0
  28. package/dest/job/epoch-proving-job.d.ts +30 -15
  29. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  30. package/dest/job/epoch-proving-job.js +119 -46
  31. package/dest/metrics.d.ts +28 -4
  32. package/dest/metrics.d.ts.map +1 -1
  33. package/dest/metrics.js +141 -35
  34. package/dest/monitors/epoch-monitor.d.ts +3 -1
  35. package/dest/monitors/epoch-monitor.d.ts.map +1 -1
  36. package/dest/monitors/epoch-monitor.js +15 -2
  37. package/dest/prover-node-publisher.d.ts +7 -10
  38. package/dest/prover-node-publisher.d.ts.map +1 -1
  39. package/dest/prover-node-publisher.js +58 -59
  40. package/dest/prover-node.d.ts +43 -39
  41. package/dest/prover-node.d.ts.map +1 -1
  42. package/dest/prover-node.js +171 -100
  43. package/dest/prover-publisher-factory.d.ts +21 -0
  44. package/dest/prover-publisher-factory.d.ts.map +1 -0
  45. package/dest/prover-publisher-factory.js +26 -0
  46. package/dest/test/index.d.ts +4 -2
  47. package/dest/test/index.d.ts.map +1 -1
  48. package/dest/test/index.js +1 -3
  49. package/package.json +36 -31
  50. package/src/actions/download-epoch-proving-job.ts +44 -0
  51. package/src/actions/index.ts +2 -0
  52. package/src/actions/rerun-epoch-proving-job.ts +61 -0
  53. package/src/actions/upload-epoch-proof-failure.ts +88 -0
  54. package/src/bin/run-failed-epoch.ts +77 -0
  55. package/src/config.ts +108 -24
  56. package/src/factory.ts +158 -43
  57. package/src/index.ts +1 -1
  58. package/src/job/epoch-proving-job-data.ts +76 -0
  59. package/src/job/epoch-proving-job.ts +177 -46
  60. package/src/metrics.ts +135 -37
  61. package/src/monitors/epoch-monitor.ts +16 -5
  62. package/src/prover-node-publisher.ts +90 -85
  63. package/src/prover-node.ts +203 -126
  64. package/src/prover-publisher-factory.ts +37 -0
  65. package/src/test/index.ts +7 -4
  66. package/dest/http.d.ts +0 -8
  67. package/dest/http.d.ts.map +0 -1
  68. package/dest/http.js +0 -9
  69. package/dest/prover-coordination/config.d.ts +0 -7
  70. package/dest/prover-coordination/config.d.ts.map +0 -1
  71. package/dest/prover-coordination/config.js +0 -11
  72. package/dest/prover-coordination/factory.d.ts +0 -22
  73. package/dest/prover-coordination/factory.d.ts.map +0 -1
  74. package/dest/prover-coordination/factory.js +0 -42
  75. package/dest/prover-coordination/index.d.ts +0 -3
  76. package/dest/prover-coordination/index.d.ts.map +0 -1
  77. package/dest/prover-coordination/index.js +0 -2
  78. package/src/http.ts +0 -13
  79. package/src/prover-coordination/config.ts +0 -17
  80. package/src/prover-coordination/factory.ts +0 -72
  81. package/src/prover-coordination/index.ts +0 -2
package/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
+ export * from './actions/index.js';
1
2
  export * from './config.js';
2
3
  export * from './factory.js';
3
- export * from './http.js';
4
4
  export * from './prover-node-publisher.js';
5
5
  export * from './prover-node.js';
@@ -0,0 +1,76 @@
1
+ import { Fr } from '@aztec/foundation/fields';
2
+ import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
3
+ import { CommitteeAttestation, L2Block } from '@aztec/stdlib/block';
4
+ import { BlockHeader, Tx } from '@aztec/stdlib/tx';
5
+
6
+ /** All data from an epoch used in proving. */
7
+ export type EpochProvingJobData = {
8
+ epochNumber: bigint;
9
+ blocks: L2Block[];
10
+ txs: Map<string, Tx>;
11
+ l1ToL2Messages: Record<number, Fr[]>;
12
+ previousBlockHeader: BlockHeader;
13
+ attestations: CommitteeAttestation[];
14
+ };
15
+
16
+ export function validateEpochProvingJobData(data: EpochProvingJobData) {
17
+ if (data.blocks.length > 0 && data.previousBlockHeader.getBlockNumber() + 1 !== data.blocks[0].number) {
18
+ throw new Error(
19
+ `Initial block number ${
20
+ data.blocks[0].number
21
+ } does not match previous block header ${data.previousBlockHeader.getBlockNumber()}`,
22
+ );
23
+ }
24
+
25
+ for (const blockNumber of data.blocks.map(block => block.number)) {
26
+ if (!(blockNumber in data.l1ToL2Messages)) {
27
+ throw new Error(`Missing L1 to L2 messages for block number ${blockNumber}`);
28
+ }
29
+ }
30
+ }
31
+
32
+ export function serializeEpochProvingJobData(data: EpochProvingJobData): Buffer {
33
+ const blocks = data.blocks.map(block => block.toBuffer());
34
+ const txs = Array.from(data.txs.values()).map(tx => tx.toBuffer());
35
+ const l1ToL2Messages = Object.entries(data.l1ToL2Messages).map(([blockNumber, messages]) => [
36
+ Number(blockNumber),
37
+ messages.length,
38
+ ...messages,
39
+ ]);
40
+ const attestations = data.attestations.map(attestation => attestation.toBuffer());
41
+
42
+ return serializeToBuffer(
43
+ Number(data.epochNumber),
44
+ data.previousBlockHeader,
45
+ blocks.length,
46
+ ...blocks,
47
+ txs.length,
48
+ ...txs,
49
+ l1ToL2Messages.length,
50
+ ...l1ToL2Messages,
51
+ attestations.length,
52
+ ...attestations,
53
+ );
54
+ }
55
+
56
+ export function deserializeEpochProvingJobData(buf: Buffer): EpochProvingJobData {
57
+ const reader = BufferReader.asReader(buf);
58
+ const epochNumber = BigInt(reader.readNumber());
59
+ const previousBlockHeader = reader.readObject(BlockHeader);
60
+ const blocks = reader.readVector(L2Block);
61
+ const txArray = reader.readVector(Tx);
62
+
63
+ const l1ToL2MessageBlockCount = reader.readNumber();
64
+ const l1ToL2Messages: Record<number, Fr[]> = {};
65
+ for (let i = 0; i < l1ToL2MessageBlockCount; i++) {
66
+ const blockNumber = reader.readNumber();
67
+ const messages = reader.readVector(Fr);
68
+ l1ToL2Messages[blockNumber] = messages;
69
+ }
70
+
71
+ const attestations = reader.readVector(CommitteeAttestation);
72
+
73
+ const txs = new Map<string, Tx>(txArray.map(tx => [tx.getTxHash().toString(), tx]));
74
+
75
+ return { epochNumber, previousBlockHeader, blocks, txs, l1ToL2Messages, attestations };
76
+ }
@@ -1,6 +1,10 @@
1
+ import { BatchedBlob, Blob } from '@aztec/blob-lib';
2
+ import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
1
3
  import { asyncPool } from '@aztec/foundation/async-pool';
4
+ import { padArrayEnd } from '@aztec/foundation/collection';
5
+ import { Fr } from '@aztec/foundation/fields';
2
6
  import { createLogger } from '@aztec/foundation/log';
3
- import { promiseWithResolvers } from '@aztec/foundation/promise';
7
+ import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
4
8
  import { Timer } from '@aztec/foundation/timer';
5
9
  import type { PublicProcessor, PublicProcessorFactory } from '@aztec/simulator/server';
6
10
  import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
@@ -10,17 +14,24 @@ import {
10
14
  EpochProvingJobTerminalState,
11
15
  type ForkMerkleTreeOperations,
12
16
  } from '@aztec/stdlib/interfaces/server';
13
- import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
17
+ import { MerkleTreeId } from '@aztec/stdlib/trees';
14
18
  import type { ProcessedTx, Tx } from '@aztec/stdlib/tx';
15
19
  import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
16
20
 
17
21
  import * as crypto from 'node:crypto';
18
22
 
19
- import type { ProverNodeMetrics } from '../metrics.js';
23
+ import type { ProverNodeJobMetrics } from '../metrics.js';
20
24
  import type { ProverNodePublisher } from '../prover-node-publisher.js';
25
+ import { type EpochProvingJobData, validateEpochProvingJobData } from './epoch-proving-job-data.js';
26
+
27
+ export type EpochProvingJobOptions = {
28
+ parallelBlockLimit?: number;
29
+ skipEpochCheck?: boolean;
30
+ skipSubmitProof?: boolean;
31
+ };
21
32
 
22
33
  /**
23
- * Job that grabs a range of blocks from the unfinalised chain from L1, gets their txs given their hashes,
34
+ * Job that grabs a range of blocks from the unfinalized chain from L1, gets their txs given their hashes,
24
35
  * re-executes their public calls, generates a rollup proof, and submits it to L1. This job will update the
25
36
  * world state as part of public call execution via the public processor.
26
37
  */
@@ -30,27 +41,25 @@ export class EpochProvingJob implements Traceable {
30
41
  private uuid: string;
31
42
 
32
43
  private runPromise: Promise<void> | undefined;
44
+ private epochCheckPromise: RunningPromise | undefined;
33
45
  private deadlineTimeoutHandler: NodeJS.Timeout | undefined;
34
46
 
35
47
  public readonly tracer: Tracer;
36
48
 
37
49
  constructor(
38
- private dbProvider: ForkMerkleTreeOperations,
39
- private epochNumber: bigint,
40
- private blocks: L2Block[],
41
- private txs: Tx[],
50
+ private data: EpochProvingJobData,
51
+ private dbProvider: Pick<ForkMerkleTreeOperations, 'fork'>,
42
52
  private prover: EpochProver,
43
53
  private publicProcessorFactory: PublicProcessorFactory,
44
- private publisher: ProverNodePublisher,
45
- private l2BlockSource: L2BlockSource,
46
- private l1ToL2MessageSource: L1ToL2MessageSource,
47
- private metrics: ProverNodeMetrics,
54
+ private publisher: Pick<ProverNodePublisher, 'submitEpochProof'>,
55
+ private l2BlockSource: L2BlockSource | undefined,
56
+ private metrics: ProverNodeJobMetrics,
48
57
  private deadline: Date | undefined,
49
- private config: { parallelBlockLimit: number } = { parallelBlockLimit: 32 },
50
- private cleanUp: (job: EpochProvingJob) => Promise<void> = () => Promise.resolve(),
58
+ private config: EpochProvingJobOptions,
51
59
  ) {
60
+ validateEpochProvingJobData(data);
52
61
  this.uuid = crypto.randomUUID();
53
- this.tracer = metrics.client.getTracer('EpochProvingJob');
62
+ this.tracer = metrics.tracer;
54
63
  }
55
64
 
56
65
  public getId(): string {
@@ -62,18 +71,46 @@ export class EpochProvingJob implements Traceable {
62
71
  }
63
72
 
64
73
  public getEpochNumber(): bigint {
65
- return this.epochNumber;
74
+ return this.data.epochNumber;
75
+ }
76
+
77
+ public getDeadline(): Date | undefined {
78
+ return this.deadline;
79
+ }
80
+
81
+ public getProvingData(): EpochProvingJobData {
82
+ return this.data;
83
+ }
84
+
85
+ private get epochNumber() {
86
+ return this.data.epochNumber;
87
+ }
88
+
89
+ private get blocks() {
90
+ return this.data.blocks;
91
+ }
92
+
93
+ private get txs() {
94
+ return this.data.txs;
95
+ }
96
+
97
+ private get attestations() {
98
+ return this.data.attestations;
66
99
  }
67
100
 
68
101
  /**
69
102
  * Proves the given epoch and submits the proof to L1.
70
103
  */
71
104
  @trackSpan('EpochProvingJob.run', function () {
72
- return { [Attributes.EPOCH_NUMBER]: Number(this.epochNumber) };
105
+ return { [Attributes.EPOCH_NUMBER]: Number(this.data.epochNumber) };
73
106
  })
74
107
  public async run() {
75
108
  this.scheduleDeadlineStop();
109
+ if (!this.config.skipEpochCheck) {
110
+ await this.scheduleEpochCheck();
111
+ }
76
112
 
113
+ const attestations = this.attestations.map(attestation => attestation.toViem());
77
114
  const epochNumber = Number(this.epochNumber);
78
115
  const epochSizeBlocks = this.blocks.length;
79
116
  const epochSizeTxs = this.blocks.reduce((total, current) => total + current.body.txEffects.length, 0);
@@ -92,16 +129,21 @@ export class EpochProvingJob implements Traceable {
92
129
  this.runPromise = promise;
93
130
 
94
131
  try {
95
- this.prover.startNewEpoch(epochNumber, fromBlock, epochSizeBlocks);
96
- await this.prover.startTubeCircuits(this.txs);
132
+ const allBlobs = (
133
+ await Promise.all(this.blocks.map(async block => await Blob.getBlobsPerBlock(block.body.toBlobFields())))
134
+ ).flat();
135
+
136
+ const finalBlobBatchingChallenges = await BatchedBlob.precomputeBatchedBlobChallenges(allBlobs);
137
+ this.prover.startNewEpoch(epochNumber, fromBlock, epochSizeBlocks, finalBlobBatchingChallenges);
138
+ await this.prover.startTubeCircuits(Array.from(this.txs.values()));
97
139
 
98
- await asyncPool(this.config.parallelBlockLimit, this.blocks, async block => {
140
+ await asyncPool(this.config.parallelBlockLimit ?? 32, this.blocks, async block => {
99
141
  this.checkState();
100
142
 
101
143
  const globalVariables = block.header.globalVariables;
102
- const txs = await this.getTxs(block);
103
- const l1ToL2Messages = await this.getL1ToL2Messages(block);
104
- const previousHeader = (await this.getBlockHeader(block.number - 1))!;
144
+ const txs = this.getTxs(block);
145
+ const l1ToL2Messages = this.getL1ToL2Messages(block);
146
+ const previousHeader = this.getBlockHeader(block.number - 1)!;
105
147
 
106
148
  this.log.verbose(`Starting processing block ${block.number}`, {
107
149
  number: block.number,
@@ -119,7 +161,7 @@ export class EpochProvingJob implements Traceable {
119
161
  await this.prover.startNewBlock(globalVariables, l1ToL2Messages, previousHeader);
120
162
 
121
163
  // Process public fns
122
- const db = await this.dbProvider.fork(block.number - 1);
164
+ const db = await this.createFork(block.number - 1, l1ToL2Messages);
123
165
  const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, true);
124
166
  const processed = await this.processTxs(publicProcessor, txs);
125
167
  await this.prover.addTxs(processed);
@@ -137,11 +179,29 @@ export class EpochProvingJob implements Traceable {
137
179
  const executionTime = timer.ms();
138
180
 
139
181
  this.progressState('awaiting-prover');
140
- const { publicInputs, proof } = await this.prover.finaliseEpoch();
141
- this.log.info(`Finalised proof for epoch ${epochNumber}`, { epochNumber, uuid: this.uuid, duration: timer.ms() });
182
+ const { publicInputs, proof, batchedBlobInputs } = await this.prover.finalizeEpoch();
183
+ this.log.info(`Finalized proof for epoch ${epochNumber}`, { epochNumber, uuid: this.uuid, duration: timer.ms() });
142
184
 
143
185
  this.progressState('publishing-proof');
144
- const success = await this.publisher.submitEpochProof({ fromBlock, toBlock, epochNumber, publicInputs, proof });
186
+
187
+ if (this.config.skipSubmitProof) {
188
+ this.log.info(
189
+ `Proof publishing is disabled. Dropping valid proof for epoch ${epochNumber} (blocks ${fromBlock} to ${toBlock})`,
190
+ );
191
+ this.state = 'completed';
192
+ this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeBlocks, epochSizeTxs);
193
+ return;
194
+ }
195
+
196
+ const success = await this.publisher.submitEpochProof({
197
+ fromBlock,
198
+ toBlock,
199
+ epochNumber,
200
+ publicInputs,
201
+ proof,
202
+ batchedBlobInputs,
203
+ attestations,
204
+ });
145
205
  if (!success) {
146
206
  throw new Error('Failed to submit epoch proof to L1');
147
207
  }
@@ -154,31 +214,57 @@ export class EpochProvingJob implements Traceable {
154
214
  this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeBlocks, epochSizeTxs);
155
215
  } catch (err: any) {
156
216
  if (err && err.name === 'HaltExecutionError') {
157
- this.log.warn(`Halted execution of epoch ${epochNumber} prover job`, { uuid: this.uuid, epochNumber });
217
+ this.log.warn(`Halted execution of epoch ${epochNumber} prover job`, {
218
+ uuid: this.uuid,
219
+ epochNumber,
220
+ details: err.message,
221
+ });
158
222
  return;
159
223
  }
160
224
  this.log.error(`Error running epoch ${epochNumber} prover job`, err, { uuid: this.uuid, epochNumber });
161
- this.state = 'failed';
225
+ if (this.state === 'processing' || this.state === 'awaiting-prover' || this.state === 'publishing-proof') {
226
+ this.state = 'failed';
227
+ }
162
228
  } finally {
163
229
  clearTimeout(this.deadlineTimeoutHandler);
164
- await this.cleanUp(this);
230
+ await this.epochCheckPromise?.stop();
165
231
  await this.prover.stop();
166
232
  resolve();
167
233
  }
168
234
  }
169
235
 
236
+ /**
237
+ * Create a new db fork for tx processing, inserting all L1 to L2.
238
+ * REFACTOR: The prover already spawns a db fork of its own for each block, so we may be able to do away with just one fork.
239
+ */
240
+ private async createFork(blockNumber: number, l1ToL2Messages: Fr[]) {
241
+ const db = await this.dbProvider.fork(blockNumber);
242
+ const l1ToL2MessagesPadded = padArrayEnd(
243
+ l1ToL2Messages,
244
+ Fr.ZERO,
245
+ NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
246
+ 'Too many L1 to L2 messages',
247
+ );
248
+ this.log.verbose(`Creating fork at ${blockNumber} with ${l1ToL2Messages.length} L1 to L2 messages`, {
249
+ blockNumber,
250
+ l1ToL2Messages: l1ToL2MessagesPadded.map(m => m.toString()),
251
+ });
252
+ await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
253
+ return db;
254
+ }
255
+
170
256
  private progressState(state: EpochProvingJobState) {
171
257
  this.checkState();
172
258
  this.state = state;
173
259
  }
174
260
 
175
261
  private checkState() {
176
- if (this.state === 'timed-out' || this.state === 'stopped' || this.state === 'failed') {
262
+ if (this.state === 'timed-out' || this.state === 'stopped' || this.state === 'failed' || this.state === 'reorg') {
177
263
  throw new HaltExecutionError(this.state);
178
264
  }
179
265
  }
180
266
 
181
- public async stop(state: EpochProvingJobState = 'stopped') {
267
+ public async stop(state: EpochProvingJobTerminalState = 'stopped') {
182
268
  this.state = state;
183
269
  this.prover.cancel();
184
270
  // TODO(palla/prover): Stop the publisher as well
@@ -207,24 +293,66 @@ export class EpochProvingJob implements Traceable {
207
293
  }
208
294
  }
209
295
 
210
- /* Returns the header for the given block number, or the genesis block for block zero. */
211
- private async getBlockHeader(blockNumber: number) {
212
- if (blockNumber === 0) {
213
- return (await this.dbProvider.fork()).getInitialHeader();
296
+ /**
297
+ * Kicks off a running promise that queries the archiver for the set of L2 blocks of the current epoch.
298
+ * If those change, stops the proving job with a `rerun` state, so the node re-enqueues it.
299
+ */
300
+ private async scheduleEpochCheck() {
301
+ const l2BlockSource = this.l2BlockSource;
302
+ if (!l2BlockSource) {
303
+ this.log.warn(`No L2 block source available, skipping epoch check`);
304
+ return;
214
305
  }
215
- return this.l2BlockSource.getBlockHeader(blockNumber);
306
+
307
+ const intervalMs = Math.ceil((await l2BlockSource.getL1Constants()).ethereumSlotDuration / 2) * 1000;
308
+ this.epochCheckPromise = new RunningPromise(
309
+ async () => {
310
+ const blocks = await l2BlockSource.getBlockHeadersForEpoch(this.epochNumber);
311
+ const blockHashes = await Promise.all(blocks.map(block => block.hash()));
312
+ const thisBlockHashes = await Promise.all(this.blocks.map(block => block.hash()));
313
+ if (
314
+ blocks.length !== this.blocks.length ||
315
+ !blockHashes.every((block, i) => block.equals(thisBlockHashes[i]))
316
+ ) {
317
+ this.log.warn('Epoch blocks changed underfoot', {
318
+ uuid: this.uuid,
319
+ epochNumber: this.epochNumber,
320
+ oldBlockHashes: thisBlockHashes,
321
+ newBlockHashes: blockHashes,
322
+ });
323
+ void this.stop('reorg');
324
+ }
325
+ },
326
+ this.log,
327
+ intervalMs,
328
+ ).start();
329
+ this.log.verbose(`Scheduled epoch check for epoch ${this.epochNumber} every ${intervalMs}ms`);
330
+ }
331
+
332
+ /* Returns the header for the given block number based on the epoch proving job data. */
333
+ private getBlockHeader(blockNumber: number) {
334
+ const block = this.blocks.find(b => b.number === blockNumber);
335
+ if (block) {
336
+ return block.header;
337
+ }
338
+
339
+ if (blockNumber === Number(this.data.previousBlockHeader.getBlockNumber())) {
340
+ return this.data.previousBlockHeader;
341
+ }
342
+
343
+ throw new Error(
344
+ `Block header not found for block number ${blockNumber} (got ${this.blocks
345
+ .map(b => b.number)
346
+ .join(', ')} and previous header ${this.data.previousBlockHeader.getBlockNumber()})`,
347
+ );
216
348
  }
217
349
 
218
- private async getTxs(block: L2Block): Promise<Tx[]> {
219
- const txHashes = block.body.txEffects.map(tx => tx.txHash.toBigInt());
220
- const txsAndHashes = await Promise.all(this.txs.map(async tx => ({ tx, hash: await tx.getTxHash() })));
221
- return txsAndHashes
222
- .filter(txAndHash => txHashes.includes(txAndHash.hash.toBigInt()))
223
- .map(txAndHash => txAndHash.tx);
350
+ private getTxs(block: L2Block): Tx[] {
351
+ return block.body.txEffects.map(txEffect => this.txs.get(txEffect.txHash.toString())!);
224
352
  }
225
353
 
226
354
  private getL1ToL2Messages(block: L2Block) {
227
- return this.l1ToL2MessageSource.getL1ToL2Messages(BigInt(block.number));
355
+ return this.data.l1ToL2Messages[block.number];
228
356
  }
229
357
 
230
358
  private async processTxs(publicProcessor: PublicProcessor, txs: Tx[]): Promise<ProcessedTx[]> {
@@ -232,8 +360,11 @@ export class EpochProvingJob implements Traceable {
232
360
  const [processedTxs, failedTxs] = await publicProcessor.process(txs, { deadline });
233
361
 
234
362
  if (failedTxs.length) {
363
+ const failedTxHashes = await Promise.all(failedTxs.map(({ tx }) => tx.getTxHash()));
235
364
  throw new Error(
236
- `Txs failed processing: ${failedTxs.map(({ tx, error }) => `${tx.getTxHash()} (${error})`).join(', ')}`,
365
+ `Txs failed processing: ${failedTxs
366
+ .map(({ error }, index) => `${failedTxHashes[index]} (${error})`)
367
+ .join(', ')}`,
237
368
  );
238
369
  }
239
370
 
@@ -246,7 +377,7 @@ export class EpochProvingJob implements Traceable {
246
377
  }
247
378
 
248
379
  class HaltExecutionError extends Error {
249
- constructor(state: EpochProvingJobState) {
380
+ constructor(public readonly state: EpochProvingJobState) {
250
381
  super(`Halted execution due to state ${state}`);
251
382
  this.name = 'HaltExecutionError';
252
383
  }