@aztec/prover-node 0.0.1-commit.b6e433891 → 0.0.1-commit.b9865e97
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.js +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 +105 -25
- package/dest/bin/run-failed-epoch.js +1 -3
- package/dest/factory.d.ts +1 -1
- package/dest/factory.d.ts.map +1 -1
- package/dest/factory.js +21 -2
- package/dest/job/epoch-proving-job.d.ts +6 -2
- package/dest/job/epoch-proving-job.d.ts.map +1 -1
- package/dest/job/epoch-proving-job.js +186 -36
- package/dest/metrics.d.ts +11 -1
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +22 -0
- package/dest/monitors/epoch-monitor.js +6 -2
- package/dest/prover-node-publisher.d.ts +20 -1
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +200 -5
- package/dest/prover-node.d.ts +6 -6
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +77 -32
- package/dest/prover-publisher-factory.d.ts +2 -2
- package/dest/prover-publisher-factory.d.ts.map +1 -1
- package/dest/prover-publisher-factory.js +3 -3
- package/package.json +23 -23
- package/src/actions/download-epoch-proving-job.ts +1 -1
- package/src/actions/rerun-epoch-proving-job.ts +16 -5
- package/src/bin/run-failed-epoch.ts +1 -2
- package/src/factory.ts +18 -2
- package/src/job/epoch-proving-job.ts +102 -36
- package/src/metrics.ts +37 -0
- package/src/monitors/epoch-monitor.ts +2 -2
- package/src/prover-node-publisher.ts +232 -9
- package/src/prover-node.ts +81 -44
- package/src/prover-publisher-factory.ts +3 -3
package/dest/prover-node.js
CHANGED
|
@@ -378,7 +378,7 @@ import { createLogger } from '@aztec/foundation/log';
|
|
|
378
378
|
import { DateProvider } from '@aztec/foundation/timer';
|
|
379
379
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
380
380
|
import { getProofSubmissionDeadlineTimestamp } from '@aztec/stdlib/epoch-helpers';
|
|
381
|
-
import {
|
|
381
|
+
import { tryStop } from '@aztec/stdlib/interfaces/server';
|
|
382
382
|
import { Attributes, getTelemetryClient, trackSpan } from '@aztec/telemetry-client';
|
|
383
383
|
import { uploadEpochProofFailure } from './actions/upload-epoch-proof-failure.js';
|
|
384
384
|
import { EpochProvingJob } from './job/epoch-proving-job.js';
|
|
@@ -430,6 +430,7 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
430
430
|
config;
|
|
431
431
|
jobMetrics;
|
|
432
432
|
rewardsMetrics;
|
|
433
|
+
startingProofEpochs;
|
|
433
434
|
tracer;
|
|
434
435
|
publisher;
|
|
435
436
|
constructor(prover, publisherFactory, l2BlockSource, l1ToL2MessageSource, contractDataSource, worldState, p2pClient, epochsMonitor, rollupContract, l1Metrics, config = {}, telemetryClient = getTelemetryClient(), delayer, dateProvider = new DateProvider()){
|
|
@@ -448,6 +449,7 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
448
449
|
this.dateProvider = dateProvider;
|
|
449
450
|
this.log = (_initProto(this), createLogger('prover-node'));
|
|
450
451
|
this.jobs = new Map();
|
|
452
|
+
this.startingProofEpochs = new Set();
|
|
451
453
|
this.config = {
|
|
452
454
|
proverNodePollingIntervalMs: 1_000,
|
|
453
455
|
proverNodeMaxPendingJobs: 100,
|
|
@@ -484,15 +486,7 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
484
486
|
this.log.debug(`Running jobs as ${epochNumber} is ready to prove`, {
|
|
485
487
|
jobs: Array.from(this.jobs.values()).map((job)=>`${job.getEpochNumber()}:${job.getId()}`)
|
|
486
488
|
});
|
|
487
|
-
|
|
488
|
-
if (activeJobs.length > 0) {
|
|
489
|
-
this.log.warn(`Not starting proof for ${epochNumber} since there are active jobs for the epoch`, {
|
|
490
|
-
activeJobs: activeJobs.map((job)=>job.uuid)
|
|
491
|
-
});
|
|
492
|
-
return true;
|
|
493
|
-
}
|
|
494
|
-
await this.startProof(epochNumber);
|
|
495
|
-
return true;
|
|
489
|
+
return await this.startProofIfNeeded(epochNumber);
|
|
496
490
|
} catch (err) {
|
|
497
491
|
if (err instanceof EmptyEpochError) {
|
|
498
492
|
this.log.info(`Not starting proof for ${epochNumber} since no blocks were found`);
|
|
@@ -519,10 +513,10 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
519
513
|
*/ async stop() {
|
|
520
514
|
this.log.info('Stopping ProverNode');
|
|
521
515
|
await this.epochsMonitor.stop();
|
|
522
|
-
await this.prover.stop();
|
|
523
|
-
await tryStop(this.publisherFactory);
|
|
524
516
|
this.publisher?.interrupt();
|
|
525
517
|
await Promise.all(Array.from(this.jobs.values()).map((job)=>job.stop()));
|
|
518
|
+
await this.prover.stop();
|
|
519
|
+
await tryStop(this.publisherFactory);
|
|
526
520
|
this.rewardsMetrics.stop();
|
|
527
521
|
this.l1Metrics.stop();
|
|
528
522
|
await this.telemetryClient.stop();
|
|
@@ -538,9 +532,35 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
538
532
|
/**
|
|
539
533
|
* Starts a proving process and returns immediately.
|
|
540
534
|
*/ async startProof(epochNumber) {
|
|
541
|
-
|
|
535
|
+
await this.startProofIfNeeded(epochNumber, {
|
|
542
536
|
skipEpochCheck: true
|
|
543
537
|
});
|
|
538
|
+
}
|
|
539
|
+
async startProofIfNeeded(epochNumber, opts = {}) {
|
|
540
|
+
if (this.startingProofEpochs.has(epochNumber)) {
|
|
541
|
+
this.log.warn(`Not starting proof for ${epochNumber} since a proof is already being started for the epoch`, {
|
|
542
|
+
epochNumber
|
|
543
|
+
});
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
this.startingProofEpochs.add(epochNumber);
|
|
547
|
+
try {
|
|
548
|
+
const activeJobs = await this.activeJobsCoverEpoch(epochNumber);
|
|
549
|
+
if (activeJobs.length > 0) {
|
|
550
|
+
this.log.warn(`Not starting proof for ${epochNumber} since an active job already covers the epoch`, {
|
|
551
|
+
epochNumber,
|
|
552
|
+
activeJobs
|
|
553
|
+
});
|
|
554
|
+
return true;
|
|
555
|
+
}
|
|
556
|
+
await this.startProofInternal(epochNumber, opts);
|
|
557
|
+
return true;
|
|
558
|
+
} finally{
|
|
559
|
+
this.startingProofEpochs.delete(epochNumber);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
async startProofInternal(epochNumber, opts = {}) {
|
|
563
|
+
const job = await this.createProvingJob(epochNumber, opts);
|
|
544
564
|
void this.runJob(job);
|
|
545
565
|
}
|
|
546
566
|
async runJob(job) {
|
|
@@ -582,15 +602,40 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
582
602
|
/**
|
|
583
603
|
* Returns an array of jobs being processed.
|
|
584
604
|
*/ getJobs() {
|
|
585
|
-
return Promise.resolve(
|
|
605
|
+
return Promise.resolve(this.getJobsInternal());
|
|
606
|
+
}
|
|
607
|
+
getJobsInternal() {
|
|
608
|
+
return Array.from(this.jobs.entries()).map(([uuid, job])=>({
|
|
586
609
|
uuid,
|
|
587
610
|
status: job.getState(),
|
|
588
611
|
epochNumber: job.getEpochNumber()
|
|
589
|
-
}))
|
|
612
|
+
}));
|
|
590
613
|
}
|
|
591
|
-
async
|
|
592
|
-
const
|
|
593
|
-
|
|
614
|
+
async activeJobsCoverEpoch(epochNumber) {
|
|
615
|
+
const checkpoints = await this.l2BlockSource.getCheckpointsData({
|
|
616
|
+
epoch: epochNumber
|
|
617
|
+
});
|
|
618
|
+
if (checkpoints.length === 0) {
|
|
619
|
+
return [];
|
|
620
|
+
}
|
|
621
|
+
const firstCheckpoint = checkpoints.at(0).checkpointNumber;
|
|
622
|
+
const latestCheckpoint = checkpoints.at(-1).checkpointNumber;
|
|
623
|
+
const jobs = [];
|
|
624
|
+
for (const job of this.jobs.values()){
|
|
625
|
+
if (job.getEpochNumber() !== epochNumber) {
|
|
626
|
+
continue;
|
|
627
|
+
}
|
|
628
|
+
const jobCheckpoints = job.getProvingData().checkpoints;
|
|
629
|
+
const checkpointOverlap = jobCheckpoints.at(0).number <= firstCheckpoint && jobCheckpoints.at(-1).number >= latestCheckpoint;
|
|
630
|
+
if (checkpointOverlap && ![
|
|
631
|
+
'failed',
|
|
632
|
+
'stopped',
|
|
633
|
+
'timed-out'
|
|
634
|
+
].includes(job.getState())) {
|
|
635
|
+
jobs.push(job.getId());
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
return jobs;
|
|
594
639
|
}
|
|
595
640
|
checkMaximumPendingJobs() {
|
|
596
641
|
const { proverNodeMaxPendingJobs: maxPendingJobs } = this.config;
|
|
@@ -625,7 +670,14 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
625
670
|
return this.l2BlockSource.getL1Constants();
|
|
626
671
|
}
|
|
627
672
|
async gatherEpochData(epochNumber) {
|
|
628
|
-
const
|
|
673
|
+
const publishedCheckpoints = await this.l2BlockSource.getCheckpoints({
|
|
674
|
+
epoch: epochNumber
|
|
675
|
+
});
|
|
676
|
+
if (publishedCheckpoints.length === 0) {
|
|
677
|
+
throw new EmptyEpochError(epochNumber);
|
|
678
|
+
}
|
|
679
|
+
const checkpoints = publishedCheckpoints.map((p)=>p.checkpoint);
|
|
680
|
+
const attestations = publishedCheckpoints.at(-1)?.attestations ?? [];
|
|
629
681
|
const txArray = await this.gatherTxs(epochNumber, checkpoints);
|
|
630
682
|
const txs = new Map(txArray.map((tx)=>[
|
|
631
683
|
tx.getTxHash().toString(),
|
|
@@ -634,8 +686,6 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
634
686
|
const l1ToL2Messages = await this.gatherMessages(epochNumber, checkpoints);
|
|
635
687
|
const [firstBlock] = checkpoints[0].blocks;
|
|
636
688
|
const previousBlockHeader = await this.gatherPreviousBlockHeader(epochNumber, firstBlock.number - 1);
|
|
637
|
-
const [lastPublishedCheckpoint] = await this.l2BlockSource.getCheckpoints(checkpoints.at(-1).number, 1);
|
|
638
|
-
const attestations = lastPublishedCheckpoint?.attestations ?? [];
|
|
639
689
|
return {
|
|
640
690
|
checkpoints,
|
|
641
691
|
txs,
|
|
@@ -645,13 +695,6 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
645
695
|
attestations
|
|
646
696
|
};
|
|
647
697
|
}
|
|
648
|
-
async gatherCheckpoints(epochNumber) {
|
|
649
|
-
const checkpoints = await this.l2BlockSource.getCheckpointsForEpoch(epochNumber);
|
|
650
|
-
if (checkpoints.length === 0) {
|
|
651
|
-
throw new EmptyEpochError(epochNumber);
|
|
652
|
-
}
|
|
653
|
-
return checkpoints;
|
|
654
|
-
}
|
|
655
698
|
async gatherTxs(epochNumber, checkpoints) {
|
|
656
699
|
const deadline = new Date(this.dateProvider.now() + this.config.txGatheringTimeoutMs);
|
|
657
700
|
const txProvider = this.p2pClient.getTxProvider();
|
|
@@ -682,12 +725,14 @@ _dec = trackSpan('ProverNode.createProvingJob', (epochNumber)=>({
|
|
|
682
725
|
return messagesByCheckpoint;
|
|
683
726
|
}
|
|
684
727
|
async gatherPreviousBlockHeader(epochNumber, previousBlockNumber) {
|
|
685
|
-
const
|
|
686
|
-
|
|
728
|
+
const data = await this.l2BlockSource.getBlockData({
|
|
729
|
+
number: BlockNumber(previousBlockNumber)
|
|
730
|
+
});
|
|
731
|
+
if (!data?.header) {
|
|
687
732
|
throw new Error(`Previous block header ${previousBlockNumber} not found for proving epoch ${epochNumber}`);
|
|
688
733
|
}
|
|
689
|
-
this.log.verbose(`Gathered previous block header ${header.getBlockNumber()} for epoch ${epochNumber}`);
|
|
690
|
-
return header;
|
|
734
|
+
this.log.verbose(`Gathered previous block header ${data.header.getBlockNumber()} for epoch ${epochNumber}`);
|
|
735
|
+
return data.header;
|
|
691
736
|
}
|
|
692
737
|
/** Extracted for testing purposes. */ doCreateEpochProvingJob(data, deadline, publicProcessorFactory, publisher, opts = {}) {
|
|
693
738
|
const { proverNodeMaxParallelBlocksPerEpoch: parallelBlockLimit, proverNodeDisableProofPublish } = this.config;
|
|
@@ -15,11 +15,11 @@ export declare class ProverPublisherFactory {
|
|
|
15
15
|
telemetry?: TelemetryClient;
|
|
16
16
|
}, bindings?: LoggerBindings | undefined);
|
|
17
17
|
start(): Promise<void>;
|
|
18
|
-
stop(): void
|
|
18
|
+
stop(): Promise<void>;
|
|
19
19
|
/**
|
|
20
20
|
* Creates a new Prover Publisher instance.
|
|
21
21
|
* @returns A new ProverNodePublisher instance.
|
|
22
22
|
*/
|
|
23
23
|
create(): Promise<ProverNodePublisher>;
|
|
24
24
|
}
|
|
25
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmVyLXB1Ymxpc2hlci1mYWN0b3J5LmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvcHJvdmVyLXB1Ymxpc2hlci1mYWN0b3J5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxFQUFFLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ2hFLE9BQU8sS0FBSyxFQUFFLFNBQVMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzdELE9BQU8sS0FBSyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDMUUsT0FBTyxLQUFLLEVBQUUsY0FBYyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDNUQsT0FBTyxLQUFLLEVBQUUscUJBQXFCLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUMzRixPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUUvRCxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVqRSxxQkFBYSxzQkFBc0I7SUFFL0IsT0FBTyxDQUFDLE1BQU07SUFDZCxPQUFPLENBQUMsSUFBSTtJQUtaLE9BQU8sQ0FBQyxRQUFRLENBQUM7SUFQbkIsWUFDVSxNQUFNLEVBQUUsb0JBQW9CLEdBQUcscUJBQXFCLEVBQ3BELElBQUksRUFBRTtRQUNaLGNBQWMsRUFBRSxjQUFjLENBQUM7UUFDL0IsZ0JBQWdCLEVBQUUsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDOUMsU0FBUyxDQUFDLEVBQUUsZUFBZSxDQUFDO0tBQzdCLEVBQ08sUUFBUSxDQUFDLDRCQUFnQixFQUMvQjtJQUVTLEtBQUssa0JBRWpCO0lBRVksSUFBSSxrQkFFaEI7SUFFRDs7O09BR0c7SUFDVSxNQUFNLElBQUksT0FBTyxDQUFDLG1CQUFtQixDQUFDLENBV2xEO0NBQ0YifQ==
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prover-publisher-factory.d.ts","sourceRoot":"","sources":["../src/prover-publisher-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,QAAQ,CAAC;IAPnB,YACU,MAAM,EAAE,oBAAoB,GAAG,qBAAqB,EACpD,IAAI,EAAE;QACZ,cAAc,EAAE,cAAc,CAAC;QAC/B,gBAAgB,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC9C,SAAS,CAAC,EAAE,eAAe,CAAC;KAC7B,EACO,QAAQ,CAAC,4BAAgB,EAC/B;IAES,KAAK,kBAEjB;
|
|
1
|
+
{"version":3,"file":"prover-publisher-factory.d.ts","sourceRoot":"","sources":["../src/prover-publisher-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAC3F,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEjE,qBAAa,sBAAsB;IAE/B,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,IAAI;IAKZ,OAAO,CAAC,QAAQ,CAAC;IAPnB,YACU,MAAM,EAAE,oBAAoB,GAAG,qBAAqB,EACpD,IAAI,EAAE;QACZ,cAAc,EAAE,cAAc,CAAC;QAC/B,gBAAgB,EAAE,gBAAgB,CAAC,SAAS,CAAC,CAAC;QAC9C,SAAS,CAAC,EAAE,eAAe,CAAC;KAC7B,EACO,QAAQ,CAAC,4BAAgB,EAC/B;IAES,KAAK,kBAEjB;IAEY,IAAI,kBAEhB;IAED;;;OAGG;IACU,MAAM,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAWlD;CACF"}
|
|
@@ -9,10 +9,10 @@ export class ProverPublisherFactory {
|
|
|
9
9
|
this.bindings = bindings;
|
|
10
10
|
}
|
|
11
11
|
async start() {
|
|
12
|
-
await this.deps.publisherManager.
|
|
12
|
+
await this.deps.publisherManager.start();
|
|
13
13
|
}
|
|
14
|
-
stop() {
|
|
15
|
-
this.deps.publisherManager.
|
|
14
|
+
async stop() {
|
|
15
|
+
await this.deps.publisherManager.stop();
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Creates a new Prover Publisher instance.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/prover-node",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.b9865e97",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dest/index.js",
|
|
@@ -56,28 +56,28 @@
|
|
|
56
56
|
]
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@aztec/archiver": "0.0.1-commit.
|
|
60
|
-
"@aztec/bb-prover": "0.0.1-commit.
|
|
61
|
-
"@aztec/blob-client": "0.0.1-commit.
|
|
62
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
63
|
-
"@aztec/constants": "0.0.1-commit.
|
|
64
|
-
"@aztec/epoch-cache": "0.0.1-commit.
|
|
65
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
66
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
67
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
68
|
-
"@aztec/l1-artifacts": "0.0.1-commit.
|
|
69
|
-
"@aztec/native": "0.0.1-commit.
|
|
70
|
-
"@aztec/node-keystore": "0.0.1-commit.
|
|
71
|
-
"@aztec/node-lib": "0.0.1-commit.
|
|
72
|
-
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.
|
|
73
|
-
"@aztec/p2p": "0.0.1-commit.
|
|
74
|
-
"@aztec/protocol-contracts": "0.0.1-commit.
|
|
75
|
-
"@aztec/prover-client": "0.0.1-commit.
|
|
76
|
-
"@aztec/sequencer-client": "0.0.1-commit.
|
|
77
|
-
"@aztec/simulator": "0.0.1-commit.
|
|
78
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
79
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
80
|
-
"@aztec/world-state": "0.0.1-commit.
|
|
59
|
+
"@aztec/archiver": "0.0.1-commit.b9865e97",
|
|
60
|
+
"@aztec/bb-prover": "0.0.1-commit.b9865e97",
|
|
61
|
+
"@aztec/blob-client": "0.0.1-commit.b9865e97",
|
|
62
|
+
"@aztec/blob-lib": "0.0.1-commit.b9865e97",
|
|
63
|
+
"@aztec/constants": "0.0.1-commit.b9865e97",
|
|
64
|
+
"@aztec/epoch-cache": "0.0.1-commit.b9865e97",
|
|
65
|
+
"@aztec/ethereum": "0.0.1-commit.b9865e97",
|
|
66
|
+
"@aztec/foundation": "0.0.1-commit.b9865e97",
|
|
67
|
+
"@aztec/kv-store": "0.0.1-commit.b9865e97",
|
|
68
|
+
"@aztec/l1-artifacts": "0.0.1-commit.b9865e97",
|
|
69
|
+
"@aztec/native": "0.0.1-commit.b9865e97",
|
|
70
|
+
"@aztec/node-keystore": "0.0.1-commit.b9865e97",
|
|
71
|
+
"@aztec/node-lib": "0.0.1-commit.b9865e97",
|
|
72
|
+
"@aztec/noir-protocol-circuits-types": "0.0.1-commit.b9865e97",
|
|
73
|
+
"@aztec/p2p": "0.0.1-commit.b9865e97",
|
|
74
|
+
"@aztec/protocol-contracts": "0.0.1-commit.b9865e97",
|
|
75
|
+
"@aztec/prover-client": "0.0.1-commit.b9865e97",
|
|
76
|
+
"@aztec/sequencer-client": "0.0.1-commit.b9865e97",
|
|
77
|
+
"@aztec/simulator": "0.0.1-commit.b9865e97",
|
|
78
|
+
"@aztec/stdlib": "0.0.1-commit.b9865e97",
|
|
79
|
+
"@aztec/telemetry-client": "0.0.1-commit.b9865e97",
|
|
80
|
+
"@aztec/world-state": "0.0.1-commit.b9865e97",
|
|
81
81
|
"source-map-support": "^0.5.21",
|
|
82
82
|
"tslib": "^2.4.0",
|
|
83
83
|
"viem": "npm:@aztec/viem@2.38.2"
|
|
@@ -30,7 +30,7 @@ export async function downloadEpochProvingJob(
|
|
|
30
30
|
|
|
31
31
|
const dataUrls = makeSnapshotPaths(location);
|
|
32
32
|
log.info(`Downloading state snapshot from ${location} to local data directory`, { metadata, dataUrls });
|
|
33
|
-
await snapshotSync({ dataUrls }, log, { ...config, ...metadata,
|
|
33
|
+
await snapshotSync({ dataUrls }, log, { ...config, ...metadata, fileStore });
|
|
34
34
|
|
|
35
35
|
const dataPath = urlJoin(location, 'data.bin');
|
|
36
36
|
const localPath = config.jobDataDownloadPath;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { createArchiverStore } from '@aztec/archiver';
|
|
1
|
+
import { createArchiverStore, createContractDataSource } from '@aztec/archiver';
|
|
2
2
|
import type { L1ContractsConfig } from '@aztec/ethereum/config';
|
|
3
3
|
import type { Logger } from '@aztec/foundation/log';
|
|
4
4
|
import { type ProverClientConfig, createProverClient } from '@aztec/prover-client';
|
|
5
5
|
import { ProverBrokerConfig, createAndStartProvingBroker } from '@aztec/prover-client/broker';
|
|
6
6
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
7
7
|
import type { DataStoreConfig } from '@aztec/stdlib/kv-store';
|
|
8
|
+
import type { GenesisData } from '@aztec/stdlib/world-state';
|
|
8
9
|
import { getTelemetryClient } from '@aztec/telemetry-client';
|
|
9
10
|
import { createWorldState } from '@aztec/world-state';
|
|
10
11
|
|
|
@@ -23,17 +24,27 @@ export async function rerunEpochProvingJob(
|
|
|
23
24
|
localPath: string,
|
|
24
25
|
log: Logger,
|
|
25
26
|
config: DataStoreConfig & ProverBrokerConfig & ProverClientConfig & Pick<L1ContractsConfig, 'aztecEpochDuration'>,
|
|
27
|
+
genesis?: GenesisData,
|
|
26
28
|
) {
|
|
27
29
|
const jobData = deserializeEpochProvingJobData(readFileSync(localPath));
|
|
28
30
|
log.info(`Loaded proving job data for epoch ${jobData.epochNumber}`);
|
|
29
31
|
|
|
30
32
|
const telemetry = getTelemetryClient();
|
|
31
33
|
const metrics = new ProverNodeJobMetrics(telemetry.getMeter('prover-job'), telemetry.getTracer('prover-job'));
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
const
|
|
34
|
+
await using worldState = await createWorldState(config, genesis);
|
|
35
|
+
const initialBlockHash = await worldState.getInitialHeader().hash();
|
|
36
|
+
const archiver = await createArchiverStore(config, initialBlockHash);
|
|
37
|
+
const publicProcessorFactory = new PublicProcessorFactory(
|
|
38
|
+
createContractDataSource(archiver),
|
|
39
|
+
undefined,
|
|
40
|
+
undefined,
|
|
41
|
+
log.getBindings(),
|
|
42
|
+
);
|
|
35
43
|
|
|
36
|
-
const publisher = {
|
|
44
|
+
const publisher = {
|
|
45
|
+
submitEpochProof: () => Promise.resolve(true),
|
|
46
|
+
analyzeEpochProofSubmission: () => Promise.resolve(),
|
|
47
|
+
};
|
|
37
48
|
const l2BlockSourceForReorgDetection = undefined;
|
|
38
49
|
const deadline = undefined;
|
|
39
50
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-console */
|
|
2
2
|
import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
|
|
3
|
-
import type { L1ContractAddresses } from '@aztec/ethereum/l1-contract-addresses';
|
|
4
3
|
import { EthAddress } from '@aztec/foundation/eth-address';
|
|
5
4
|
import { jsonParseWithSchema, jsonStringify } from '@aztec/foundation/json-rpc';
|
|
6
5
|
import { createLogger } from '@aztec/foundation/log';
|
|
@@ -50,7 +49,7 @@ async function rerunFailedEpoch(provingJobUrl: string, baseLocalDir: string) {
|
|
|
50
49
|
logger.info(`Rerunning proving job from ${jobPath} with state from ${dataDir}`, metadata);
|
|
51
50
|
const result = await rerunEpochProvingJob(jobPath, logger, {
|
|
52
51
|
...config,
|
|
53
|
-
|
|
52
|
+
rollupAddress: metadata.rollupAddress,
|
|
54
53
|
rollupVersion: metadata.rollupVersion,
|
|
55
54
|
});
|
|
56
55
|
|
package/src/factory.ts
CHANGED
|
@@ -100,7 +100,7 @@ export async function createProverNode(
|
|
|
100
100
|
pollingInterval: config.viemPollingIntervalMS,
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
const rollupContract = new RollupContract(publicClient, config.
|
|
103
|
+
const rollupContract = new RollupContract(publicClient, config.rollupAddress.toString());
|
|
104
104
|
|
|
105
105
|
const l1TxUtils = deps.l1TxUtils
|
|
106
106
|
? [deps.l1TxUtils]
|
|
@@ -119,11 +119,27 @@ export async function createProverNode(
|
|
|
119
119
|
{ telemetry, logger: log.createChild('l1-tx-utils'), dateProvider },
|
|
120
120
|
);
|
|
121
121
|
|
|
122
|
+
// Create a funder L1TxUtils from the keystore funding account (if configured)
|
|
123
|
+
const fundingSigner = keyStoreManager?.createFundingSigner();
|
|
124
|
+
let funderL1TxUtils: L1TxUtils | undefined;
|
|
125
|
+
if (fundingSigner) {
|
|
126
|
+
const [funder] = await createL1TxUtilsFromSigners(
|
|
127
|
+
publicClient,
|
|
128
|
+
[fundingSigner],
|
|
129
|
+
{ ...config, scope: 'prover' },
|
|
130
|
+
{ telemetry, logger: log.createChild('l1-tx-utils:funder'), dateProvider },
|
|
131
|
+
);
|
|
132
|
+
funderL1TxUtils = funder;
|
|
133
|
+
}
|
|
134
|
+
|
|
122
135
|
const publisherFactory =
|
|
123
136
|
deps.publisherFactory ??
|
|
124
137
|
new ProverPublisherFactory(config, {
|
|
125
138
|
rollupContract,
|
|
126
|
-
publisherManager: new PublisherManager(l1TxUtils, getPublisherConfigFromProverConfig(config),
|
|
139
|
+
publisherManager: new PublisherManager(l1TxUtils, getPublisherConfigFromProverConfig(config), {
|
|
140
|
+
bindings: log.getBindings(),
|
|
141
|
+
funder: funderL1TxUtils,
|
|
142
|
+
}),
|
|
127
143
|
telemetry,
|
|
128
144
|
});
|
|
129
145
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP } from '@aztec/constants';
|
|
2
1
|
import { asyncPool } from '@aztec/foundation/async-pool';
|
|
3
2
|
import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
4
|
-
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
5
3
|
import { Fr } from '@aztec/foundation/curves/bn254';
|
|
6
4
|
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
7
5
|
import { RunningPromise, promiseWithResolvers } from '@aztec/foundation/promise';
|
|
@@ -20,8 +18,8 @@ import {
|
|
|
20
18
|
EpochProvingJobTerminalState,
|
|
21
19
|
type ForkMerkleTreeOperations,
|
|
22
20
|
} from '@aztec/stdlib/interfaces/server';
|
|
21
|
+
import { appendL1ToL2MessagesToTree } from '@aztec/stdlib/messaging';
|
|
23
22
|
import { CheckpointConstantData } from '@aztec/stdlib/rollup';
|
|
24
|
-
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
25
23
|
import type { ProcessedTx, Tx } from '@aztec/stdlib/tx';
|
|
26
24
|
import { Attributes, type Traceable, type Tracer, trackSpan } from '@aztec/telemetry-client';
|
|
27
25
|
|
|
@@ -48,6 +46,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
48
46
|
private uuid: string;
|
|
49
47
|
|
|
50
48
|
private runPromise: Promise<void> | undefined;
|
|
49
|
+
private abortController = new AbortController();
|
|
51
50
|
private epochCheckPromise: RunningPromise | undefined;
|
|
52
51
|
private deadlineTimeoutHandler: NodeJS.Timeout | undefined;
|
|
53
52
|
|
|
@@ -58,7 +57,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
58
57
|
private dbProvider: Pick<ForkMerkleTreeOperations, 'fork'>,
|
|
59
58
|
private prover: EpochProver,
|
|
60
59
|
private publicProcessorFactory: PublicProcessorFactory,
|
|
61
|
-
private publisher: Pick<ProverNodePublisher, 'submitEpochProof'>,
|
|
60
|
+
private publisher: Pick<ProverNodePublisher, 'submitEpochProof' | 'analyzeEpochProofSubmission'>,
|
|
62
61
|
private l2BlockSource: L2BlockSource | undefined,
|
|
63
62
|
private metrics: ProverNodeJobMetrics,
|
|
64
63
|
private deadline: Date | undefined,
|
|
@@ -172,7 +171,7 @@ export class EpochProvingJob implements Traceable {
|
|
|
172
171
|
? AVM_MAX_CONCURRENT_SIMULATIONS
|
|
173
172
|
: this.checkpoints.length;
|
|
174
173
|
|
|
175
|
-
await
|
|
174
|
+
await this.processCheckpoints(parallelism, async checkpoint => {
|
|
176
175
|
this.checkState();
|
|
177
176
|
const checkpointTimer = new Timer();
|
|
178
177
|
|
|
@@ -191,11 +190,12 @@ export class EpochProvingJob implements Traceable {
|
|
|
191
190
|
const previousHeader = previousBlockHeaders[checkpointIndex];
|
|
192
191
|
const l1ToL2Messages = this.getL1ToL2Messages(checkpoint);
|
|
193
192
|
|
|
194
|
-
this.log.
|
|
193
|
+
this.log.debug(`Starting processing checkpoint ${checkpoint.number}`, {
|
|
195
194
|
number: checkpoint.number,
|
|
196
195
|
checkpointHash: checkpoint.hash().toString(),
|
|
197
|
-
|
|
198
|
-
|
|
196
|
+
headerHash: checkpoint.header.hash().toString(),
|
|
197
|
+
numL1ToL2Messages: l1ToL2Messages.length,
|
|
198
|
+
previousBlockNumber: previousHeader.globalVariables.blockNumber,
|
|
199
199
|
uuid: this.uuid,
|
|
200
200
|
});
|
|
201
201
|
|
|
@@ -229,22 +229,26 @@ export class EpochProvingJob implements Traceable {
|
|
|
229
229
|
|
|
230
230
|
// Process public fns. L1 to L2 messages are only inserted for the first block of a checkpoint,
|
|
231
231
|
// as the fork for subsequent blocks already includes them from the previous block's synced state.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
232
|
+
{
|
|
233
|
+
await using db = await this.createFork(
|
|
234
|
+
BlockNumber(block.number - 1),
|
|
235
|
+
blockIndex === 0 ? l1ToL2Messages : undefined,
|
|
236
|
+
);
|
|
237
|
+
this.checkState();
|
|
238
|
+
const config = PublicSimulatorConfig.from({
|
|
239
|
+
proverId: this.prover.getProverId().toField(),
|
|
240
|
+
skipFeeEnforcement: false,
|
|
241
|
+
collectDebugLogs: false,
|
|
242
|
+
collectHints: true,
|
|
243
|
+
collectPublicInputs: true,
|
|
244
|
+
collectStatistics: false,
|
|
245
|
+
});
|
|
246
|
+
const publicProcessor = this.publicProcessorFactory.create(db, globalVariables, config);
|
|
247
|
+
const processed = await this.processTxs(publicProcessor, txs);
|
|
248
|
+
this.checkState();
|
|
249
|
+
await this.prover.addTxs(processed);
|
|
250
|
+
}
|
|
251
|
+
this.checkState();
|
|
248
252
|
this.log.verbose(`Processed all ${txs.length} txs for block ${block.number}`, {
|
|
249
253
|
blockNumber: block.number,
|
|
250
254
|
blockHash: (await block.hash()).toString(),
|
|
@@ -270,8 +274,21 @@ export class EpochProvingJob implements Traceable {
|
|
|
270
274
|
|
|
271
275
|
if (this.config.skipSubmitProof) {
|
|
272
276
|
this.log.info(
|
|
273
|
-
`Proof publishing is disabled.
|
|
277
|
+
`Proof publishing is disabled. Analyzing estimated L1 fees for epoch ${epochNumber} (checkpoints ${fromCheckpoint} to ${toCheckpoint})`,
|
|
274
278
|
);
|
|
279
|
+
try {
|
|
280
|
+
await this.publisher.analyzeEpochProofSubmission({
|
|
281
|
+
fromCheckpoint,
|
|
282
|
+
toCheckpoint,
|
|
283
|
+
epochNumber,
|
|
284
|
+
publicInputs,
|
|
285
|
+
proof,
|
|
286
|
+
batchedBlobInputs,
|
|
287
|
+
attestations,
|
|
288
|
+
});
|
|
289
|
+
} catch (err) {
|
|
290
|
+
this.log.warn(`Failed to analyze estimated L1 fees for epoch ${epochNumber}`, err);
|
|
291
|
+
}
|
|
275
292
|
this.state = 'completed';
|
|
276
293
|
this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeCheckpoints, epochSizeBlocks, epochSizeTxs);
|
|
277
294
|
return;
|
|
@@ -325,25 +342,56 @@ export class EpochProvingJob implements Traceable {
|
|
|
325
342
|
*/
|
|
326
343
|
private async createFork(blockNumber: BlockNumber, l1ToL2Messages: Fr[] | undefined) {
|
|
327
344
|
this.log.verbose(`Creating fork at ${blockNumber}`, { blockNumber });
|
|
328
|
-
|
|
345
|
+
// temporary stack to control fork lifetime
|
|
346
|
+
await using cleanup = new AsyncDisposableStack();
|
|
347
|
+
const db = cleanup.use(await this.dbProvider.fork(blockNumber));
|
|
329
348
|
|
|
330
349
|
if (l1ToL2Messages !== undefined) {
|
|
331
350
|
this.log.verbose(`Inserting ${l1ToL2Messages.length} L1 to L2 messages in fork`, {
|
|
332
351
|
blockNumber,
|
|
333
352
|
l1ToL2Messages: l1ToL2Messages.map(m => m.toString()),
|
|
334
353
|
});
|
|
335
|
-
|
|
336
|
-
l1ToL2Messages,
|
|
337
|
-
Fr.ZERO,
|
|
338
|
-
NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP,
|
|
339
|
-
'Too many L1 to L2 messages',
|
|
340
|
-
);
|
|
341
|
-
await db.appendLeaves(MerkleTreeId.L1_TO_L2_MESSAGE_TREE, l1ToL2MessagesPadded);
|
|
354
|
+
await appendL1ToL2MessagesToTree(db, l1ToL2Messages);
|
|
342
355
|
}
|
|
343
356
|
|
|
357
|
+
// everything run succesfully so we can release this stack and give control of the fork's lifetime to the caller
|
|
358
|
+
cleanup.move();
|
|
344
359
|
return db;
|
|
345
360
|
}
|
|
346
361
|
|
|
362
|
+
private async processCheckpoints(
|
|
363
|
+
parallelism: number,
|
|
364
|
+
processCheckpoint: (checkpoint: Checkpoint) => Promise<void>,
|
|
365
|
+
): Promise<void> {
|
|
366
|
+
let hasError = false;
|
|
367
|
+
let firstError: unknown;
|
|
368
|
+
|
|
369
|
+
await asyncPool(Math.max(parallelism, 1), this.checkpoints, async checkpoint => {
|
|
370
|
+
if (hasError || this.abortController.signal.aborted) {
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
try {
|
|
375
|
+
this.checkState();
|
|
376
|
+
await processCheckpoint(checkpoint);
|
|
377
|
+
} catch (err) {
|
|
378
|
+
if (!hasError) {
|
|
379
|
+
hasError = true;
|
|
380
|
+
firstError = err;
|
|
381
|
+
this.failProcessing();
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
if (hasError) {
|
|
387
|
+
throw firstError;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
if (this.abortController.signal.aborted) {
|
|
391
|
+
this.checkState();
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
347
395
|
private progressState(state: EpochProvingJobState) {
|
|
348
396
|
this.checkState();
|
|
349
397
|
this.state = state;
|
|
@@ -357,12 +405,24 @@ export class EpochProvingJob implements Traceable {
|
|
|
357
405
|
|
|
358
406
|
public async stop(state: EpochProvingJobTerminalState = 'stopped') {
|
|
359
407
|
this.state = state;
|
|
360
|
-
this.
|
|
408
|
+
this.interruptProcessing();
|
|
361
409
|
if (this.runPromise) {
|
|
362
410
|
await this.runPromise;
|
|
363
411
|
}
|
|
364
412
|
}
|
|
365
413
|
|
|
414
|
+
private failProcessing() {
|
|
415
|
+
if (!EpochProvingJobTerminalState.includes(this.state)) {
|
|
416
|
+
this.state = 'failed';
|
|
417
|
+
}
|
|
418
|
+
this.interruptProcessing();
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
private interruptProcessing() {
|
|
422
|
+
this.abortController.abort();
|
|
423
|
+
this.prover.cancel();
|
|
424
|
+
}
|
|
425
|
+
|
|
366
426
|
private scheduleDeadlineStop() {
|
|
367
427
|
const deadline = this.deadline;
|
|
368
428
|
if (deadline) {
|
|
@@ -397,7 +457,9 @@ export class EpochProvingJob implements Traceable {
|
|
|
397
457
|
const intervalMs = Math.ceil((await l2BlockSource.getL1Constants()).ethereumSlotDuration / 2) * 1000;
|
|
398
458
|
this.epochCheckPromise = new RunningPromise(
|
|
399
459
|
async () => {
|
|
400
|
-
const blockHeaders =
|
|
460
|
+
const blockHeaders = (
|
|
461
|
+
await l2BlockSource.getBlocksData({ epoch: this.epochNumber, onlyCheckpointed: true })
|
|
462
|
+
).map(d => d.header);
|
|
401
463
|
const blockHashes = await Promise.all(blockHeaders.map(header => header.hash()));
|
|
402
464
|
const thisBlocks = this.checkpoints.flatMap(checkpoint => checkpoint.blocks);
|
|
403
465
|
const thisBlockHashes = await Promise.all(thisBlocks.map(block => block.hash()));
|
|
@@ -436,7 +498,11 @@ export class EpochProvingJob implements Traceable {
|
|
|
436
498
|
|
|
437
499
|
private async processTxs(publicProcessor: PublicProcessor, txs: Tx[]): Promise<ProcessedTx[]> {
|
|
438
500
|
const { deadline } = this;
|
|
439
|
-
const [processedTxs, failedTxs] = await publicProcessor.process(txs, {
|
|
501
|
+
const [processedTxs, failedTxs] = await publicProcessor.process(txs, {
|
|
502
|
+
deadline,
|
|
503
|
+
signal: this.abortController.signal,
|
|
504
|
+
});
|
|
505
|
+
this.checkState();
|
|
440
506
|
|
|
441
507
|
if (failedTxs.length) {
|
|
442
508
|
const failedTxHashes = await Promise.all(failedTxs.map(({ tx }) => tx.getTxHash()));
|