@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.
- package/dest/actions/download-epoch-proving-job.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/config.d.ts +5 -4
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +4 -3
- package/dest/factory.d.ts +5 -4
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +28 -19
- 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 +2 -2
- package/dest/job/epoch-proving-job-data.d.ts.map +1 -1
- package/dest/job/epoch-proving-job-data.js +1 -1
- package/dest/job/epoch-proving-job.d.ts +3 -2
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +416 -29
- package/dest/metrics.d.ts +2 -2
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +26 -100
- package/dest/monitors/epoch-monitor.d.ts +1 -1
- package/dest/monitors/epoch-monitor.d.ts.map +1 -1
- package/dest/monitors/epoch-monitor.js +1 -10
- package/dest/prover-node-publisher.d.ts +9 -7
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +25 -20
- package/dest/prover-node.d.ts +3 -3
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +402 -24
- package/dest/prover-publisher-factory.d.ts +7 -3
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +4 -2
- package/package.json +23 -23
- package/src/actions/rerun-epoch-proving-job.ts +5 -3
- package/src/bin/run-failed-epoch.ts +1 -1
- package/src/config.ts +6 -4
- package/src/factory.ts +36 -22
- package/src/index.ts +1 -0
- package/src/job/epoch-proving-job-data.ts +1 -1
- package/src/job/epoch-proving-job.ts +45 -24
- package/src/metrics.ts +21 -84
- package/src/monitors/epoch-monitor.ts +1 -8
- package/src/prover-node-publisher.ts +33 -25
- package/src/prover-node.ts +7 -7
- 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
|
|
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 {
|
|
3
|
+
import { createBlobClientWithFileStores } from '@aztec/blob-client/client';
|
|
4
4
|
import { EpochCache } from '@aztec/epoch-cache';
|
|
5
|
-
import {
|
|
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 {
|
|
13
|
-
|
|
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
|
|
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, {
|
|
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
|
-
|
|
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
|
-
:
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
168
|
-
|
|
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,5 @@
|
|
|
1
1
|
import { CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
2
|
-
import { Fr } from '@aztec/foundation/
|
|
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/
|
|
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 {
|
|
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
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
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
|
|
365
|
-
const blockHashes = await Promise.all(
|
|
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 (
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
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
|
|
160
|
-
|
|
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 {
|
|
3
|
-
import type {
|
|
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 {
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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(
|
|
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(),
|