@aztec/prover-node 4.0.0-nightly.20250907 → 4.0.0-nightly.20260108
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.
- package/dest/actions/download-epoch-proving-job.d.ts +4 -4
- package/dest/actions/index.d.ts +1 -1
- package/dest/actions/rerun-epoch-proving-job.d.ts +2 -2
- package/dest/actions/upload-epoch-proof-failure.d.ts +1 -1
- package/dest/bin/run-failed-epoch.d.ts +1 -1
- package/dest/bin/run-failed-epoch.js +1 -1
- package/dest/config.d.ts +7 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +21 -15
- package/dest/factory.d.ts +2 -4
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +31 -13
- package/dest/index.d.ts +1 -1
- package/dest/job/epoch-proving-job-data.d.ts +8 -6
- package/dest/job/epoch-proving-job-data.d.ts.map +1 -1
- package/dest/job/epoch-proving-job-data.js +25 -18
- package/dest/job/epoch-proving-job.d.ts +11 -16
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +493 -77
- package/dest/metrics.d.ts +4 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +9 -3
- package/dest/monitors/epoch-monitor.d.ts +5 -2
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +11 -11
- package/dest/monitors/index.d.ts +1 -1
- package/dest/prover-node-publisher.d.ts +9 -10
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +51 -53
- package/dest/prover-node.d.ts +8 -7
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +435 -50
- package/dest/prover-publisher-factory.d.ts +6 -2
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +6 -0
- package/dest/test/index.d.ts +1 -1
- package/dest/test/index.d.ts.map +1 -1
- package/package.json +26 -25
- package/src/bin/run-failed-epoch.ts +2 -2
- package/src/config.ts +33 -30
- package/src/factory.ts +37 -20
- package/src/job/epoch-proving-job-data.ts +31 -25
- package/src/job/epoch-proving-job.ts +138 -82
- package/src/metrics.ts +16 -4
- package/src/monitors/epoch-monitor.ts +16 -13
- package/src/prover-node-publisher.ts +74 -73
- package/src/prover-node.ts +52 -45
- package/src/prover-publisher-factory.ts +12 -1
|
@@ -1,19 +1,25 @@
|
|
|
1
|
-
import { BatchedBlob, Blob } from '@aztec/blob-lib';
|
|
2
1
|
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
3
2
|
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
3
|
+
import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
4
4
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
5
|
-
import { Fr } from '@aztec/foundation/
|
|
5
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
6
6
|
import { createLogger } from '@aztec/foundation/log';
|
|
7
7
|
import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
8
8
|
import { Timer } from '@aztec/foundation/timer';
|
|
9
|
+
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
10
|
+
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
11
|
+
import { buildFinalBlobChallenges } from '@aztec/prover-client/helpers';
|
|
9
12
|
import type { PublicProcessor, PublicProcessorFactory } from '@aztec/simulator/server';
|
|
10
|
-
import
|
|
13
|
+
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
14
|
+
import type { L2BlockNew, L2BlockSource } from '@aztec/stdlib/block';
|
|
15
|
+
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
11
16
|
import {
|
|
12
17
|
type EpochProver,
|
|
13
18
|
type EpochProvingJobState,
|
|
14
19
|
EpochProvingJobTerminalState,
|
|
15
20
|
type ForkMerkleTreeOperations,
|
|
16
21
|
} from '@aztec/stdlib/interfaces/server';
|
|
22
|
+
import { CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
17
23
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
18
24
|
import type { ProcessedTx, Tx } from '@aztec/stdlib/tx';
|
|
19
25
|
import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
|
|
@@ -24,6 +30,12 @@ import type { ProverNodeJobMetrics } from '../metrics.js';
|
|
|
24
30
|
import type { ProverNodePublisher } from '../prover-node-publisher.js';
|
|
25
31
|
import { type EpochProvingJobData, validateEpochProvingJobData } from './epoch-proving-job-data.js';
|
|
26
32
|
|
|
33
|
+
export type EpochProvingJobOptions = {
|
|
34
|
+
parallelBlockLimit?: number;
|
|
35
|
+
skipEpochCheck?: boolean;
|
|
36
|
+
skipSubmitProof?: boolean;
|
|
37
|
+
};
|
|
38
|
+
|
|
27
39
|
/**
|
|
28
40
|
* Job that grabs a range of blocks from the unfinalized chain from L1, gets their txs given their hashes,
|
|
29
41
|
* re-executes their public calls, generates a rollup proof, and submits it to L1. This job will update the
|
|
@@ -49,7 +61,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
49
61
|
private l2BlockSource: L2BlockSource | undefined,
|
|
50
62
|
private metrics: ProverNodeJobMetrics,
|
|
51
63
|
private deadline: Date | undefined,
|
|
52
|
-
private config:
|
|
64
|
+
private config: EpochProvingJobOptions,
|
|
53
65
|
) {
|
|
54
66
|
validateEpochProvingJobData(data);
|
|
55
67
|
this.uuid = crypto.randomUUID();
|
|
@@ -64,7 +76,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
64
76
|
return this.state;
|
|
65
77
|
}
|
|
66
78
|
|
|
67
|
-
public getEpochNumber():
|
|
79
|
+
public getEpochNumber(): EpochNumber {
|
|
68
80
|
return this.data.epochNumber;
|
|
69
81
|
}
|
|
70
82
|
|
|
@@ -80,8 +92,8 @@ export class EpochProvingJob implements Traceable {
|
|
|
80
92
|
return this.data.epochNumber;
|
|
81
93
|
}
|
|
82
94
|
|
|
83
|
-
private get
|
|
84
|
-
return this.data.
|
|
95
|
+
private get checkpoints() {
|
|
96
|
+
return this.data.checkpoints;
|
|
85
97
|
}
|
|
86
98
|
|
|
87
99
|
private get txs() {
|
|
@@ -96,7 +108,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
96
108
|
* Proves the given epoch and submits the proof to L1.
|
|
97
109
|
*/
|
|
98
110
|
@trackSpan('EpochProvingJob.run', function () {
|
|
99
|
-
return { [Attributes.EPOCH_NUMBER]:
|
|
111
|
+
return { [Attributes.EPOCH_NUMBER]: this.data.epochNumber };
|
|
100
112
|
})
|
|
101
113
|
public async run() {
|
|
102
114
|
this.scheduleDeadlineStop();
|
|
@@ -105,14 +117,22 @@ export class EpochProvingJob implements Traceable {
|
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
const attestations = this.attestations.map(attestation => attestation.toViem());
|
|
108
|
-
const epochNumber =
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
|
|
120
|
+
const epochNumber = this.epochNumber;
|
|
121
|
+
const epochSizeCheckpoints = this.checkpoints.length;
|
|
122
|
+
const epochSizeBlocks = this.checkpoints.reduce((accum, checkpoint) => accum + checkpoint.blocks.length, 0);
|
|
123
|
+
const epochSizeTxs = this.checkpoints.reduce(
|
|
124
|
+
(accum, checkpoint) =>
|
|
125
|
+
accum + checkpoint.blocks.reduce((accumC, block) => accumC + block.body.txEffects.length, 0),
|
|
126
|
+
0,
|
|
127
|
+
);
|
|
128
|
+
const fromCheckpoint = this.checkpoints[0].number;
|
|
129
|
+
const toCheckpoint = this.checkpoints.at(-1)!.number;
|
|
130
|
+
const fromBlock = this.checkpoints[0].blocks[0].number;
|
|
131
|
+
const toBlock = this.checkpoints.at(-1)!.blocks.at(-1)!.number;
|
|
132
|
+
this.log.info(`Starting epoch ${epochNumber} proving job with checkpoints ${fromCheckpoint} to ${toCheckpoint}`, {
|
|
113
133
|
fromBlock,
|
|
114
134
|
toBlock,
|
|
115
|
-
|
|
135
|
+
epochSizeTxs,
|
|
116
136
|
epochNumber,
|
|
117
137
|
uuid: this.uuid,
|
|
118
138
|
});
|
|
@@ -123,51 +143,93 @@ export class EpochProvingJob implements Traceable {
|
|
|
123
143
|
this.runPromise = promise;
|
|
124
144
|
|
|
125
145
|
try {
|
|
126
|
-
const
|
|
127
|
-
|
|
128
|
-
|
|
146
|
+
const blobFieldsPerCheckpoint = this.checkpoints.map(checkpoint => checkpoint.toBlobFields());
|
|
147
|
+
const finalBlobBatchingChallenges = await buildFinalBlobChallenges(blobFieldsPerCheckpoint);
|
|
148
|
+
|
|
149
|
+
this.prover.startNewEpoch(epochNumber, epochSizeCheckpoints, finalBlobBatchingChallenges);
|
|
150
|
+
await this.prover.startChonkVerifierCircuits(Array.from(this.txs.values()));
|
|
129
151
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
await this.prover.startTubeCircuits(Array.from(this.txs.values()));
|
|
152
|
+
// Everything in the epoch should have the same chainId and version.
|
|
153
|
+
const { chainId, version } = this.checkpoints[0].blocks[0].header.globalVariables;
|
|
133
154
|
|
|
134
|
-
|
|
155
|
+
const previousBlockHeaders = this.gatherPreviousBlockHeaders();
|
|
156
|
+
|
|
157
|
+
await asyncPool(this.config.parallelBlockLimit ?? 32, this.checkpoints, async checkpoint => {
|
|
135
158
|
this.checkState();
|
|
136
159
|
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
publicDataTreeRoot: block.header.state.partial.publicDataTree.root,
|
|
149
|
-
previousHeader: previousHeader.hash(),
|
|
150
|
-
uuid: this.uuid,
|
|
151
|
-
...globalVariables,
|
|
160
|
+
const checkpointIndex = checkpoint.number - fromCheckpoint;
|
|
161
|
+
const checkpointConstants = CheckpointConstantData.from({
|
|
162
|
+
chainId,
|
|
163
|
+
version,
|
|
164
|
+
vkTreeRoot: getVKTreeRoot(),
|
|
165
|
+
protocolContractsHash: protocolContractsHash,
|
|
166
|
+
proverId: this.prover.getProverId().toField(),
|
|
167
|
+
slotNumber: checkpoint.header.slotNumber,
|
|
168
|
+
coinbase: checkpoint.header.coinbase,
|
|
169
|
+
feeRecipient: checkpoint.header.feeRecipient,
|
|
170
|
+
gasFees: checkpoint.header.gasFees,
|
|
152
171
|
});
|
|
172
|
+
const previousHeader = previousBlockHeaders[checkpointIndex];
|
|
173
|
+
const l1ToL2Messages = this.getL1ToL2Messages(checkpoint);
|
|
153
174
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, true);
|
|
160
|
-
const processed = await this.processTxs(publicProcessor, txs);
|
|
161
|
-
await this.prover.addTxs(processed);
|
|
162
|
-
await db.close();
|
|
163
|
-
this.log.verbose(`Processed all ${txs.length} txs for block ${block.number}`, {
|
|
164
|
-
blockNumber: block.number,
|
|
165
|
-
blockHash: (await block.hash()).toString(),
|
|
175
|
+
this.log.verbose(`Starting processing checkpoint ${checkpoint.number}`, {
|
|
176
|
+
number: checkpoint.number,
|
|
177
|
+
checkpointHash: checkpoint.hash().toString(),
|
|
178
|
+
lastArchive: checkpoint.header.lastArchiveRoot,
|
|
179
|
+
previousHeader: previousHeader.hash(),
|
|
166
180
|
uuid: this.uuid,
|
|
167
181
|
});
|
|
168
182
|
|
|
169
|
-
|
|
170
|
-
|
|
183
|
+
await this.prover.startNewCheckpoint(
|
|
184
|
+
checkpointIndex,
|
|
185
|
+
checkpointConstants,
|
|
186
|
+
l1ToL2Messages,
|
|
187
|
+
checkpoint.blocks.length,
|
|
188
|
+
previousHeader,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
for (const block of checkpoint.blocks) {
|
|
192
|
+
const globalVariables = block.header.globalVariables;
|
|
193
|
+
const txs = this.getTxs(block);
|
|
194
|
+
|
|
195
|
+
this.log.verbose(`Starting processing block ${block.number}`, {
|
|
196
|
+
number: block.number,
|
|
197
|
+
blockHash: (await block.hash()).toString(),
|
|
198
|
+
lastArchive: block.header.lastArchive.root,
|
|
199
|
+
noteHashTreeRoot: block.header.state.partial.noteHashTree.root,
|
|
200
|
+
nullifierTreeRoot: block.header.state.partial.nullifierTree.root,
|
|
201
|
+
publicDataTreeRoot: block.header.state.partial.publicDataTree.root,
|
|
202
|
+
...globalVariables,
|
|
203
|
+
numTxs: txs.length,
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Start block proving
|
|
207
|
+
await this.prover.startNewBlock(block.number, globalVariables.timestamp, txs.length);
|
|
208
|
+
|
|
209
|
+
// Process public fns
|
|
210
|
+
const db = await this.createFork(BlockNumber(block.number - 1), l1ToL2Messages);
|
|
211
|
+
const config = PublicSimulatorConfig.from({
|
|
212
|
+
proverId: this.prover.getProverId().toField(),
|
|
213
|
+
skipFeeEnforcement: false,
|
|
214
|
+
collectDebugLogs: false,
|
|
215
|
+
collectHints: true,
|
|
216
|
+
collectPublicInputs: true,
|
|
217
|
+
collectStatistics: false,
|
|
218
|
+
});
|
|
219
|
+
const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, config);
|
|
220
|
+
const processed = await this.processTxs(publicProcessor, txs);
|
|
221
|
+
await this.prover.addTxs(processed);
|
|
222
|
+
await db.close();
|
|
223
|
+
this.log.verbose(`Processed all ${txs.length} txs for block ${block.number}`, {
|
|
224
|
+
blockNumber: block.number,
|
|
225
|
+
blockHash: (await block.hash()).toString(),
|
|
226
|
+
uuid: this.uuid,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Mark block as completed to pad it
|
|
230
|
+
const expectedBlockHeader = block.header;
|
|
231
|
+
await this.prover.setBlockCompleted(block.number, expectedBlockHeader);
|
|
232
|
+
}
|
|
171
233
|
});
|
|
172
234
|
|
|
173
235
|
const executionTime = timer.ms();
|
|
@@ -178,9 +240,18 @@ export class EpochProvingJob implements Traceable {
|
|
|
178
240
|
|
|
179
241
|
this.progressState('publishing-proof');
|
|
180
242
|
|
|
243
|
+
if (this.config.skipSubmitProof) {
|
|
244
|
+
this.log.info(
|
|
245
|
+
`Proof publishing is disabled. Dropping valid proof for epoch ${epochNumber} (checkpoints ${fromCheckpoint} to ${toCheckpoint})`,
|
|
246
|
+
);
|
|
247
|
+
this.state = 'completed';
|
|
248
|
+
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeCheckpoints, epochSizeBlocks, epochSizeTxs);
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
|
|
181
252
|
const success = await this.publisher.submitEpochProof({
|
|
182
|
-
|
|
183
|
-
|
|
253
|
+
fromCheckpoint,
|
|
254
|
+
toCheckpoint,
|
|
184
255
|
epochNumber,
|
|
185
256
|
publicInputs,
|
|
186
257
|
proof,
|
|
@@ -191,12 +262,12 @@ export class EpochProvingJob implements Traceable {
|
|
|
191
262
|
throw new Error('Failed to submit epoch proof to L1');
|
|
192
263
|
}
|
|
193
264
|
|
|
194
|
-
this.log.info(`Submitted proof for epoch ${epochNumber} (
|
|
265
|
+
this.log.info(`Submitted proof for epoch ${epochNumber} (checkpoints ${fromCheckpoint} to ${toCheckpoint})`, {
|
|
195
266
|
epochNumber,
|
|
196
267
|
uuid: this.uuid,
|
|
197
268
|
});
|
|
198
269
|
this.state = 'completed';
|
|
199
|
-
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeBlocks, epochSizeTxs);
|
|
270
|
+
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeCheckpoints, epochSizeBlocks, epochSizeTxs);
|
|
200
271
|
} catch (err: any) {
|
|
201
272
|
if (err && err.name === 'HaltExecutionError') {
|
|
202
273
|
this.log.warn(`Halted execution of epoch ${epochNumber} prover job`, {
|
|
@@ -222,9 +293,9 @@ export class EpochProvingJob implements Traceable {
|
|
|
222
293
|
* Create a new db fork for tx processing, inserting all L1 to L2.
|
|
223
294
|
* 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.
|
|
224
295
|
*/
|
|
225
|
-
private async createFork(blockNumber:
|
|
296
|
+
private async createFork(blockNumber: BlockNumber, l1ToL2Messages: Fr[]) {
|
|
226
297
|
const db = await this.dbProvider.fork(blockNumber);
|
|
227
|
-
const l1ToL2MessagesPadded = padArrayEnd(
|
|
298
|
+
const l1ToL2MessagesPadded = padArrayEnd<Fr, number>(
|
|
228
299
|
l1ToL2Messages,
|
|
229
300
|
Fr.ZERO,
|
|
230
301
|
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
@@ -232,7 +303,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
232
303
|
);
|
|
233
304
|
this.log.verbose(`Creating fork at ${blockNumber} with ${l1ToL2Messages.length} L1 to L2 messages`, {
|
|
234
305
|
blockNumber,
|
|
235
|
-
l1ToL2Messages:
|
|
306
|
+
l1ToL2Messages: l1ToL2Messages.map(m => m.toString()),
|
|
236
307
|
});
|
|
237
308
|
await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
238
309
|
return db;
|
|
@@ -252,7 +323,6 @@ export class EpochProvingJob implements Traceable {
|
|
|
252
323
|
public async stop(state: EpochProvingJobTerminalState = 'stopped') {
|
|
253
324
|
this.state = state;
|
|
254
325
|
this.prover.cancel();
|
|
255
|
-
// TODO(palla/prover): Stop the publisher as well
|
|
256
326
|
if (this.runPromise) {
|
|
257
327
|
await this.runPromise;
|
|
258
328
|
}
|
|
@@ -294,11 +364,9 @@ export class EpochProvingJob implements Traceable {
|
|
|
294
364
|
async () => {
|
|
295
365
|
const blocks = await l2BlockSource.getBlockHeadersForEpoch(this.epochNumber);
|
|
296
366
|
const blockHashes = await Promise.all(blocks.map(block => block.hash()));
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
!blockHashes.every((block, i) => block.equals(thisBlockHashes[i]))
|
|
301
|
-
) {
|
|
367
|
+
const thisBlocks = this.checkpoints.flatMap(checkpoint => checkpoint.blocks);
|
|
368
|
+
const thisBlockHashes = await Promise.all(thisBlocks.map(block => block.hash()));
|
|
369
|
+
if (blocks.length !== thisBlocks.length || !blockHashes.every((block, i) => block.equals(thisBlockHashes[i]))) {
|
|
302
370
|
this.log.warn('Epoch blocks changed underfoot', {
|
|
303
371
|
uuid: this.uuid,
|
|
304
372
|
epochNumber: this.epochNumber,
|
|
@@ -314,30 +382,18 @@ export class EpochProvingJob implements Traceable {
|
|
|
314
382
|
this.log.verbose(`Scheduled epoch check for epoch ${this.epochNumber} every ${intervalMs}ms`);
|
|
315
383
|
}
|
|
316
384
|
|
|
317
|
-
/* Returns the header
|
|
318
|
-
private
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
return block.header;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
if (blockNumber === Number(this.data.previousBlockHeader.getBlockNumber())) {
|
|
325
|
-
return this.data.previousBlockHeader;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
throw new Error(
|
|
329
|
-
`Block header not found for block number ${blockNumber} (got ${this.blocks
|
|
330
|
-
.map(b => b.number)
|
|
331
|
-
.join(', ')} and previous header ${this.data.previousBlockHeader.getBlockNumber()})`,
|
|
332
|
-
);
|
|
385
|
+
/* Returns the last block header in the previous checkpoint for all checkpoints in the epoch */
|
|
386
|
+
private gatherPreviousBlockHeaders() {
|
|
387
|
+
const lastBlocks = this.checkpoints.map(checkpoint => checkpoint.blocks.at(-1)!);
|
|
388
|
+
return [this.data.previousBlockHeader, ...lastBlocks.map(block => block.header).slice(0, -1)];
|
|
333
389
|
}
|
|
334
390
|
|
|
335
|
-
private getTxs(block:
|
|
391
|
+
private getTxs(block: L2BlockNew): Tx[] {
|
|
336
392
|
return block.body.txEffects.map(txEffect => this.txs.get(txEffect.txHash.toString())!);
|
|
337
393
|
}
|
|
338
394
|
|
|
339
|
-
private getL1ToL2Messages(
|
|
340
|
-
return this.data.l1ToL2Messages[
|
|
395
|
+
private getL1ToL2Messages(checkpoint: Checkpoint) {
|
|
396
|
+
return this.data.l1ToL2Messages[checkpoint.number];
|
|
341
397
|
}
|
|
342
398
|
|
|
343
399
|
private async processTxs(publicProcessor: PublicProcessor, txs: Tx[]): Promise<ProcessedTx[]> {
|
package/src/metrics.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { RollupContract } from '@aztec/ethereum';
|
|
1
|
+
import type { RollupContract } from '@aztec/ethereum/contracts';
|
|
2
2
|
import type { EthAddress } from '@aztec/foundation/eth-address';
|
|
3
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
4
4
|
import type { L1PublishProofStats, L1PublishStats } from '@aztec/stdlib/stats';
|
|
@@ -21,6 +21,7 @@ import { formatEther, formatUnits } from 'viem';
|
|
|
21
21
|
export class ProverNodeJobMetrics {
|
|
22
22
|
proverEpochExecutionDuration: Histogram;
|
|
23
23
|
provingJobDuration: Histogram;
|
|
24
|
+
provingJobCheckpoints: Gauge;
|
|
24
25
|
provingJobBlocks: Gauge;
|
|
25
26
|
provingJobTransactions: Gauge;
|
|
26
27
|
|
|
@@ -39,6 +40,10 @@ export class ProverNodeJobMetrics {
|
|
|
39
40
|
unit: 's',
|
|
40
41
|
valueType: ValueType.DOUBLE,
|
|
41
42
|
});
|
|
43
|
+
this.provingJobCheckpoints = this.meter.createGauge(Metrics.PROVER_NODE_JOB_CHECKPOINTS, {
|
|
44
|
+
description: 'Number of checkpoints in a proven epoch',
|
|
45
|
+
valueType: ValueType.INT,
|
|
46
|
+
});
|
|
42
47
|
this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
|
|
43
48
|
description: 'Number of blocks in a proven epoch',
|
|
44
49
|
valueType: ValueType.INT,
|
|
@@ -49,9 +54,16 @@ export class ProverNodeJobMetrics {
|
|
|
49
54
|
});
|
|
50
55
|
}
|
|
51
56
|
|
|
52
|
-
public recordProvingJob(
|
|
57
|
+
public recordProvingJob(
|
|
58
|
+
executionTimeMs: number,
|
|
59
|
+
totalTimeMs: number,
|
|
60
|
+
numCheckpoints: number,
|
|
61
|
+
numBlocks: number,
|
|
62
|
+
numTxs: number,
|
|
63
|
+
) {
|
|
53
64
|
this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
|
|
54
65
|
this.provingJobDuration.record(totalTimeMs / 1000);
|
|
66
|
+
this.provingJobCheckpoints.record(Math.floor(numCheckpoints));
|
|
55
67
|
this.provingJobBlocks.record(Math.floor(numBlocks));
|
|
56
68
|
this.provingJobTransactions.record(Math.floor(numTxs));
|
|
57
69
|
}
|
|
@@ -91,13 +103,13 @@ export class ProverNodeRewardsMetrics {
|
|
|
91
103
|
}
|
|
92
104
|
|
|
93
105
|
private observe = async (observer: BatchObservableResult): Promise<void> => {
|
|
94
|
-
const epoch = await this.rollup.
|
|
106
|
+
const epoch = await this.rollup.getCurrentEpochNumber();
|
|
95
107
|
|
|
96
108
|
if (epoch > this.proofSubmissionEpochs) {
|
|
97
109
|
// look at the prev epoch so that we get an accurate value, after proof submission window has closed
|
|
98
110
|
// For example, if proof submission window is 1 epoch, and we are in epoch 2, we should be looking at epoch 0.
|
|
99
111
|
// Similarly, if the proof submission window is 0, and we are in epoch 1, we should be looking at epoch 0.
|
|
100
|
-
const closedEpoch = epoch - BigInt(this.proofSubmissionEpochs) - 1n;
|
|
112
|
+
const closedEpoch = BigInt(epoch) - BigInt(this.proofSubmissionEpochs) - 1n;
|
|
101
113
|
const rewards = await this.rollup.getSpecificProverRewardsForEpoch(closedEpoch, this.coinbase);
|
|
102
114
|
|
|
103
115
|
const fmt = parseFloat(formatUnits(rewards, 18));
|
|
@@ -1,17 +1,13 @@
|
|
|
1
|
+
import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
1
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
2
3
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
4
|
+
import { sleep } from '@aztec/foundation/sleep';
|
|
3
5
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
4
6
|
import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
5
|
-
import {
|
|
6
|
-
type TelemetryClient,
|
|
7
|
-
type Traceable,
|
|
8
|
-
type Tracer,
|
|
9
|
-
getTelemetryClient,
|
|
10
|
-
trackSpan,
|
|
11
|
-
} from '@aztec/telemetry-client';
|
|
7
|
+
import { type TelemetryClient, type Traceable, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
12
8
|
|
|
13
9
|
export interface EpochMonitorHandler {
|
|
14
|
-
handleEpochReadyToProve(epochNumber:
|
|
10
|
+
handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean>;
|
|
15
11
|
}
|
|
16
12
|
|
|
17
13
|
/**
|
|
@@ -31,21 +27,24 @@ export class EpochMonitor implements Traceable {
|
|
|
31
27
|
public readonly tracer: Tracer;
|
|
32
28
|
|
|
33
29
|
private handler: EpochMonitorHandler | undefined;
|
|
34
|
-
private latestEpochNumber:
|
|
30
|
+
private latestEpochNumber: EpochNumber | undefined;
|
|
35
31
|
|
|
36
32
|
constructor(
|
|
37
33
|
private readonly l2BlockSource: L2BlockSource,
|
|
38
34
|
private readonly l1Constants: Pick<L1RollupConstants, 'epochDuration'>,
|
|
39
|
-
private options: { pollingIntervalMs: number },
|
|
35
|
+
private options: { pollingIntervalMs: number; provingDelayMs?: number },
|
|
40
36
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
41
37
|
) {
|
|
42
38
|
this.tracer = telemetry.getTracer('EpochMonitor');
|
|
43
39
|
this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.options.pollingIntervalMs);
|
|
40
|
+
if (this.options.provingDelayMs) {
|
|
41
|
+
this.log.warn(`Prover node epoch monitor running with delay of ${this.options.provingDelayMs}ms`);
|
|
42
|
+
}
|
|
44
43
|
}
|
|
45
44
|
|
|
46
45
|
public static async create(
|
|
47
46
|
l2BlockSource: L2BlockSource,
|
|
48
|
-
options: { pollingIntervalMs: number },
|
|
47
|
+
options: { pollingIntervalMs: number; provingDelayMs?: number },
|
|
49
48
|
telemetry: TelemetryClient = getTelemetryClient(),
|
|
50
49
|
): Promise<EpochMonitor> {
|
|
51
50
|
const l1Constants = await l2BlockSource.getL1Constants();
|
|
@@ -68,7 +67,6 @@ export class EpochMonitor implements Traceable {
|
|
|
68
67
|
this.log.info('Stopped EpochMonitor');
|
|
69
68
|
}
|
|
70
69
|
|
|
71
|
-
@trackSpan('EpochMonitor.work')
|
|
72
70
|
public async work() {
|
|
73
71
|
const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
|
|
74
72
|
this.log.debug(`Epoch to prove: ${epochToProve}`, { blockNumber, slotNumber });
|
|
@@ -87,6 +85,11 @@ export class EpochMonitor implements Traceable {
|
|
|
87
85
|
return;
|
|
88
86
|
}
|
|
89
87
|
|
|
88
|
+
if (this.options.provingDelayMs) {
|
|
89
|
+
this.log.debug(`Waiting ${this.options.provingDelayMs}ms before proving epoch ${epochToProve}`);
|
|
90
|
+
await sleep(this.options.provingDelayMs);
|
|
91
|
+
}
|
|
92
|
+
|
|
90
93
|
this.log.debug(`Epoch ${epochToProve} is ready to be proven`);
|
|
91
94
|
if (await this.handler?.handleEpochReadyToProve(epochToProve)) {
|
|
92
95
|
this.latestEpochNumber = epochToProve;
|
|
@@ -95,7 +98,7 @@ export class EpochMonitor implements Traceable {
|
|
|
95
98
|
|
|
96
99
|
private async getEpochNumberToProve() {
|
|
97
100
|
const lastBlockProven = await this.l2BlockSource.getProvenBlockNumber();
|
|
98
|
-
const firstBlockToProve = lastBlockProven + 1;
|
|
101
|
+
const firstBlockToProve = BlockNumber(lastBlockProven + 1);
|
|
99
102
|
const firstBlockHeaderToProve = await this.l2BlockSource.getBlockHeader(firstBlockToProve);
|
|
100
103
|
if (!firstBlockHeaderToProve) {
|
|
101
104
|
return { epochToProve: undefined, blockNumber: firstBlockToProve };
|