@aztec/prover-node 0.0.1-commit.d3ec352c → 0.0.1-commit.d6f2b3f94

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 (47) hide show
  1. package/dest/actions/download-epoch-proving-job.d.ts +1 -1
  2. package/dest/actions/rerun-epoch-proving-job.d.ts +3 -2
  3. package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
  4. package/dest/actions/rerun-epoch-proving-job.js +5 -3
  5. package/dest/config.d.ts +5 -4
  6. package/dest/config.d.ts.map +1 -1
  7. package/dest/config.js +4 -3
  8. package/dest/factory.d.ts +5 -4
  9. package/dest/factory.d.ts.map +1 -1
  10. package/dest/factory.js +28 -19
  11. package/dest/index.d.ts +2 -1
  12. package/dest/index.d.ts.map +1 -1
  13. package/dest/index.js +1 -0
  14. package/dest/job/epoch-proving-job-data.d.ts +2 -2
  15. package/dest/job/epoch-proving-job-data.d.ts.map +1 -1
  16. package/dest/job/epoch-proving-job-data.js +1 -1
  17. package/dest/job/epoch-proving-job.d.ts +3 -2
  18. package/dest/job/epoch-proving-job.d.ts.map +1 -1
  19. package/dest/job/epoch-proving-job.js +416 -29
  20. package/dest/metrics.d.ts +2 -2
  21. package/dest/metrics.d.ts.map +1 -1
  22. package/dest/metrics.js +26 -100
  23. package/dest/monitors/epoch-monitor.d.ts +1 -1
  24. package/dest/monitors/epoch-monitor.d.ts.map +1 -1
  25. package/dest/monitors/epoch-monitor.js +1 -10
  26. package/dest/prover-node-publisher.d.ts +9 -7
  27. package/dest/prover-node-publisher.d.ts.map +1 -1
  28. package/dest/prover-node-publisher.js +25 -20
  29. package/dest/prover-node.d.ts +3 -3
  30. package/dest/prover-node.d.ts.map +1 -1
  31. package/dest/prover-node.js +402 -24
  32. package/dest/prover-publisher-factory.d.ts +7 -3
  33. package/dest/prover-publisher-factory.d.ts.map +1 -1
  34. package/dest/prover-publisher-factory.js +4 -2
  35. package/package.json +23 -23
  36. package/src/actions/rerun-epoch-proving-job.ts +5 -3
  37. package/src/bin/run-failed-epoch.ts +1 -1
  38. package/src/config.ts +6 -4
  39. package/src/factory.ts +36 -22
  40. package/src/index.ts +1 -0
  41. package/src/job/epoch-proving-job-data.ts +1 -1
  42. package/src/job/epoch-proving-job.ts +45 -24
  43. package/src/metrics.ts +21 -84
  44. package/src/monitors/epoch-monitor.ts +1 -8
  45. package/src/prover-node-publisher.ts +33 -25
  46. package/src/prover-node.ts +7 -7
  47. package/src/prover-publisher-factory.ts +14 -6
package/src/config.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver/config';
2
2
  import type { ACVMConfig, BBConfig } from '@aztec/bb-prover/config';
