@aztec/prover-node 0.0.1-commit.b655e406 → 0.0.1-commit.c0b82b2
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 +3 -2
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
- package/dest/actions/rerun-epoch-proving-job.js +5 -3
- 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 +5 -2
- package/dest/config.d.ts +7 -9
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +17 -19
- package/dest/factory.d.ts +20 -15
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +28 -61
- package/dest/index.d.ts +2 -1
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +1 -0
- 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 +7 -13
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +503 -105
- package/dest/metrics.d.ts +4 -3
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +30 -98
- package/dest/monitors/epoch-monitor.d.ts +3 -2
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +3 -11
- package/dest/monitors/index.d.ts +1 -1
- package/dest/prover-node-publisher.d.ts +14 -11
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +49 -42
- package/dest/prover-node.d.ts +26 -15
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +441 -57
- package/dest/prover-publisher-factory.d.ts +9 -5
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +4 -2
- package/dest/test/index.d.ts +1 -1
- package/dest/test/index.d.ts.map +1 -1
- package/package.json +26 -25
- package/src/actions/rerun-epoch-proving-job.ts +5 -3
- package/src/bin/run-failed-epoch.ts +5 -2
- package/src/config.ts +25 -31
- package/src/factory.ts +65 -99
- package/src/index.ts +1 -0
- package/src/job/epoch-proving-job-data.ts +31 -25
- package/src/job/epoch-proving-job.ts +139 -110
- package/src/metrics.ts +31 -82
- package/src/monitors/epoch-monitor.ts +5 -11
- package/src/prover-node-publisher.ts +71 -58
- package/src/prover-node.ts +60 -50
- package/src/prover-publisher-factory.ts +16 -8
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
2
|
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
3
|
+
import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
3
4
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
4
|
-
import { Fr } from '@aztec/foundation/
|
|
5
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
5
|
+
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
6
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
6
7
|
import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
7
8
|
import { Timer } from '@aztec/foundation/timer';
|
|
8
9
|
import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
|
|
9
10
|
import { protocolContractsHash } from '@aztec/protocol-contracts';
|
|
10
11
|
import { buildFinalBlobChallenges } from '@aztec/prover-client/helpers';
|
|
11
12
|
import type { PublicProcessor, PublicProcessorFactory } from '@aztec/simulator/server';
|
|
13
|
+
import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
|
|
12
14
|
import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
|
|
15
|
+
import type { Checkpoint } from '@aztec/stdlib/checkpoint';
|
|
13
16
|
import {
|
|
14
17
|
type EpochProver,
|
|
15
18
|
type EpochProvingJobState,
|
|
@@ -40,7 +43,7 @@ export type EpochProvingJobOptions = {
|
|
|
40
43
|
*/
|
|
41
44
|
export class EpochProvingJob implements Traceable {
|
|
42
45
|
private state: EpochProvingJobState = 'initialized';
|
|
43
|
-
private log
|
|
46
|
+
private log: Logger;
|
|
44
47
|
private uuid: string;
|
|
45
48
|
|
|
46
49
|
private runPromise: Promise<void> | undefined;
|
|
@@ -59,9 +62,14 @@ export class EpochProvingJob implements Traceable {
|
|
|
59
62
|
private metrics: ProverNodeJobMetrics,
|
|
60
63
|
private deadline: Date | undefined,
|
|
61
64
|
private config: EpochProvingJobOptions,
|
|
65
|
+
bindings?: LoggerBindings,
|
|
62
66
|
) {
|
|
63
67
|
validateEpochProvingJobData(data);
|
|
64
68
|
this.uuid = crypto.randomUUID();
|
|
69
|
+
this.log = createLogger('prover-node:epoch-proving-job', {
|
|
70
|
+
...bindings,
|
|
71
|
+
instanceId: `epoch-${data.epochNumber}`,
|
|
72
|
+
});
|
|
65
73
|
this.tracer = metrics.tracer;
|
|
66
74
|
}
|
|
67
75
|
|
|
@@ -73,7 +81,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
73
81
|
return this.state;
|
|
74
82
|
}
|
|
75
83
|
|
|
76
|
-
public getEpochNumber():
|
|
84
|
+
public getEpochNumber(): EpochNumber {
|
|
77
85
|
return this.data.epochNumber;
|
|
78
86
|
}
|
|
79
87
|
|
|
@@ -89,8 +97,8 @@ export class EpochProvingJob implements Traceable {
|
|
|
89
97
|
return this.data.epochNumber;
|
|
90
98
|
}
|
|
91
99
|
|
|
92
|
-
private get
|
|
93
|
-
return this.data.
|
|
100
|
+
private get checkpoints() {
|
|
101
|
+
return this.data.checkpoints;
|
|
94
102
|
}
|
|
95
103
|
|
|
96
104
|
private get txs() {
|
|
@@ -105,7 +113,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
105
113
|
* Proves the given epoch and submits the proof to L1.
|
|
106
114
|
*/
|
|
107
115
|
@trackSpan('EpochProvingJob.run', function () {
|
|
108
|
-
return { [Attributes.EPOCH_NUMBER]:
|
|
116
|
+
return { [Attributes.EPOCH_NUMBER]: this.data.epochNumber };
|
|
109
117
|
})
|
|
110
118
|
public async run() {
|
|
111
119
|
this.scheduleDeadlineStop();
|
|
@@ -114,14 +122,22 @@ export class EpochProvingJob implements Traceable {
|
|
|
114
122
|
}
|
|
115
123
|
|
|
116
124
|
const attestations = this.attestations.map(attestation => attestation.toViem());
|
|
117
|
-
const epochNumber =
|
|
118
|
-
const
|
|
119
|
-
const
|
|
120
|
-
const
|
|
121
|
-
|
|
125
|
+
const epochNumber = this.epochNumber;
|
|
126
|
+
const epochSizeCheckpoints = this.checkpoints.length;
|
|
127
|
+
const epochSizeBlocks = this.checkpoints.reduce((accum, checkpoint) => accum + checkpoint.blocks.length, 0);
|
|
128
|
+
const epochSizeTxs = this.checkpoints.reduce(
|
|
129
|
+
(accum, checkpoint) =>
|
|
130
|
+
accum + checkpoint.blocks.reduce((accumC, block) => accumC + block.body.txEffects.length, 0),
|
|
131
|
+
0,
|
|
132
|
+
);
|
|
133
|
+
const fromCheckpoint = this.checkpoints[0].number;
|
|
134
|
+
const toCheckpoint = this.checkpoints.at(-1)!.number;
|
|
135
|
+
const fromBlock = this.checkpoints[0].blocks[0].number;
|
|
136
|
+
const toBlock = this.checkpoints.at(-1)!.blocks.at(-1)!.number;
|
|
137
|
+
this.log.info(`Starting epoch ${epochNumber} proving job with checkpoints ${fromCheckpoint} to ${toCheckpoint}`, {
|
|
122
138
|
fromBlock,
|
|
123
139
|
toBlock,
|
|
124
|
-
|
|
140
|
+
epochSizeTxs,
|
|
125
141
|
epochNumber,
|
|
126
142
|
uuid: this.uuid,
|
|
127
143
|
});
|
|
@@ -132,83 +148,100 @@ export class EpochProvingJob implements Traceable {
|
|
|
132
148
|
this.runPromise = promise;
|
|
133
149
|
|
|
134
150
|
try {
|
|
135
|
-
const blobFieldsPerCheckpoint = this.
|
|
151
|
+
const blobFieldsPerCheckpoint = this.checkpoints.map(checkpoint => checkpoint.toBlobFields());
|
|
152
|
+
this.log.info(`Blob fields per checkpoint: ${timer.ms()}ms`);
|
|
136
153
|
const finalBlobBatchingChallenges = await buildFinalBlobChallenges(blobFieldsPerCheckpoint);
|
|
154
|
+
this.log.info(`Final blob batching challeneger: ${timer.ms()}ms`);
|
|
137
155
|
|
|
138
|
-
|
|
139
|
-
// Total number of checkpoints equals number of blocks because we currently build a checkpoint with only one block.
|
|
140
|
-
const totalNumCheckpoints = epochSizeBlocks;
|
|
141
|
-
|
|
142
|
-
this.prover.startNewEpoch(epochNumber, totalNumCheckpoints, finalBlobBatchingChallenges);
|
|
156
|
+
this.prover.startNewEpoch(epochNumber, epochSizeCheckpoints, finalBlobBatchingChallenges);
|
|
143
157
|
await this.prover.startChonkVerifierCircuits(Array.from(this.txs.values()));
|
|
144
158
|
|
|
145
|
-
|
|
146
|
-
|
|
159
|
+
// Everything in the epoch should have the same chainId and version.
|
|
160
|
+
const { chainId, version } = this.checkpoints[0].blocks[0].header.globalVariables;
|
|
147
161
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
this.log.verbose(`Starting processing block ${block.number}`, {
|
|
154
|
-
number: block.number,
|
|
155
|
-
blockHash: (await block.hash()).toString(),
|
|
156
|
-
lastArchive: block.header.lastArchive.root,
|
|
157
|
-
noteHashTreeRoot: block.header.state.partial.noteHashTree.root,
|
|
158
|
-
nullifierTreeRoot: block.header.state.partial.nullifierTree.root,
|
|
159
|
-
publicDataTreeRoot: block.header.state.partial.publicDataTree.root,
|
|
160
|
-
previousHeader: previousHeader.hash(),
|
|
161
|
-
uuid: this.uuid,
|
|
162
|
-
...globalVariables,
|
|
163
|
-
});
|
|
162
|
+
const previousBlockHeaders = this.gatherPreviousBlockHeaders();
|
|
163
|
+
|
|
164
|
+
await asyncPool(this.config.parallelBlockLimit ?? 32, this.checkpoints, async checkpoint => {
|
|
165
|
+
this.checkState();
|
|
164
166
|
|
|
167
|
+
const checkpointIndex = checkpoint.number - fromCheckpoint;
|
|
165
168
|
const checkpointConstants = CheckpointConstantData.from({
|
|
166
|
-
chainId
|
|
167
|
-
version
|
|
169
|
+
chainId,
|
|
170
|
+
version,
|
|
168
171
|
vkTreeRoot: getVKTreeRoot(),
|
|
169
172
|
protocolContractsHash: protocolContractsHash,
|
|
170
173
|
proverId: this.prover.getProverId().toField(),
|
|
171
|
-
slotNumber:
|
|
172
|
-
coinbase:
|
|
173
|
-
feeRecipient:
|
|
174
|
-
gasFees:
|
|
174
|
+
slotNumber: checkpoint.header.slotNumber,
|
|
175
|
+
coinbase: checkpoint.header.coinbase,
|
|
176
|
+
feeRecipient: checkpoint.header.feeRecipient,
|
|
177
|
+
gasFees: checkpoint.header.gasFees,
|
|
178
|
+
});
|
|
179
|
+
const previousHeader = previousBlockHeaders[checkpointIndex];
|
|
180
|
+
const l1ToL2Messages = this.getL1ToL2Messages(checkpoint);
|
|
181
|
+
|
|
182
|
+
this.log.verbose(`Starting processing checkpoint ${checkpoint.number}`, {
|
|
183
|
+
number: checkpoint.number,
|
|
184
|
+
checkpointHash: checkpoint.hash().toString(),
|
|
185
|
+
lastArchive: checkpoint.header.lastArchiveRoot,
|
|
186
|
+
previousHeader: previousHeader.hash(),
|
|
187
|
+
uuid: this.uuid,
|
|
175
188
|
});
|
|
176
189
|
|
|
177
|
-
// TODO(#17027): Enable multiple blocks per checkpoint.
|
|
178
|
-
// Each checkpoint has only one block.
|
|
179
|
-
const totalNumBlocks = 1;
|
|
180
|
-
const checkpointIndex = block.number - fromBlock;
|
|
181
190
|
await this.prover.startNewCheckpoint(
|
|
182
191
|
checkpointIndex,
|
|
183
192
|
checkpointConstants,
|
|
184
193
|
l1ToL2Messages,
|
|
185
|
-
|
|
186
|
-
blobFieldsPerCheckpoint[checkpointIndex].length,
|
|
194
|
+
checkpoint.blocks.length,
|
|
187
195
|
previousHeader,
|
|
188
196
|
);
|
|
189
197
|
|
|
190
|
-
|
|
191
|
-
|
|
198
|
+
for (let blockIndex = 0; blockIndex < checkpoint.blocks.length; blockIndex++) {
|
|
199
|
+
const block = checkpoint.blocks[blockIndex];
|
|
200
|
+
const globalVariables = block.header.globalVariables;
|
|
201
|
+
const txs = this.getTxs(block);
|
|
202
|
+
|
|
203
|
+
this.log.verbose(`Starting processing block ${block.number}`, {
|
|
204
|
+
number: block.number,
|
|
205
|
+
blockHash: (await block.hash()).toString(),
|
|
206
|
+
lastArchive: block.header.lastArchive.root,
|
|
207
|
+
noteHashTreeRoot: block.header.state.partial.noteHashTree.root,
|
|
208
|
+
nullifierTreeRoot: block.header.state.partial.nullifierTree.root,
|
|
209
|
+
publicDataTreeRoot: block.header.state.partial.publicDataTree.root,
|
|
210
|
+
...globalVariables,
|
|
211
|
+
numTxs: txs.length,
|
|
212
|
+
});
|
|
192
213
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
214
|
+
// Start block proving
|
|
215
|
+
await this.prover.startNewBlock(block.number, globalVariables.timestamp, txs.length);
|
|
216
|
+
|
|
217
|
+
// Process public fns. L1 to L2 messages are only inserted for the first block of a checkpoint,
|
|
218
|
+
// as the fork for subsequent blocks already includes them from the previous block's synced state.
|
|
219
|
+
const db = await this.createFork(
|
|
220
|
+
BlockNumber(block.number - 1),
|
|
221
|
+
blockIndex === 0 ? l1ToL2Messages : undefined,
|
|
222
|
+
);
|
|
223
|
+
const config = PublicSimulatorConfig.from({
|
|
224
|
+
proverId: this.prover.getProverId().toField(),
|
|
225
|
+
skipFeeEnforcement: false,
|
|
226
|
+
collectDebugLogs: false,
|
|
227
|
+
collectHints: true,
|
|
228
|
+
collectPublicInputs: true,
|
|
229
|
+
collectStatistics: false,
|
|
230
|
+
});
|
|
231
|
+
const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, config);
|
|
232
|
+
const processed = await this.processTxs(publicProcessor, txs);
|
|
233
|
+
await this.prover.addTxs(processed);
|
|
234
|
+
await db.close();
|
|
235
|
+
this.log.verbose(`Processed all ${txs.length} txs for block ${block.number}`, {
|
|
236
|
+
blockNumber: block.number,
|
|
237
|
+
blockHash: (await block.hash()).toString(),
|
|
238
|
+
uuid: this.uuid,
|
|
239
|
+
});
|
|
208
240
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
241
|
+
// Mark block as completed to pad it
|
|
242
|
+
const expectedBlockHeader = block.header;
|
|
243
|
+
await this.prover.setBlockCompleted(block.number, expectedBlockHeader);
|
|
244
|
+
}
|
|
212
245
|
});
|
|
213
246
|
|
|
214
247
|
const executionTime = timer.ms();
|
|
@@ -221,16 +254,16 @@ export class EpochProvingJob implements Traceable {
|
|
|
221
254
|
|
|
222
255
|
if (this.config.skipSubmitProof) {
|
|
223
256
|
this.log.info(
|
|
224
|
-
`Proof publishing is disabled. Dropping valid proof for epoch ${epochNumber} (
|
|
257
|
+
`Proof publishing is disabled. Dropping valid proof for epoch ${epochNumber} (checkpoints ${fromCheckpoint} to ${toCheckpoint})`,
|
|
225
258
|
);
|
|
226
259
|
this.state = 'completed';
|
|
227
|
-
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeBlocks, epochSizeTxs);
|
|
260
|
+
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeCheckpoints, epochSizeBlocks, epochSizeTxs);
|
|
228
261
|
return;
|
|
229
262
|
}
|
|
230
263
|
|
|
231
264
|
const success = await this.publisher.submitEpochProof({
|
|
232
|
-
|
|
233
|
-
|
|
265
|
+
fromCheckpoint,
|
|
266
|
+
toCheckpoint,
|
|
234
267
|
epochNumber,
|
|
235
268
|
publicInputs,
|
|
236
269
|
proof,
|
|
@@ -241,12 +274,12 @@ export class EpochProvingJob implements Traceable {
|
|
|
241
274
|
throw new Error('Failed to submit epoch proof to L1');
|
|
242
275
|
}
|
|
243
276
|
|
|
244
|
-
this.log.info(`Submitted proof for epoch ${epochNumber} (
|
|
277
|
+
this.log.info(`Submitted proof for epoch ${epochNumber} (checkpoints ${fromCheckpoint} to ${toCheckpoint})`, {
|
|
245
278
|
epochNumber,
|
|
246
279
|
uuid: this.uuid,
|
|
247
280
|
});
|
|
248
281
|
this.state = 'completed';
|
|
249
|
-
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeBlocks, epochSizeTxs);
|
|
282
|
+
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeCheckpoints, epochSizeBlocks, epochSizeTxs);
|
|
250
283
|
} catch (err: any) {
|
|
251
284
|
if (err && err.name === 'HaltExecutionError') {
|
|
252
285
|
this.log.warn(`Halted execution of epoch ${epochNumber} prover job`, {
|
|
@@ -269,22 +302,29 @@ export class EpochProvingJob implements Traceable {
|
|
|
269
302
|
}
|
|
270
303
|
|
|
271
304
|
/**
|
|
272
|
-
* Create a new db fork for tx processing, inserting
|
|
305
|
+
* Create a new db fork for tx processing, optionally inserting L1 to L2 messages.
|
|
306
|
+
* L1 to L2 messages should only be inserted for the first block in a checkpoint,
|
|
307
|
+
* as subsequent blocks' synced state already includes them.
|
|
273
308
|
* 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.
|
|
274
309
|
*/
|
|
275
|
-
private async createFork(blockNumber:
|
|
310
|
+
private async createFork(blockNumber: BlockNumber, l1ToL2Messages: Fr[] | undefined) {
|
|
311
|
+
this.log.verbose(`Creating fork at ${blockNumber}`, { blockNumber });
|
|
276
312
|
const db = await this.dbProvider.fork(blockNumber);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
313
|
+
|
|
314
|
+
if (l1ToL2Messages !== undefined) {
|
|
315
|
+
this.log.verbose(`Inserting ${l1ToL2Messages.length} L1 to L2 messages in fork`, {
|
|
316
|
+
blockNumber,
|
|
317
|
+
l1ToL2Messages: l1ToL2Messages.map(m => m.toString()),
|
|
318
|
+
});
|
|
319
|
+
const l1ToL2MessagesPadded = padArrayEnd<Fr, number>(
|
|
320
|
+
l1ToL2Messages,
|
|
321
|
+
Fr.ZERO,
|
|
322
|
+
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
323
|
+
'Too many L1 to L2 messages',
|
|
324
|
+
);
|
|
325
|
+
await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
326
|
+
}
|
|
327
|
+
|
|
288
328
|
return db;
|
|
289
329
|
}
|
|
290
330
|
|
|
@@ -341,11 +381,12 @@ export class EpochProvingJob implements Traceable {
|
|
|
341
381
|
const intervalMs = Math.ceil((await l2BlockSource.getL1Constants()).ethereumSlotDuration / 2) * 1000;
|
|
342
382
|
this.epochCheckPromise = new RunningPromise(
|
|
343
383
|
async () => {
|
|
344
|
-
const
|
|
345
|
-
const blockHashes = await Promise.all(
|
|
346
|
-
const
|
|
384
|
+
const blockHeaders = await l2BlockSource.getCheckpointedBlockHeadersForEpoch(this.epochNumber);
|
|
385
|
+
const blockHashes = await Promise.all(blockHeaders.map(header => header.hash()));
|
|
386
|
+
const thisBlocks = this.checkpoints.flatMap(checkpoint => checkpoint.blocks);
|
|
387
|
+
const thisBlockHashes = await Promise.all(thisBlocks.map(block => block.hash()));
|
|
347
388
|
if (
|
|
348
|
-
|
|
389
|
+
blockHeaders.length !== thisBlocks.length ||
|
|
349
390
|
!blockHashes.every((block, i) => block.equals(thisBlockHashes[i]))
|
|
350
391
|
) {
|
|
351
392
|
this.log.warn('Epoch blocks changed underfoot', {
|
|
@@ -363,30 +404,18 @@ export class EpochProvingJob implements Traceable {
|
|
|
363
404
|
this.log.verbose(`Scheduled epoch check for epoch ${this.epochNumber} every ${intervalMs}ms`);
|
|
364
405
|
}
|
|
365
406
|
|
|
366
|
-
/* Returns the header
|
|
367
|
-
private
|
|
368
|
-
const
|
|
369
|
-
|
|
370
|
-
return block.getBlockHeader();
|
|
371
|
-
}
|
|
372
|
-
|
|
373
|
-
if (blockNumber === Number(this.data.previousBlockHeader.getBlockNumber())) {
|
|
374
|
-
return this.data.previousBlockHeader;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
throw new Error(
|
|
378
|
-
`Block header not found for block number ${blockNumber} (got ${this.blocks
|
|
379
|
-
.map(b => b.number)
|
|
380
|
-
.join(', ')} and previous header ${this.data.previousBlockHeader.getBlockNumber()})`,
|
|
381
|
-
);
|
|
407
|
+
/* Returns the last block header in the previous checkpoint for all checkpoints in the epoch */
|
|
408
|
+
private gatherPreviousBlockHeaders() {
|
|
409
|
+
const lastBlocks = this.checkpoints.map(checkpoint => checkpoint.blocks.at(-1)!);
|
|
410
|
+
return [this.data.previousBlockHeader, ...lastBlocks.map(block => block.header).slice(0, -1)];
|
|
382
411
|
}
|
|
383
412
|
|
|
384
413
|
private getTxs(block: L2Block): Tx[] {
|
|
385
414
|
return block.body.txEffects.map(txEffect => this.txs.get(txEffect.txHash.toString())!);
|
|
386
415
|
}
|
|
387
416
|
|
|
388
|
-
private getL1ToL2Messages(
|
|
389
|
-
return this.data.l1ToL2Messages[
|
|
417
|
+
private getL1ToL2Messages(checkpoint: Checkpoint) {
|
|
418
|
+
return this.data.l1ToL2Messages[checkpoint.number];
|
|
390
419
|
}
|
|
391
420
|
|
|
392
421
|
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';
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
type TelemetryClient,
|
|
14
14
|
type Tracer,
|
|
15
15
|
type UpDownCounter,
|
|
16
|
-
|
|
16
|
+
createUpDownCounterWithDefault,
|
|
17
17
|
} from '@aztec/telemetry-client';
|
|
18
18
|
|
|
19
19
|
import { formatEther, formatUnits } from 'viem';
|
|
@@ -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
|
|
|
@@ -29,29 +30,23 @@ export class ProverNodeJobMetrics {
|
|
|
29
30
|
public readonly tracer: Tracer,
|
|
30
31
|
private logger = createLogger('prover-node:publisher:metrics'),
|
|
31
32
|
) {
|
|
32
|
-
this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
|
|
38
|
-
description: 'Duration of proving job',
|
|
39
|
-
unit: 's',
|
|
40
|
-
valueType: ValueType.DOUBLE,
|
|
41
|
-
});
|
|
42
|
-
this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
|
|
43
|
-
description: 'Number of blocks in a proven epoch',
|
|
44
|
-
valueType: ValueType.INT,
|
|
45
|
-
});
|
|
46
|
-
this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
|
|
47
|
-
description: 'Number of transactions in a proven epoch',
|
|
48
|
-
valueType: ValueType.INT,
|
|
49
|
-
});
|
|
33
|
+
this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION);
|
|
34
|
+
this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION);
|
|
35
|
+
this.provingJobCheckpoints = this.meter.createGauge(Metrics.PROVER_NODE_JOB_CHECKPOINTS);
|
|
36
|
+
this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS);
|
|
37
|
+
this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS);
|
|
50
38
|
}
|
|
51
39
|
|
|
52
|
-
public recordProvingJob(
|
|
40
|
+
public recordProvingJob(
|
|
41
|
+
executionTimeMs: number,
|
|
42
|
+
totalTimeMs: number,
|
|
43
|
+
numCheckpoints: number,
|
|
44
|
+
numBlocks: number,
|
|
45
|
+
numTxs: number,
|
|
46
|
+
) {
|
|
53
47
|
this.proverEpochExecutionDuration.record(Math.ceil(executionTimeMs));
|
|
54
48
|
this.provingJobDuration.record(totalTimeMs / 1000);
|
|
49
|
+
this.provingJobCheckpoints.record(Math.floor(numCheckpoints));
|
|
55
50
|
this.provingJobBlocks.record(Math.floor(numBlocks));
|
|
56
51
|
this.provingJobTransactions.record(Math.floor(numTxs));
|
|
57
52
|
}
|
|
@@ -69,15 +64,9 @@ export class ProverNodeRewardsMetrics {
|
|
|
69
64
|
private rollup: RollupContract,
|
|
70
65
|
private logger = createLogger('prover-node:publisher:metrics'),
|
|
71
66
|
) {
|
|
72
|
-
this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH
|
|
73
|
-
valueType: ValueType.DOUBLE,
|
|
74
|
-
description: 'The rewards earned',
|
|
75
|
-
});
|
|
67
|
+
this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH);
|
|
76
68
|
|
|
77
|
-
this.accumulatedRewards = this.meter
|
|
78
|
-
valueType: ValueType.DOUBLE,
|
|
79
|
-
description: 'The rewards earned (total)',
|
|
80
|
-
});
|
|
69
|
+
this.accumulatedRewards = createUpDownCounterWithDefault(this.meter, Metrics.PROVER_NODE_REWARDS_TOTAL);
|
|
81
70
|
}
|
|
82
71
|
|
|
83
72
|
public async start() {
|
|
@@ -97,7 +86,7 @@ export class ProverNodeRewardsMetrics {
|
|
|
97
86
|
// look at the prev epoch so that we get an accurate value, after proof submission window has closed
|
|
98
87
|
// For example, if proof submission window is 1 epoch, and we are in epoch 2, we should be looking at epoch 0.
|
|
99
88
|
// 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;
|
|
89
|
+
const closedEpoch = BigInt(epoch) - BigInt(this.proofSubmissionEpochs) - 1n;
|
|
101
90
|
const rewards = await this.rollup.getSpecificProverRewardsForEpoch(closedEpoch, this.coinbase);
|
|
102
91
|
|
|
103
92
|
const fmt = parseFloat(formatUnits(rewards, 18));
|
|
@@ -138,68 +127,28 @@ export class ProverNodePublisherMetrics {
|
|
|
138
127
|
) {
|
|
139
128
|
this.meter = client.getMeter(name);
|
|
140
129
|
|
|
141
|
-
this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE
|
|
142
|
-
description: 'The gas price used for transactions',
|
|
143
|
-
unit: 'gwei',
|
|
144
|
-
valueType: ValueType.DOUBLE,
|
|
145
|
-
});
|
|
130
|
+
this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE);
|
|
146
131
|
|
|
147
|
-
this.txCount = this.meter
|
|
148
|
-
|
|
132
|
+
this.txCount = createUpDownCounterWithDefault(this.meter, Metrics.L1_PUBLISHER_TX_COUNT, {
|
|
133
|
+
[Attributes.L1_TX_TYPE]: ['submitProof'],
|
|
134
|
+
[Attributes.OK]: [true, false],
|
|
149
135
|
});
|
|
150
136
|
|
|
151
|
-
this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION
|
|
152
|
-
description: 'The duration of transaction processing',
|
|
153
|
-
unit: 'ms',
|
|
154
|
-
valueType: ValueType.INT,
|
|
155
|
-
});
|
|
137
|
+
this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION);
|
|
156
138
|
|
|
157
|
-
this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS
|
|
158
|
-
description: 'The gas consumed by transactions',
|
|
159
|
-
unit: 'gas',
|
|
160
|
-
valueType: ValueType.INT,
|
|
161
|
-
});
|
|
139
|
+
this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS);
|
|
162
140
|
|
|
163
|
-
this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE
|
|
164
|
-
description: 'The size of the calldata in transactions',
|
|
165
|
-
unit: 'By',
|
|
166
|
-
valueType: ValueType.INT,
|
|
167
|
-
});
|
|
141
|
+
this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE);
|
|
168
142
|
|
|
169
|
-
this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS
|
|
170
|
-
description: 'The gas consumed by the calldata in transactions',
|
|
171
|
-
unit: 'gas',
|
|
172
|
-
valueType: ValueType.INT,
|
|
173
|
-
});
|
|
143
|
+
this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS);
|
|
174
144
|
|
|
175
|
-
this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED
|
|
176
|
-
description: 'The amount of blob gas used in transactions',
|
|
177
|
-
unit: 'gas',
|
|
178
|
-
valueType: ValueType.INT,
|
|
179
|
-
});
|
|
145
|
+
this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED);
|
|
180
146
|
|
|
181
|
-
this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST
|
|
182
|
-
description: 'The gas cost of blobs in transactions',
|
|
183
|
-
unit: 'gwei',
|
|
184
|
-
valueType: ValueType.INT,
|
|
185
|
-
});
|
|
147
|
+
this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST);
|
|
186
148
|
|
|
187
|
-
this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE
|
|
188
|
-
description: 'How much L1 tx costs',
|
|
189
|
-
unit: 'gwei',
|
|
190
|
-
valueType: ValueType.DOUBLE,
|
|
191
|
-
advice: {
|
|
192
|
-
explicitBucketBoundaries: [
|
|
193
|
-
0.001, 0.002, 0.004, 0.008, 0.01, 0.02, 0.04, 0.08, 0.1, 0.2, 0.4, 0.8, 1, 1.2, 1.4, 1.8, 2,
|
|
194
|
-
],
|
|
195
|
-
},
|
|
196
|
-
});
|
|
149
|
+
this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE);
|
|
197
150
|
|
|
198
|
-
this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE
|
|
199
|
-
unit: 'eth',
|
|
200
|
-
description: 'The balance of the sender address',
|
|
201
|
-
valueType: ValueType.DOUBLE,
|
|
202
|
-
});
|
|
151
|
+
this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE);
|
|
203
152
|
}
|
|
204
153
|
|
|
205
154
|
recordFailedTx() {
|
|
@@ -1,18 +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';
|
|
3
4
|
import { sleep } from '@aztec/foundation/sleep';
|
|
4
5
|
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
5
6
|
import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
|
|
6
|
-
import {
|
|
7
|
-
type TelemetryClient,
|
|
8
|
-
type Traceable,
|
|
9
|
-
type Tracer,
|
|
10
|
-
getTelemetryClient,
|
|
11
|
-
trackSpan,
|
|
12
|
-
} from '@aztec/telemetry-client';
|
|
7
|
+
import { type TelemetryClient, type Traceable, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
13
8
|
|
|
14
9
|
export interface EpochMonitorHandler {
|
|
15
|
-
handleEpochReadyToProve(epochNumber:
|
|
10
|
+
handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean>;
|
|
16
11
|
}
|
|
17
12
|
|
|
18
13
|
/**
|
|
@@ -32,7 +27,7 @@ export class EpochMonitor implements Traceable {
|
|
|
32
27
|
public readonly tracer: Tracer;
|
|
33
28
|
|
|
34
29
|
private handler: EpochMonitorHandler | undefined;
|
|
35
|
-
private latestEpochNumber:
|
|
30
|
+
private latestEpochNumber: EpochNumber | undefined;
|
|
36
31
|
|
|
37
32
|
constructor(
|
|
38
33
|
private readonly l2BlockSource: L2BlockSource,
|
|
@@ -72,7 +67,6 @@ export class EpochMonitor implements Traceable {
|
|
|
72
67
|
this.log.info('Stopped EpochMonitor');
|
|
73
68
|
}
|
|
74
69
|
|
|
75
|
-
@trackSpan('EpochMonitor.work')
|
|
76
70
|
public async work() {
|
|
77
71
|
const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
|
|
78
72
|
this.log.debug(`Epoch to prove: ${epochToProve}`, { blockNumber, slotNumber });
|
|
@@ -104,7 +98,7 @@ export class EpochMonitor implements Traceable {
|
|
|
104
98
|
|
|
105
99
|
private async getEpochNumberToProve() {
|
|
106
100
|
const lastBlockProven = await this.l2BlockSource.getProvenBlockNumber();
|
|
107
|
-
const firstBlockToProve = lastBlockProven + 1;
|
|
101
|
+
const firstBlockToProve = BlockNumber(lastBlockProven + 1);
|
|
108
102
|
const firstBlockHeaderToProve = await this.l2BlockSource.getBlockHeader(firstBlockToProve);
|
|
109
103
|
if (!firstBlockHeaderToProve) {
|
|
110
104
|
return { epochToProve: undefined, blockNumber: firstBlockToProve };
|