3
- import { type GenesisStateConfig, genesisStateConfigMappings } from '@aztec/ethereum';
3
+ import { type GenesisStateConfig, genesisStateConfigMappings } from '@aztec/ethereum/config';
4
4
  import {
5
5
  type ConfigMappingsType,
6
6
  booleanConfigHelper,
@@ -8,7 +8,9 @@ import {
8
8
  numberConfigHelper,
9
9
  } from '@aztec/foundation/config';
10
10
  import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config';
11
- import { type KeyStore, type KeyStoreConfig, ethPrivateKeySchema, keyStoreConfigMappings } from '@aztec/node-keystore';
11
+ import { type KeyStoreConfig, keyStoreConfigMappings } from '@aztec/node-keystore/config';
12
+ import { ethPrivateKeySchema } from '@aztec/node-keystore/schemas';
13
+ import type { KeyStore } from '@aztec/node-keystore/types';
12
14
  import { type SharedNodeConfig, sharedNodeConfigMappings } from '@aztec/node-lib/config';
13
15
  import { type P2PConfig, p2pConfigMappings } from '@aztec/p2p/config';
14
16
  import {
@@ -16,7 +18,7 @@ import {
16
18
  type ProverBrokerConfig,
17
19
  proverAgentConfigMappings,
18
20
  proverBrokerConfigMappings,
19
- } from '@aztec/prover-client/broker';
21
+ } from '@aztec/prover-client/broker/config';
20
22
  import { type ProverClientUserConfig, bbConfigMappings, proverClientConfigMappings } from '@aztec/prover-client/config';
21
23
  import {
22
24
  type PublisherConfig,
@@ -163,7 +165,7 @@ function createKeyStoreFromWeb3Signer(config: ProverNodeConfig): KeyStore | unde
163
165
  function createKeyStoreFromPublisherKeys(config: ProverNodeConfig): KeyStore | undefined {
164
166
  // Extract the publisher keys from the provided config.
165
167
  const publisherKeys = config.publisherPrivateKeys
166
- ? config.publisherPrivateKeys.map(k => ethPrivateKeySchema.parse(k.getValue()))
168
+ ? config.publisherPrivateKeys.map((k: { getValue: () => string }) => ethPrivateKeySchema.parse(k.getValue()))
167
169
  : [];
168
170
 
169
171
  // There must be at least 1.
package/src/factory.ts CHANGED
@@ -1,16 +1,22 @@
1
1
  import { type Archiver, createArchiver } from '@aztec/archiver';
2
2
  import { BBCircuitVerifier, QueuedIVCVerifier, TestCircuitVerifier } from '@aztec/bb-prover';
3
- import { type BlobSinkClientInterface, createBlobSinkClient } from '@aztec/blob-sink/client';
3
+ import { createBlobClientWithFileStores } from '@aztec/blob-client/client';
4
4
  import { EpochCache } from '@aztec/epoch-cache';
5
- import { L1TxUtils, PublisherManager, RollupContract, createEthereumChain } from '@aztec/ethereum';
5
+ import { createEthereumChain } from '@aztec/ethereum/chain';
6
+ import { RollupContract } from '@aztec/ethereum/contracts';
7
+ import { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
8
+ import { PublisherManager } from '@aztec/ethereum/publisher-manager';
6
9
  import { pick } from '@aztec/foundation/collection';
7
10
  import { type Logger, createLogger } from '@aztec/foundation/log';
8
11
  import { DateProvider } from '@aztec/foundation/timer';
9
12
  import type { DataStoreConfig } from '@aztec/kv-store/config';
10
13
  import { type KeyStoreConfig, KeystoreManager, loadKeystores, mergeKeystores } from '@aztec/node-keystore';
11
14
  import { trySnapshotSync } from '@aztec/node-lib/actions';
12
- import { createL1TxUtilsFromEthSignerWithStore } from '@aztec/node-lib/factories';
13
- import { NodeRpcTxSource, createP2PClient } from '@aztec/p2p';
15
+ import {
16
+ createForwarderL1TxUtilsFromEthSigner,
17
+ createL1TxUtilsFromEthSignerWithStore,
18
+ } from '@aztec/node-lib/factories';
19
+ import { NodeRpcTxSource, type P2PClientDeps, createP2PClient } from '@aztec/p2p';
14
20
  import { type ProverClientConfig, createProverClient } from '@aztec/prover-client';
15
21
  import { createAndStartProvingBroker } from '@aztec/prover-client/broker';
16
22
  import type { AztecNode, ProvingJobBroker } from '@aztec/stdlib/interfaces/server';
@@ -33,10 +39,10 @@ export type ProverNodeDeps = {
33
39
  aztecNodeTxProvider?: Pick<AztecNode, 'getTxsByHash'>;
34
40
  archiver?: Archiver;
35
41
  publisherFactory?: ProverPublisherFactory;
36
- blobSinkClient?: BlobSinkClientInterface;
37
42
  broker?: ProvingJobBroker;
38
43
  l1TxUtils?: L1TxUtils;
39
44
  dateProvider?: DateProvider;
45
+ p2pClientDeps?: P2PClientDeps<P2PClientType.Prover>;
40
46
  };
41
47
 
42
48
  /** Creates a new prover node given a config. */
@@ -50,8 +56,7 @@ export async function createProverNode(
50
56
  const config = { ...userConfig };
51
57
  const telemetry = deps.telemetry ?? getTelemetryClient();
52
58
  const dateProvider = deps.dateProvider ?? new DateProvider();
53
- const blobSinkClient =
54
- deps.blobSinkClient ?? createBlobSinkClient(config, { logger: createLogger('prover-node:blob-sink:client') });
59
+ const blobClient = await createBlobClientWithFileStores(config, createLogger('prover-node:blob-client:client'));
55
60
  const log = deps.log ?? createLogger('prover-node');
56
61
 
57
62
  // Build a key store from file if given or from environment otherwise
@@ -102,12 +107,11 @@ export async function createProverNode(
102
107
 
103
108
  const archiver =
104
109
  deps.archiver ??
105
- (await createArchiver(config, { blobSinkClient, epochCache, telemetry, dateProvider }, { blockUntilSync: true }));
110
+ (await createArchiver(config, { blobClient, epochCache, telemetry, dateProvider }, { blockUntilSync: true }));
106
111
  log.verbose(`Created archiver and synced to block ${await archiver.getBlockNumber()}`);
107
112
 
108
- const worldStateConfig = { ...config, worldStateProvenBlocksOnly: false };
109
113
  const worldStateSynchronizer = await createWorldStateSynchronizer(
110
- worldStateConfig,
114
+ config,
111
115
  archiver,
112
116
  options.prefilledPublicData,
113
117
  telemetry,
@@ -123,7 +127,7 @@ export async function createProverNode(
123
127
 
124
128
  const publicClient = createPublicClient({
125
129
  chain: chain.chainInfo,
126
- transport: fallback(config.l1RpcUrls.map((url: string) => http(url))),
130
+ transport: fallback(config.l1RpcUrls.map((url: string) => http(url, { batch: false }))),
127
131
  pollingInterval: config.viemPollingIntervalMS,
128
132
  });
129
133
 
@@ -131,24 +135,32 @@ export async function createProverNode(
131
135
 
132
136
  const l1TxUtils = deps.l1TxUtils
133
137
  ? [deps.l1TxUtils]
134
- : await createL1TxUtilsFromEthSignerWithStore(
135
- publicClient,
136
- proverSigners.signers,
137
- { ...config, scope: 'prover' },
138
- { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
139
- );
138
+ : config.publisherForwarderAddress
139
+ ? await createForwarderL1TxUtilsFromEthSigner(
140
+ publicClient,
141
+ proverSigners.signers,
142
+ config.publisherForwarderAddress,
143
+ { ...config, scope: 'prover' },
144
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
145
+ )
146
+ : await createL1TxUtilsFromEthSignerWithStore(
147
+ publicClient,
148
+ proverSigners.signers,
149
+ { ...config, scope: 'prover' },
150
+ { telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
151
+ );
140
152
 
141
153
  const publisherFactory =
142
154
  deps.publisherFactory ??
143
155
  new ProverPublisherFactory(config, {
144
156
  rollupContract,
145
- publisherManager: new PublisherManager(l1TxUtils, config),
157
+ publisherManager: new PublisherManager(l1TxUtils, config, log.getBindings()),
146
158
  telemetry,
147
159
  });
148
160
 
149
161
  const proofVerifier = new QueuedIVCVerifier(
150
162
  config,
151
- config.realProofs
163
+ config.realProofs || config.debugForceTxProofVerification
152
164
  ? await BBCircuitVerifier.new(config)
153
165
  : new TestCircuitVerifier(config.proverTestVerificationDelayMs),
154
166
  );
@@ -164,9 +176,11 @@ export async function createProverNode(
164
176
  dateProvider,
165
177
  telemetry,
166
178
  {
167
- txCollectionNodeSources: deps.aztecNodeTxProvider
168
- ? [new NodeRpcTxSource(deps.aztecNodeTxProvider, 'TestNode')]
169
- : [],
179
+ ...deps.p2pClientDeps,
180
+ txCollectionNodeSources: [
181
+ ...(deps.p2pClientDeps?.txCollectionNodeSources ?? []),
182
+ ...(deps.aztecNodeTxProvider ? [new NodeRpcTxSource(deps.aztecNodeTxProvider, 'TestNode')] : []),
183
+ ],
170
184
  },
171
185
  );
172
186
 
package/src/index.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './actions/index.js';
2
2
  export * from './config.js';
3
3
  export * from './factory.js';
4
+ export * from './monitors/index.js';
4
5
  export * from './prover-node-publisher.js';
5
6
  export * from './prover-node.js';
@@ -1,5 +1,5 @@
1
1
  import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
2
- import { Fr } from '@aztec/foundation/fields';
2
+ import { Fr } from '@aztec/foundation/curves/bn254';
3
3
  import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
4
4
  import { CommitteeAttestation } from '@aztec/stdlib/block';
5
5
  import { Checkpoint } from '@aztec/stdlib/checkpoint';
@@ -2,8 +2,8 @@ import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
2
2
  import { asyncPool } from '@aztec/foundation/async-pool';
3
3
  import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
4
4
  import { padArrayEnd } from '@aztec/foundation/collection';
5
- import { Fr } from '@aztec/foundation/fields';
6
- 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';
7
7
  import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
8
8
  import { Timer } from '@aztec/foundation/timer';
9
9
  import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types/vk-tree';
@@ -11,7 +11,7 @@ import { protocolContractsHash } from '@aztec/protocol-contracts';
11
11
  import { buildFinalBlobChallenges } from '@aztec/prover-client/helpers';
12
12
  import type { PublicProcessor, PublicProcessorFactory } from '@aztec/simulator/server';
13
13
  import { PublicSimulatorConfig } from '@aztec/stdlib/avm';
14
- import type { L2BlockNew, L2BlockSource } from '@aztec/stdlib/block';
14
+ import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
15
15
  import type { Checkpoint } from '@aztec/stdlib/checkpoint';
16
16
  import {
17
17
  type EpochProver,
@@ -43,7 +43,7 @@ export type EpochProvingJobOptions = {
43
43
  */
44
44
  export class EpochProvingJob implements Traceable {
45
45
  private state: EpochProvingJobState = 'initialized';
46
- private log = createLogger('prover-node:epoch-proving-job');
46
+ private log: Logger;
47
47
  private uuid: string;
48
48
 
49
49
  private runPromise: Promise<void> | undefined;
@@ -62,9 +62,14 @@ export class EpochProvingJob implements Traceable {
62
62
  private metrics: ProverNodeJobMetrics,
63
63
  private deadline: Date | undefined,
64
64
  private config: EpochProvingJobOptions,
65
+ bindings?: LoggerBindings,
65
66
  ) {
66
67
  validateEpochProvingJobData(data);
67
68
  this.uuid = crypto.randomUUID();
69
+ this.log = createLogger('prover-node:epoch-proving-job', {
70
+ ...bindings,
71
+ instanceId: `epoch-${data.epochNumber}`,
72
+ });
68
73
  this.tracer = metrics.tracer;
69
74
  }
70
75
 
@@ -188,7 +193,8 @@ export class EpochProvingJob implements Traceable {
188
193
  previousHeader,
189
194
  );
190
195
 
191
- for (const block of checkpoint.blocks) {
196
+ for (let blockIndex = 0; blockIndex < checkpoint.blocks.length; blockIndex++) {
197
+ const block = checkpoint.blocks[blockIndex];
192
198
  const globalVariables = block.header.globalVariables;
193
199
  const txs = this.getTxs(block);
194
200
 
@@ -206,13 +212,18 @@ export class EpochProvingJob implements Traceable {
206
212
  // Start block proving
207
213
  await this.prover.startNewBlock(block.number, globalVariables.timestamp, txs.length);
208
214
 
209
- // Process public fns
210
- const db = await this.createFork(BlockNumber(block.number - 1), l1ToL2Messages);
215
+ // Process public fns. L1 to L2 messages are only inserted for the first block of a checkpoint,
216
+ // as the fork for subsequent blocks already includes them from the previous block's synced state.
217
+ const db = await this.createFork(
218
+ BlockNumber(block.number - 1),
219
+ blockIndex === 0 ? l1ToL2Messages : undefined,
220
+ );
211
221
  const config = PublicSimulatorConfig.from({
212
222
  proverId: this.prover.getProverId().toField(),
213
223
  skipFeeEnforcement: false,
214
224
  collectDebugLogs: false,
215
225
  collectHints: true,
226
+ collectPublicInputs: true,
216
227
  collectStatistics: false,
217
228
  });
218
229
  const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, config);
@@ -289,22 +300,29 @@ export class EpochProvingJob implements Traceable {
289
300
  }
290
301
 
291
302
  /**
292
- * Create a new db fork for tx processing, inserting all L1 to L2.
303
+ * Create a new db fork for tx processing, optionally inserting L1 to L2 messages.
304
+ * L1 to L2 messages should only be inserted for the first block in a checkpoint,
305
+ * as subsequent blocks' synced state already includes them.
293
306
  * 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.
294
307
  */
295
- private async createFork(blockNumber: BlockNumber, l1ToL2Messages: Fr[]) {
308
+ private async createFork(blockNumber: BlockNumber, l1ToL2Messages: Fr[] | undefined) {
309
+ this.log.verbose(`Creating fork at ${blockNumber}`, { blockNumber });
296
310
  const db = await this.dbProvider.fork(blockNumber);
297
- const l1ToL2MessagesPadded = padArrayEnd<Fr, number>(
298
- l1ToL2Messages,
299
- Fr.ZERO,
300
- NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
301
- 'Too many L1 to L2 messages',
302
- );
303
- this.log.verbose(`Creating fork at ${blockNumber} with ${l1ToL2Messages.length} L1 to L2 messages`, {
304
- blockNumber,
305
- l1ToL2Messages: l1ToL2Messages.map(m => m.toString()),
306
- });
307
- await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
311
+
312
+ if (l1ToL2Messages !== undefined) {
313
+ this.log.verbose(`Inserting ${l1ToL2Messages.length} L1 to L2 messages in fork`, {
314
+ blockNumber,
315
+ l1ToL2Messages: l1ToL2Messages.map(m => m.toString()),
316
+ });
317
+ const l1ToL2MessagesPadded = padArrayEnd<Fr, number>(
318
+ l1ToL2Messages,
319
+ Fr.ZERO,
320
+ NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
321
+ 'Too many L1 to L2 messages',
322
+ );
323
+ await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
324
+ }
325
+
308
326
  return db;
309
327
  }
310
328
 
@@ -361,11 +379,14 @@ export class EpochProvingJob implements Traceable {
361
379
  const intervalMs = Math.ceil((await l2BlockSource.getL1Constants()).ethereumSlotDuration / 2) * 1000;
362
380
  this.epochCheckPromise = new RunningPromise(
363
381
  async () => {
364
- const blocks = await l2BlockSource.getBlockHeadersForEpoch(this.epochNumber);
365
- const blockHashes = await Promise.all(blocks.map(block => block.hash()));
382
+ const blockHeaders = await l2BlockSource.getCheckpointedBlockHeadersForEpoch(this.epochNumber);
383
+ const blockHashes = await Promise.all(blockHeaders.map(header => header.hash()));
366
384
  const thisBlocks = this.checkpoints.flatMap(checkpoint => checkpoint.blocks);
367
385
  const thisBlockHashes = await Promise.all(thisBlocks.map(block => block.hash()));
368
- if (blocks.length !== thisBlocks.length || !blockHashes.every((block, i) => block.equals(thisBlockHashes[i]))) {
386
+ if (
387
+ blockHeaders.length !== thisBlocks.length ||
388
+ !blockHashes.every((block, i) => block.equals(thisBlockHashes[i]))
389
+ ) {
369
390
  this.log.warn('Epoch blocks changed underfoot', {
370
391
  uuid: this.uuid,
371
392
  epochNumber: this.epochNumber,
@@ -387,7 +408,7 @@ export class EpochProvingJob implements Traceable {
387
408
  return [this.data.previousBlockHeader, ...lastBlocks.map(block => block.header).slice(0, -1)];
388
409
  }
389
410
 
390
- private getTxs(block: L2BlockNew): Tx[] {
411
+ private getTxs(block: L2Block): Tx[] {
391
412
  return block.body.txEffects.map(txEffect => this.txs.get(txEffect.txHash.toString())!);
392
413
  }
393
414
 
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
- ValueType,
16
+ createUpDownCounterWithDefault,
17
17
  } from '@aztec/telemetry-client';
18
18
 
19
19
  import { formatEther, formatUnits } from 'viem';
@@ -30,28 +30,11 @@ export class ProverNodeJobMetrics {
30
30
  public readonly tracer: Tracer,
31
31
  private logger = createLogger('prover-node:publisher:metrics'),
32
32
  ) {
33
- this.proverEpochExecutionDuration = this.meter.createHistogram(Metrics.PROVER_NODE_EXECUTION_DURATION, {
34
- description: 'Duration of execution of an epoch by the prover',
35
- unit: 'ms',
36
- valueType: ValueType.INT,
37
- });
38
- this.provingJobDuration = this.meter.createHistogram(Metrics.PROVER_NODE_JOB_DURATION, {
39
- description: 'Duration of proving job',
40
- unit: 's',
41
- valueType: ValueType.DOUBLE,
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
- });
47
- this.provingJobBlocks = this.meter.createGauge(Metrics.PROVER_NODE_JOB_BLOCKS, {
48
- description: 'Number of blocks in a proven epoch',
49
- valueType: ValueType.INT,
50
- });
51
- this.provingJobTransactions = this.meter.createGauge(Metrics.PROVER_NODE_JOB_TRANSACTIONS, {
52
- description: 'Number of transactions in a proven epoch',
53
- valueType: ValueType.INT,
54
- });
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);
55
38
  }
56
39
 
57
40
  public recordProvingJob(
@@ -81,15 +64,9 @@ export class ProverNodeRewardsMetrics {
81
64
  private rollup: RollupContract,
82
65
  private logger = createLogger('prover-node:publisher:metrics'),
83
66
  ) {
84
- this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH, {
85
- valueType: ValueType.DOUBLE,
86
- description: 'The rewards earned',
87
- });
67
+ this.rewards = this.meter.createObservableGauge(Metrics.PROVER_NODE_REWARDS_PER_EPOCH);
88
68
 
89
- this.accumulatedRewards = this.meter.createUpDownCounter(Metrics.PROVER_NODE_REWARDS_TOTAL, {
90
- valueType: ValueType.DOUBLE,
91
- description: 'The rewards earned (total)',
92
- });
69
+ this.accumulatedRewards = createUpDownCounterWithDefault(this.meter, Metrics.PROVER_NODE_REWARDS_TOTAL);
93
70
  }
94
71
 
95
72
  public async start() {
@@ -150,68 +127,28 @@ export class ProverNodePublisherMetrics {
150
127
  ) {
151
128
  this.meter = client.getMeter(name);
152
129
 
153
- this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE, {
154
- description: 'The gas price used for transactions',
155
- unit: 'gwei',
156
- valueType: ValueType.DOUBLE,
157
- });
130
+ this.gasPrice = this.meter.createHistogram(Metrics.L1_PUBLISHER_GAS_PRICE);
158
131
 
159
- this.txCount = this.meter.createUpDownCounter(Metrics.L1_PUBLISHER_TX_COUNT, {
160
- description: 'The number of transactions processed',
132
+ this.txCount = createUpDownCounterWithDefault(this.meter, Metrics.L1_PUBLISHER_TX_COUNT, {
133
+ [Attributes.L1_TX_TYPE]: ['submitProof'],
134
+ [Attributes.OK]: [true, false],
161
135
  });
162
136
 
163
- this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION, {
164
- description: 'The duration of transaction processing',
165
- unit: 'ms',
166
- valueType: ValueType.INT,
167
- });
137
+ this.txDuration = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_DURATION);
168
138
 
169
- this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS, {
170
- description: 'The gas consumed by transactions',
171
- unit: 'gas',
172
- valueType: ValueType.INT,
173
- });
139
+ this.txGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_GAS);
174
140
 
175
- this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE, {
176
- description: 'The size of the calldata in transactions',
177
- unit: 'By',
178
- valueType: ValueType.INT,
179
- });
141
+ this.txCalldataSize = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_SIZE);
180
142
 
181
- this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS, {
182
- description: 'The gas consumed by the calldata in transactions',
183
- unit: 'gas',
184
- valueType: ValueType.INT,
185
- });
143
+ this.txCalldataGas = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_CALLDATA_GAS);
186
144
 
187
- this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED, {
188
- description: 'The amount of blob gas used in transactions',
189
- unit: 'gas',
190
- valueType: ValueType.INT,
191
- });
145
+ this.txBlobDataGasUsed = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_USED);
192
146
 
193
- this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST, {
194
- description: 'The gas cost of blobs in transactions',
195
- unit: 'gwei',
196
- valueType: ValueType.INT,
197
- });
147
+ this.txBlobDataGasCost = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_BLOBDATA_GAS_COST);
198
148
 
199
- this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE, {
200
- description: 'How much L1 tx costs',
201
- unit: 'gwei',
202
- valueType: ValueType.DOUBLE,
203
- advice: {
204
- explicitBucketBoundaries: [
205
- 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,
206
- ],
207
- },
208
- });
149
+ this.txTotalFee = this.meter.createHistogram(Metrics.L1_PUBLISHER_TX_TOTAL_FEE);
209
150
 
210
- this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE, {
211
- unit: 'eth',
212
- description: 'The balance of the sender address',
213
- valueType: ValueType.DOUBLE,
214
- });
151
+ this.senderBalance = this.meter.createGauge(Metrics.L1_PUBLISHER_BALANCE);
215
152
  }
216
153
 
217
154
  recordFailedTx() {
@@ -4,13 +4,7 @@ import { RunningPromise } from '@aztec/foundation/running-promise';
4
4
  import { sleep } from '@aztec/foundation/sleep';
5
5
  import type { L2BlockSource } from '@aztec/stdlib/block';
6
6
  import { type L1RollupConstants, getEpochAtSlot } from '@aztec/stdlib/epoch-helpers';
7
- import {
8
- type TelemetryClient,
9
- type Traceable,
10
- type Tracer,
11
- getTelemetryClient,
12
- trackSpan,
13
- } from '@aztec/telemetry-client';
7
+ import { type TelemetryClient, type Traceable, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
14
8
 
15
9
  export interface EpochMonitorHandler {
16
10
  handleEpochReadyToProve(epochNumber: EpochNumber): Promise<boolean>;
@@ -73,7 +67,6 @@ export class EpochMonitor implements Traceable {
73
67
  this.log.info('Stopped EpochMonitor');
74
68
  }
75
69
 
76
- @trackSpan('EpochMonitor.work')
77
70
  public async work() {
78
71
  const { epochToProve, blockNumber, slotNumber } = await this.getEpochNumberToProve();
79
72
  this.log.debug(`Epoch to prove: ${epochToProve}`, { blockNumber, slotNumber });
@@ -1,12 +1,13 @@
1
1
  import { BatchedBlob, getEthBlobEvaluationInputs } from '@aztec/blob-lib';
2
- import { AZTEC_MAX_EPOCH_DURATION } from '@aztec/constants';
3
- import type { L1TxUtils, RollupContract, ViemCommitteeAttestation } from '@aztec/ethereum';
2
+ import { MAX_CHECKPOINTS_PER_EPOCH } from '@aztec/constants';
3
+ import type { RollupContract, ViemCommitteeAttestation } from '@aztec/ethereum/contracts';
4
+ import type { L1TxUtils } from '@aztec/ethereum/l1-tx-utils';
4
5
  import { makeTuple } from '@aztec/foundation/array';
5
6
  import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
6
7
  import { areArraysEqual } from '@aztec/foundation/collection';
8
+ import { Fr } from '@aztec/foundation/curves/bn254';
7
9
  import { EthAddress } from '@aztec/foundation/eth-address';
8
- import { Fr } from '@aztec/foundation/fields';
9
- import { createLogger } from '@aztec/foundation/log';
10
+ import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
10
11
  import type { Tuple } from '@aztec/foundation/serialize';
11
12
  import { Timer } from '@aztec/foundation/timer';
12
13
  import { RollupAbi } from '@aztec/l1-artifacts';
@@ -30,7 +31,7 @@ export type L1SubmitEpochProofArgs = {
30
31
  endTimestamp: Fr;
31
32
  outHash: Fr;
32
33
  proverId: Fr;
33
- fees: Tuple<FeeRecipient, typeof AZTEC_MAX_EPOCH_DURATION>;
34
+ fees: Tuple<FeeRecipient, typeof MAX_CHECKPOINTS_PER_EPOCH>;
34
35
  proof: Proof;
35
36
  };
36
37
 
@@ -38,7 +39,7 @@ export class ProverNodePublisher {
38
39
  private interrupted = false;
39
40
  private metrics: ProverNodePublisherMetrics;
40
41
 
41
- protected log = createLogger('prover-node:l1-tx-publisher');
42
+ protected log: Logger;
42
43
 
43
44
  protected rollupContract: RollupContract;
44
45
 
@@ -51,10 +52,12 @@ export class ProverNodePublisher {
51
52
  l1TxUtils: L1TxUtils;
52
53
  telemetry?: TelemetryClient;
53
54
  },
55
+ bindings?: LoggerBindings,
54
56
  ) {
55
57
  const telemetry = deps.telemetry ?? getTelemetryClient();
56
58
 
57
59
  this.metrics = new ProverNodePublisherMetrics(telemetry, 'ProverNode');
60
+ this.log = createLogger('prover-node:l1-tx-publisher', bindings);
58
61
 
59
62
  this.rollupContract = deps.rollupContract;
60
63
  this.l1TxUtils = deps.l1TxUtils;
@@ -104,6 +107,7 @@ export class ProverNodePublisher {
104
107
 
105
108
  const txReceipt = await this.sendSubmitEpochProofTx(args);
106
109
  if (!txReceipt) {
110
+ this.log.error(`Failed to mine submitEpochProof tx`, undefined, ctx);
107
111
  return false;
108
112
  }
109
113
 
@@ -136,7 +140,7 @@ export class ProverNodePublisher {
136
140
  }
137
141
 
138
142
  this.metrics.recordFailedTx();
139
- this.log.error(`Rollup.submitEpochProof tx status failed ${txReceipt.transactionHash}`, undefined, ctx);
143
+ this.log.error(`Rollup submitEpochProof tx reverted ${txReceipt.transactionHash}`, undefined, ctx);
140
144
  }
141
145
 
142
146
  this.log.verbose('Checkpoint data syncing interrupted', ctx);
@@ -170,17 +174,17 @@ export class ProverNodePublisher {
170
174
 
171
175
  // Check the archive for the immediate checkpoint before the epoch
172
176
  const checkpointLog = await this.rollupContract.getCheckpoint(CheckpointNumber(fromCheckpoint - 1));
173
- if (publicInputs.previousArchiveRoot.toString() !== checkpointLog.archive) {
177
+ if (!publicInputs.previousArchiveRoot.equals(checkpointLog.archive)) {
174
178
  throw new Error(
175
- `Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${checkpointLog.archive}`,
179
+ `Previous archive root mismatch: ${publicInputs.previousArchiveRoot.toString()} !== ${checkpointLog.archive.toString()}`,
176
180
  );
177
181
  }
178
182
 
179
183
  // Check the archive for the last checkpoint in the epoch
180
184
  const endCheckpointLog = await this.rollupContract.getCheckpoint(toCheckpoint);
181
- if (publicInputs.endArchiveRoot.toString() !== endCheckpointLog.archive) {
185
+ if (!publicInputs.endArchiveRoot.equals(endCheckpointLog.archive)) {
182
186
  throw new Error(
183
- `End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${endCheckpointLog.archive}`,
187
+ `End archive root mismatch: ${publicInputs.endArchiveRoot.toString()} !== ${endCheckpointLog.archive.toString()}`,
184
188
  );
185
189
  }
186
190
 
@@ -198,7 +202,7 @@ export class ProverNodePublisher {
198
202
  );
199
203
  const argsPublicInputs = [...publicInputs.toFields()];
200
204
 
201
- if (!areArraysEqual(rollupPublicInputs.map(Fr.fromHexString), argsPublicInputs, (a, b) => a.equals(b))) {
205
+ if (!areArraysEqual(rollupPublicInputs, argsPublicInputs, (a, b) => a.equals(b))) {
202
206
  const fmt = (inputs: Fr[] | readonly string[]) => inputs.map(x => x.toString()).join(', ');
203
207
  throw new Error(
204
208
  `Root rollup public inputs mismatch:\nRollup: ${fmt(rollupPublicInputs)}\nComputed:${fmt(argsPublicInputs)}`,
@@ -228,21 +232,24 @@ export class ProverNodePublisher {
228
232
  });
229
233
  try {
230
234
  const { receipt } = await this.l1TxUtils.sendAndMonitorTransaction({ to: this.rollupContract.address, data });
235
+ if (receipt.status !== 'success') {
236
+ const errorMsg = await this.l1TxUtils.tryGetErrorFromRevertedTx(
237
+ data,
238
+ {
239
+ args: [...txArgs],
240
+ functionName: 'submitEpochRootProof',
241
+ abi: RollupAbi,
242
+ address: this.rollupContract.address,
243
+ },
244
+ /*blobInputs*/ undefined,
245
+ /*stateOverride*/ [],
246
+ );
247
+ this.log.error(`Rollup submit epoch proof tx reverted with ${errorMsg ?? 'unknown error'}`);
248
+ return undefined;
249
+ }
231
250
  return receipt;
232
251
  } catch (err) {
233
252
  this.log.error(`Rollup submit epoch proof failed`, err);
234
- const errorMsg = await this.l1TxUtils.tryGetErrorFromRevertedTx(
235
- data,
236
- {
237
- args: [...txArgs],
238
- functionName: 'submitEpochRootProof',
239
- abi: RollupAbi,
240
- address: this.rollupContract.address,
241
- },
242
- /*blobInputs*/ undefined,
243
- /*stateOverride*/ [],
244
- );
245
- this.log.error(`Rollup submit epoch proof tx reverted. ${errorMsg}`);
246
253
  return undefined;
247
254
  }
248
255
  }
@@ -261,9 +268,10 @@ export class ProverNodePublisher {
261
268
  {
262
269
  previousArchive: args.publicInputs.previousArchiveRoot.toString(),
263
270
  endArchive: args.publicInputs.endArchiveRoot.toString(),
271
+ outHash: args.publicInputs.outHash.toString(),
264
272
  proverId: EthAddress.fromField(args.publicInputs.constants.proverId).toString(),
265
273
  } /*_args*/,
266
- makeTuple(AZTEC_MAX_EPOCH_DURATION * 2, i =>
274
+ makeTuple(MAX_CHECKPOINTS_PER_EPOCH * 2, i =>
267
275
  i % 2 === 0
268
276
  ? args.publicInputs.fees[i / 2].recipient.toField().toString()
269
277
  : args.publicInputs.fees[(i - 1) / 2].value.toString(),