@aztec/prover-node 5.0.0-rc.1 → 5.0.0
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/README.md +73 -68
- package/dest/actions/rerun-epoch-proving-job.d.ts +2 -2
- package/dest/actions/rerun-epoch-proving-job.d.ts.map +1 -1
- package/dest/checkpoint-store.d.ts +42 -37
- package/dest/checkpoint-store.d.ts.map +1 -1
- package/dest/checkpoint-store.js +65 -77
- package/dest/job/checkpoint-prover.d.ts +6 -16
- package/dest/job/checkpoint-prover.d.ts.map +1 -1
- package/dest/job/checkpoint-prover.js +15 -35
- package/dest/job/epoch-session.d.ts +2 -2
- package/dest/job/epoch-session.d.ts.map +1 -1
- package/dest/job/epoch-session.js +20 -9
- package/dest/metrics.d.ts +7 -4
- package/dest/metrics.d.ts.map +1 -1
- package/dest/metrics.js +14 -6
- package/dest/proof-publishing-service.d.ts +4 -2
- package/dest/proof-publishing-service.d.ts.map +1 -1
- package/dest/proof-publishing-service.js +1 -0
- package/dest/prover-node-publisher.d.ts +5 -5
- package/dest/prover-node-publisher.d.ts.map +1 -1
- package/dest/prover-node-publisher.js +2 -3
- package/dest/prover-node.d.ts +25 -15
- package/dest/prover-node.d.ts.map +1 -1
- package/dest/prover-node.js +152 -51
- package/dest/session-manager.d.ts +2 -2
- package/dest/session-manager.d.ts.map +1 -1
- package/dest/session-manager.js +38 -8
- package/package.json +23 -23
- package/src/checkpoint-store.ts +66 -85
- package/src/job/checkpoint-prover.ts +17 -40
- package/src/job/epoch-session.ts +21 -9
- package/src/metrics.ts +15 -12
- package/src/proof-publishing-service.ts +4 -1
- package/src/prover-node-publisher.ts +11 -10
- package/src/prover-node.ts +170 -60
- package/src/session-manager.ts +38 -7
package/dest/prover-node.js
CHANGED
|
@@ -371,15 +371,16 @@ function _apply_decs_2203_r(targetClass, memberDecs, classDecs, parentClass) {
|
|
|
371
371
|
return (_apply_decs_2203_r = applyDecs2203RFactory())(targetClass, memberDecs, classDecs, parentClass);
|
|
372
372
|
}
|
|
373
373
|
var _initProto;
|
|
374
|
-
import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
374
|
+
import { BlockNumber, CheckpointNumber, EpochNumber } from '@aztec/foundation/branded-types';
|
|
375
375
|
import { assertRequired, compact, pick } from '@aztec/foundation/collection';
|
|
376
376
|
import { memoize } from '@aztec/foundation/decorators';
|
|
377
377
|
import { createLogger } from '@aztec/foundation/log';
|
|
378
|
+
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
378
379
|
import { DateProvider, executeTimeout } from '@aztec/foundation/timer';
|
|
379
380
|
import { getLastSiblingPath } from '@aztec/prover-client/helpers';
|
|
380
381
|
import { ChonkCache } from '@aztec/prover-client/orchestrator';
|
|
381
382
|
import { PublicProcessorFactory } from '@aztec/simulator/server';
|
|
382
|
-
import {
|
|
383
|
+
import { EventDrivenL2BlockStream, L2TipsMemoryStore } from '@aztec/stdlib/block';
|
|
383
384
|
import { getEpochAtSlot, getProofSubmissionDeadlineEpoch } from '@aztec/stdlib/epoch-helpers';
|
|
384
385
|
import { EpochProvingJobTerminalState, tryStop } from '@aztec/stdlib/interfaces/server';
|
|
385
386
|
import { MerkleTreeId } from '@aztec/stdlib/trees';
|
|
@@ -440,6 +441,13 @@ import { SessionManager } from './session-manager.js';
|
|
|
440
441
|
* event by comparing the archiver's latest synced L2 slot against each epoch's
|
|
441
442
|
* submission deadline. Protected so tests can verify the start() seeding.
|
|
442
443
|
*/ lastExpiredEpoch;
|
|
444
|
+
/**
|
|
445
|
+
* Highest checkpoint number whose proving-side handling has completed (or that was legitimately skipped).
|
|
446
|
+
* The catch-up loop walks from here to each `chain-checkpointed` tip event. Seeded at start() from the last
|
|
447
|
+
* checkpoint of the last fully-proven epoch (or 0), so a restart reprocesses the partially-proven epoch rather
|
|
448
|
+
* than trusting a checkpointed tip that may sit ahead of unproven checkpoints. Clamped down on a prune.
|
|
449
|
+
*/ lastProcessedCheckpoint;
|
|
450
|
+
/** Periodic tick that runs the epoch-expiry sweep during idle periods when no block-stream events arrive. */ expiryTicker;
|
|
443
451
|
tracer;
|
|
444
452
|
publishingService;
|
|
445
453
|
constructor(prover, publisherFactory, l2BlockSource, l1ToL2MessageSource, contractDataSource, worldState, p2pClient, rollupContract, l1Metrics, config = {}, telemetryClient = getTelemetryClient(), delayer, dateProvider = new DateProvider()){
|
|
@@ -456,6 +464,7 @@ import { SessionManager } from './session-manager.js';
|
|
|
456
464
|
this.delayer = delayer;
|
|
457
465
|
this.dateProvider = dateProvider;
|
|
458
466
|
this.log = (_initProto(this), createLogger('prover-node'));
|
|
467
|
+
this.lastProcessedCheckpoint = CheckpointNumber.ZERO;
|
|
459
468
|
this.config = {
|
|
460
469
|
proverNodePollingIntervalMs: 1_000,
|
|
461
470
|
proverNodeMaxPendingJobs: 100,
|
|
@@ -486,8 +495,6 @@ import { SessionManager } from './session-manager.js';
|
|
|
486
495
|
metrics: this.jobMetrics,
|
|
487
496
|
txGatheringTimeoutMs: this.config.txGatheringTimeoutMs,
|
|
488
497
|
deadline: undefined
|
|
489
|
-
}, {
|
|
490
|
-
slotWatcherPollIntervalMs: this.config.proverNodePollingIntervalMs
|
|
491
498
|
}, this.log.getBindings());
|
|
492
499
|
}
|
|
493
500
|
getProverId() {
|
|
@@ -514,13 +521,6 @@ import { SessionManager } from './session-manager.js';
|
|
|
514
521
|
}
|
|
515
522
|
return this.sessionManager;
|
|
516
523
|
}
|
|
517
|
-
/** Returns world state status. */ async getWorldStateSyncStatus() {
|
|
518
|
-
const { syncSummary } = await this.worldState.status();
|
|
519
|
-
return syncSummary;
|
|
520
|
-
}
|
|
521
|
-
/** Returns archiver status. */ getL2Tips() {
|
|
522
|
-
return this.l2BlockSource.getL2Tips();
|
|
523
|
-
}
|
|
524
524
|
/** Returns the underlying prover instance. */ getProver() {
|
|
525
525
|
return this.prover;
|
|
526
526
|
}
|
|
@@ -528,17 +528,26 @@ import { SessionManager } from './session-manager.js';
|
|
|
528
528
|
async handleBlockStreamEvent(event) {
|
|
529
529
|
switch(event.type){
|
|
530
530
|
case 'chain-checkpointed':
|
|
531
|
-
await this.
|
|
531
|
+
await this.processCheckpointJump(event.checkpoint.number);
|
|
532
532
|
break;
|
|
533
533
|
case 'chain-pruned':
|
|
534
|
-
await this.handlePruneEvent(event.
|
|
534
|
+
await this.handlePruneEvent(event.block);
|
|
535
535
|
break;
|
|
536
536
|
case 'chain-proven':
|
|
537
537
|
this.publishingService?.onChainProven(BlockNumber(event.block.number));
|
|
538
538
|
break;
|
|
539
|
+
// The proposed tip drives only the tips store's walk-back history (recorded below); the prover-node
|
|
540
|
+
// tracks checkpoints, not proposed blocks. `blocks-added` is never emitted in tips-only mode, and
|
|
541
|
+
// `chain-finalized` carries nothing the prover-node acts on.
|
|
542
|
+
case 'chain-proposed':
|
|
539
543
|
case 'chain-finalized':
|
|
540
544
|
case 'blocks-added':
|
|
541
545
|
break;
|
|
546
|
+
default:
|
|
547
|
+
{
|
|
548
|
+
const _ = event;
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
542
551
|
}
|
|
543
552
|
// Expiry is driven by the archiver's latest synced L2 slot
|
|
544
553
|
await this.checkEpochExpiry();
|
|
@@ -547,27 +556,87 @@ import { SessionManager } from './session-manager.js';
|
|
|
547
556
|
// skips this update, so the event is re-emitted on the next poll rather than skipped (A-1041).
|
|
548
557
|
await this.tipsStore.handleBlockStreamEvent(event);
|
|
549
558
|
}
|
|
550
|
-
/**
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
559
|
+
/**
|
|
560
|
+
* Walks every checkpoint between the local cursor and the newly-reported checkpointed tip, registering
|
|
561
|
+
* each one that belongs to an epoch that can still be proven. The block stream now delivers a single thin
|
|
562
|
+
* `chain-checkpointed` tip event per pass rather than one fat event per checkpoint, so this drives the
|
|
563
|
+
* catch-up itself: light metadata first (`getCheckpointsData`) to decide relevance per epoch, then a heavy
|
|
564
|
+
* `getCheckpoints` fetch only for checkpoints in provable epochs.
|
|
565
|
+
*
|
|
566
|
+
* The cursor advances one checkpoint at a time and only after that checkpoint's proving-side handling has
|
|
567
|
+
* fully succeeded, preserving the A-1041 at-least-once semantics: a mid-jump failure leaves the cursor
|
|
568
|
+
* behind so the next pass retries from the first checkpoint that did not complete.
|
|
569
|
+
*/ async processCheckpointJump(targetCheckpoint) {
|
|
570
|
+
if (targetCheckpoint <= this.lastProcessedCheckpoint) {
|
|
557
571
|
return;
|
|
558
572
|
}
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
573
|
+
const l1Constants = await this.getL1Constants();
|
|
574
|
+
// Cap the catch-up at the `(proofSubmissionEpochs + 1) * epochDuration` most recent checkpoints.
|
|
575
|
+
// When the cursor is much further behind (e.g. resyncing after a long time offline), fetching the whole gap could
|
|
576
|
+
// load thousands of checkpoints we cannot act on: anything older than the last two epochs is already past
|
|
577
|
+
// its proof-submission window, so we skip it and jump the cursor forward to the start of the capped range.
|
|
578
|
+
const maxCheckpoints = (l1Constants.proofSubmissionEpochs + 1) * l1Constants.epochDuration;
|
|
579
|
+
let from = CheckpointNumber(this.lastProcessedCheckpoint + 1);
|
|
580
|
+
if (Number(targetCheckpoint - from) + 1 > maxCheckpoints) {
|
|
581
|
+
const cappedFrom = CheckpointNumber(targetCheckpoint - maxCheckpoints + 1);
|
|
582
|
+
this.log.warn(`Skipping unprovable checkpoints during catch-up; the prover node is far behind`, {
|
|
583
|
+
from,
|
|
584
|
+
cappedFrom,
|
|
585
|
+
targetCheckpoint,
|
|
586
|
+
maxCheckpoints
|
|
587
|
+
});
|
|
588
|
+
// Advance the cursor past the skipped checkpoints so they are never retried.
|
|
589
|
+
this.lastProcessedCheckpoint = CheckpointNumber(cappedFrom - 1);
|
|
590
|
+
from = cappedFrom;
|
|
591
|
+
}
|
|
592
|
+
const limit = Number(targetCheckpoint - from) + 1;
|
|
593
|
+
const metadatas = await this.l2BlockSource.getCheckpointsData({
|
|
594
|
+
from,
|
|
595
|
+
limit
|
|
596
|
+
});
|
|
597
|
+
// Per-epoch relevance is cached so a multi-checkpoint epoch resolves it once. Skipping is whole-epoch
|
|
598
|
+
// only: the SessionManager requires an epoch's checkpoints fully covered before it opens a session, so we
|
|
599
|
+
// never drop an individual checkpoint inside an epoch we will prove.
|
|
600
|
+
const epochSkippable = new Map();
|
|
601
|
+
for (const metadata of metadatas){
|
|
602
|
+
const epochNumber = getEpochAtSlot(metadata.header.slotNumber, l1Constants);
|
|
603
|
+
let skippable = epochSkippable.get(epochNumber);
|
|
604
|
+
if (skippable === undefined) {
|
|
605
|
+
skippable = await this.isEpochFullyProven(epochNumber, l1Constants) || await this.isEpochPastProofSubmissionWindow(epochNumber, l1Constants);
|
|
606
|
+
epochSkippable.set(epochNumber, skippable);
|
|
607
|
+
}
|
|
608
|
+
if (skippable) {
|
|
609
|
+
this.log.debug(`Skipping checkpoint ${metadata.checkpointNumber} for unprovable epoch ${epochNumber}`);
|
|
610
|
+
} else {
|
|
611
|
+
await this.registerCheckpoint(metadata.checkpointNumber, epochNumber);
|
|
612
|
+
}
|
|
613
|
+
// Advance only after the checkpoint's handling succeeded (or it was legitimately skipped). registerCheckpoint
|
|
614
|
+
// throws on failure, which leaves the cursor here for the next pass to retry (A-1041).
|
|
615
|
+
this.lastProcessedCheckpoint = metadata.checkpointNumber;
|
|
562
616
|
}
|
|
617
|
+
}
|
|
618
|
+
/** Heavy-fetch a single checkpoint, register it with the store, and notify the session manager. */ async registerCheckpoint(checkpointNumber, epochNumber) {
|
|
619
|
+
const published = await this.l2BlockSource.getCheckpoint({
|
|
620
|
+
number: checkpointNumber
|
|
621
|
+
});
|
|
622
|
+
if (!published) {
|
|
623
|
+
throw new Error(`Checkpoint ${checkpointNumber} not found in block source during catch-up`);
|
|
624
|
+
}
|
|
625
|
+
const checkpoint = published.checkpoint;
|
|
563
626
|
this.log.info(`New checkpoint ${checkpoint.number} for epoch ${epochNumber}`, {
|
|
564
627
|
checkpointNumber: checkpoint.number,
|
|
565
628
|
epochNumber,
|
|
566
|
-
slotNumber
|
|
629
|
+
slotNumber: checkpoint.header.slotNumber
|
|
567
630
|
});
|
|
568
|
-
const registerData = await this.collectRegisterData(checkpoint,
|
|
631
|
+
const registerData = await this.collectRegisterData(checkpoint, published.attestations);
|
|
569
632
|
await this.checkpointStore.addOrUpdate(checkpoint, registerData);
|
|
570
633
|
await this.sessionManager?.onCheckpointAdded(epochNumber);
|
|
634
|
+
// Tips-only mode delivers no blocks, so record one witness per checkpointed block: a reorg into the checkpoint's
|
|
635
|
+
// range then prunes at the true divergence instead of the nearest sparse tip anchor.
|
|
636
|
+
await this.tipsStore.recordBlockHashes(await Promise.all(checkpoint.blocks.map(async (block)=>({
|
|
637
|
+
number: block.number,
|
|
638
|
+
hash: (await block.header.hash()).toString()
|
|
639
|
+
}))));
|
|
571
640
|
}
|
|
572
641
|
/**
|
|
573
642
|
* Gathers register-time data for a checkpoint: previous block header, L1-to-L2 messages,
|
|
@@ -587,11 +656,38 @@ import { SessionManager } from './session-manager.js';
|
|
|
587
656
|
previousArchiveSiblingPath
|
|
588
657
|
};
|
|
589
658
|
}
|
|
590
|
-
/**
|
|
591
|
-
|
|
592
|
-
|
|
659
|
+
/**
|
|
660
|
+
* Marks every prover orphaned by the prune as pruned, clamps the catch-up cursor below the prune target's
|
|
661
|
+
* checkpoint, and notifies the session manager. Keyed off the prune target block (the highest surviving block)
|
|
662
|
+
* rather than the source's checkpointed tip, which can sit above the target after a re-checkpoint and would leave
|
|
663
|
+
* orphaned provers canonical. Throws (rather than warning) if the cursor floor cannot be resolved, so the pass
|
|
664
|
+
* fails and the prune is retried next iteration.
|
|
665
|
+
*/ async handlePruneEvent(prunedToBlock) {
|
|
666
|
+
this.log.warn(`Chain pruned to block ${prunedToBlock.number}`, {
|
|
667
|
+
prunedToBlock
|
|
593
668
|
});
|
|
594
|
-
|
|
669
|
+
// Resolve the cursor floor BEFORE removing provers: cancelAndRemoveAboveBlock returns only the provers it removed,
|
|
670
|
+
// so a throw after removing would leave a retry pass with nothing to act on. Resolving first means a throw leaves
|
|
671
|
+
// everything untouched and the next pass retries the whole handler (the tips cursor only advances on success).
|
|
672
|
+
let cursorFloor;
|
|
673
|
+
if (prunedToBlock.number === 0) {
|
|
674
|
+
cursorFloor = CheckpointNumber.ZERO;
|
|
675
|
+
} else {
|
|
676
|
+
const targetData = await this.l2BlockSource.getBlockData({
|
|
677
|
+
number: prunedToBlock.number
|
|
678
|
+
});
|
|
679
|
+
if (targetData === undefined) {
|
|
680
|
+
throw new Error(`No block data found for prune target block ${prunedToBlock.number}; cannot clamp checkpoint cursor`);
|
|
681
|
+
}
|
|
682
|
+
// Clamp to `cpAtTarget - 1`: a mid-checkpoint target leaves that checkpoint partially orphaned and it must be
|
|
683
|
+
// reprocessed. Over-clamping merely re-registers a checkpoint (at-least-once by design — A-1041); under-clamping
|
|
684
|
+
// would permanently skip a rebuilt same-number checkpoint.
|
|
685
|
+
cursorFloor = CheckpointNumber(Math.max(0, Number(targetData.checkpointNumber) - 1));
|
|
686
|
+
}
|
|
687
|
+
const affected = this.checkpointStore.cancelAndRemoveAboveBlock(prunedToBlock.number);
|
|
688
|
+
if (this.lastProcessedCheckpoint > cursorFloor) {
|
|
689
|
+
this.lastProcessedCheckpoint = cursorFloor;
|
|
690
|
+
}
|
|
595
691
|
if (affected.length === 0) {
|
|
596
692
|
return;
|
|
597
693
|
}
|
|
@@ -689,13 +785,18 @@ import { SessionManager } from './session-manager.js';
|
|
|
689
785
|
this.sessionManager.start();
|
|
690
786
|
// Now that the store + manager exist, arm the live-state observable gauges.
|
|
691
787
|
this.jobMetrics.observeState(this.checkpointStore, this.sessionManager);
|
|
692
|
-
const {
|
|
788
|
+
const { lastFullyProvenEpoch } = await this.resolveLastFullyProvenEpoch();
|
|
693
789
|
this.lastExpiredEpoch = lastFullyProvenEpoch;
|
|
694
|
-
this.
|
|
790
|
+
this.lastProcessedCheckpoint = await this.computeStartingCheckpoint(lastFullyProvenEpoch);
|
|
791
|
+
this.blockStream = new EventDrivenL2BlockStream(this.l2BlockSource, this.tipsStore, this, this.log, {
|
|
695
792
|
pollIntervalMS: this.config.proverNodePollingIntervalMs,
|
|
696
|
-
|
|
793
|
+
tipsOnly: true
|
|
697
794
|
});
|
|
698
795
|
this.blockStream.start();
|
|
796
|
+
// With thin once-per-pass tip events, the expiry sweep no longer fires once per checkpoint; drive it
|
|
797
|
+
// from a periodic tick so epochs still expire during idle/no-event periods.
|
|
798
|
+
this.expiryTicker = new RunningPromise(()=>this.checkEpochExpiry(), this.log, this.config.proverNodePollingIntervalMs);
|
|
799
|
+
this.expiryTicker.start();
|
|
699
800
|
await this.rewardsMetrics.start();
|
|
700
801
|
this.l1Metrics.start();
|
|
701
802
|
this.log.info(`Started Prover Node with prover id ${this.prover.getProverId().toString()}`, this.config);
|
|
@@ -704,6 +805,7 @@ import { SessionManager } from './session-manager.js';
|
|
|
704
805
|
this.log.info('Stopping ProverNode');
|
|
705
806
|
this.jobMetrics.stopObservingState();
|
|
706
807
|
await this.blockStream?.stop();
|
|
808
|
+
await this.expiryTicker?.stop();
|
|
707
809
|
if (this.sessionManager) {
|
|
708
810
|
await this.sessionManager.stop();
|
|
709
811
|
}
|
|
@@ -803,18 +905,16 @@ import { SessionManager } from './session-manager.js';
|
|
|
803
905
|
return this.l2BlockSource.isEpochComplete(provenEpoch);
|
|
804
906
|
}
|
|
805
907
|
/**
|
|
806
|
-
* Resolves the
|
|
807
|
-
*
|
|
808
|
-
*
|
|
809
|
-
*
|
|
810
|
-
|
|
811
|
-
*/ async computeStartupState() {
|
|
908
|
+
* Resolves the last fully-proven epoch from L1 proven state, used to seed the catch-up cursor (via
|
|
909
|
+
* `computeStartingCheckpoint`) and `lastExpiredEpoch`. The fully-proven epoch is `provenEpoch` when the
|
|
910
|
+
* proven tip is the last block of its epoch, otherwise `provenEpoch - 1`, or `undefined` if no block is
|
|
911
|
+
* proven yet (so a restart reprocesses the partially-proven epoch rather than trusting a stale tip).
|
|
912
|
+
*/ async resolveLastFullyProvenEpoch() {
|
|
812
913
|
const provenBlockNumber = await this.l2BlockSource.getBlockNumber({
|
|
813
914
|
tag: 'proven'
|
|
814
915
|
});
|
|
815
916
|
if (!provenBlockNumber || provenBlockNumber <= 0) {
|
|
816
917
|
return {
|
|
817
|
-
startingBlock: BlockNumber(1),
|
|
818
918
|
lastFullyProvenEpoch: undefined
|
|
819
919
|
};
|
|
820
920
|
}
|
|
@@ -824,32 +924,33 @@ import { SessionManager } from './session-manager.js';
|
|
|
824
924
|
}))?.header;
|
|
825
925
|
if (!provenHeader) {
|
|
826
926
|
return {
|
|
827
|
-
startingBlock: BlockNumber(provenBlockNumber + 1),
|
|
828
927
|
lastFullyProvenEpoch: undefined
|
|
829
928
|
};
|
|
830
929
|
}
|
|
831
930
|
const provenEpoch = getEpochAtSlot(provenHeader.getSlot(), l1Constants);
|
|
832
931
|
if (await this.isProvenBlockLastOfItsEpoch(BlockNumber(provenBlockNumber), provenEpoch, l1Constants)) {
|
|
833
932
|
return {
|
|
834
|
-
startingBlock: BlockNumber(provenBlockNumber + 1),
|
|
835
933
|
lastFullyProvenEpoch: provenEpoch
|
|
836
934
|
};
|
|
837
935
|
}
|
|
838
|
-
const epochCheckpoints = await this.l2BlockSource.getCheckpointsData({
|
|
839
|
-
epoch: provenEpoch
|
|
840
|
-
});
|
|
841
|
-
const firstBlockOfEpoch = epochCheckpoints.length > 0 ? epochCheckpoints[0].startBlock : BlockNumber(provenBlockNumber);
|
|
842
|
-
this.log.info(`Starting L2BlockStream at block ${firstBlockOfEpoch} (start of partially-proven epoch ${provenEpoch})`, {
|
|
843
|
-
provenBlockNumber,
|
|
844
|
-
provenEpoch,
|
|
845
|
-
firstBlockOfEpoch
|
|
846
|
-
});
|
|
847
936
|
const lastFullyProvenEpoch = provenEpoch > 0 ? EpochNumber(provenEpoch - 1) : undefined;
|
|
848
937
|
return {
|
|
849
|
-
startingBlock: firstBlockOfEpoch,
|
|
850
938
|
lastFullyProvenEpoch
|
|
851
939
|
};
|
|
852
940
|
}
|
|
941
|
+
/**
|
|
942
|
+
* Resolves the catch-up cursor seed: the last checkpoint of the last fully-proven epoch, or 0 if none. Seeding
|
|
943
|
+
* from a checkpoint (rather than a checkpointed tip) guarantees a restart reprocesses every checkpoint of the
|
|
944
|
+
* partially-proven epoch, since the checkpointed tip can sit ahead of the last fully-proven checkpoint.
|
|
945
|
+
*/ async computeStartingCheckpoint(lastFullyProvenEpoch) {
|
|
946
|
+
if (lastFullyProvenEpoch === undefined) {
|
|
947
|
+
return CheckpointNumber.ZERO;
|
|
948
|
+
}
|
|
949
|
+
const checkpoints = await this.l2BlockSource.getCheckpointsData({
|
|
950
|
+
epoch: lastFullyProvenEpoch
|
|
951
|
+
});
|
|
952
|
+
return checkpoints.at(-1)?.checkpointNumber ?? CheckpointNumber.ZERO;
|
|
953
|
+
}
|
|
853
954
|
async gatherPreviousBlockHeader(previousBlockNumber) {
|
|
854
955
|
const data = await this.l2BlockSource.getBlockData({
|
|
855
956
|
number: BlockNumber(previousBlockNumber)
|
|
@@ -148,11 +148,11 @@ export declare class SessionManager {
|
|
|
148
148
|
private atMaxSessionLimit;
|
|
149
149
|
private epochsForTrigger;
|
|
150
150
|
private nextUnprovenEpoch;
|
|
151
|
-
private
|
|
151
|
+
private checkpointsForSpec;
|
|
152
152
|
private fireAndForgetCancel;
|
|
153
153
|
private checkpointsMatch;
|
|
154
154
|
private archiverFullyCovered;
|
|
155
155
|
private isProvenChainEncompassing;
|
|
156
156
|
private getL1Constants;
|
|
157
157
|
}
|
|
158
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
158
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2Vzc2lvbi1tYW5hZ2VyLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvc2Vzc2lvbi1tYW5hZ2VyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBZSxLQUFLLFdBQVcsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRWhGLE9BQU8sS0FBSyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBQ2hFLE9BQU8sRUFBZSxLQUFLLGNBQWMsRUFBZ0IsTUFBTSx1QkFBdUIsQ0FBQztBQUd2RixPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQy9ELE9BQU8sS0FBSyxFQUFFLGFBQWEsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBUXpELE9BQU8sS0FBSyxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFNUUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDOUQsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMzRSxPQUFPLEVBQ0wsWUFBWSxFQUNaLEtBQUssZ0JBQWdCLEVBQ3JCLEtBQUssaUJBQWlCLEVBRXRCLEtBQUssV0FBVyxFQUVqQixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sS0FBSyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ3pELE9BQU8sS0FBSyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFNUUsdUNBQXVDO0FBQ3ZDLE1BQU0sTUFBTSxnQkFBZ0IsR0FDeEI7SUFBRSxJQUFJLEVBQUUsWUFBWSxDQUFDO0lBQUMsS0FBSyxFQUFFLFdBQVcsQ0FBQTtDQUFFLEdBQzFD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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../src/session-manager.ts"],"names":[],"mappings":"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"}
|
package/dest/session-manager.js
CHANGED
|
@@ -109,7 +109,7 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
109
109
|
* partial's spec stops at the last canonical slot, while the full's stops at the epoch's last
|
|
110
110
|
* slot. Dedupes against any existing session covering the same range, returning its id.
|
|
111
111
|
*/ async startProof(epoch) {
|
|
112
|
-
const canonical = await this.deps.checkpointStore.
|
|
112
|
+
const canonical = await this.deps.checkpointStore.listForEpoch(epoch);
|
|
113
113
|
if (canonical.length === 0) {
|
|
114
114
|
throw new EmptyEpochError(epoch);
|
|
115
115
|
}
|
|
@@ -185,7 +185,7 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
185
185
|
this.fullSessions.delete(key);
|
|
186
186
|
continue;
|
|
187
187
|
}
|
|
188
|
-
const canonical = this.
|
|
188
|
+
const canonical = this.checkpointsForSpec(session.getSpec());
|
|
189
189
|
if (!this.checkpointsMatch(session.getCheckpoints(), canonical)) {
|
|
190
190
|
this.fireAndForgetCancel(session, 'canonical content changed');
|
|
191
191
|
this.fullSessions.delete(key);
|
|
@@ -201,7 +201,7 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
201
201
|
this.partialSessions.delete(key);
|
|
202
202
|
continue;
|
|
203
203
|
}
|
|
204
|
-
const canonical = this.
|
|
204
|
+
const canonical = this.checkpointsForSpec(session.getSpec());
|
|
205
205
|
if (!this.checkpointsMatch(session.getCheckpoints(), canonical)) {
|
|
206
206
|
this.fireAndForgetCancel(session, 'canonical content changed');
|
|
207
207
|
this.partialSessions.delete(key);
|
|
@@ -214,6 +214,8 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
async openFullSessionIfReady(epoch) {
|
|
217
|
+
// `recreateInvalidSessions` runs at the top of every reconcile and deletes terminal sessions
|
|
218
|
+
// before this is called, so a session present here is live and already covers the epoch.
|
|
217
219
|
if (this.fullSessions.has(epoch)) {
|
|
218
220
|
return;
|
|
219
221
|
}
|
|
@@ -232,7 +234,7 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
232
234
|
return;
|
|
233
235
|
}
|
|
234
236
|
const [fromSlot, toSlot] = getSlotRangeForEpoch(epoch, l1Constants);
|
|
235
|
-
const canonical = this.deps.checkpointStore.
|
|
237
|
+
const canonical = this.deps.checkpointStore.listInSlotRange(fromSlot, toSlot);
|
|
236
238
|
if (!this.archiverFullyCovered(archiverCps, canonical)) {
|
|
237
239
|
this.log.debug(`Skipping full-session open for epoch ${epoch}: archiver checkpoints not all in store`, {
|
|
238
240
|
archiverCount: archiverCps.length,
|
|
@@ -251,7 +253,7 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
251
253
|
void this.runSession(session);
|
|
252
254
|
}
|
|
253
255
|
openPartialSession(spec) {
|
|
254
|
-
const canonical = this.deps.checkpointStore.
|
|
256
|
+
const canonical = this.deps.checkpointStore.listInSlotRange(spec.fromSlot, spec.toSlot);
|
|
255
257
|
if (canonical.length === 0) {
|
|
256
258
|
return;
|
|
257
259
|
}
|
|
@@ -311,6 +313,17 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
311
313
|
const state = await session.start();
|
|
312
314
|
this.log.info(`Session ${session.getId()} exited with state ${state}`);
|
|
313
315
|
if (state === 'failed' && this.deps.onSessionFailed) {
|
|
316
|
+
// Best-effort suppression of the spurious post-mortem upload a prune produces: if the session's
|
|
317
|
+
// checkpoints no longer match the store's current set, the failure was caused by the content
|
|
318
|
+
// changing under it, not a genuine proving fault, so skip the upload. This is inherently racy —
|
|
319
|
+
// the store lags the world-state unwind, so a fault observed before the prune is reconciled here
|
|
320
|
+
// still uploads. The epoch is recovered regardless by recreating the session on re-add.
|
|
321
|
+
if (!this.checkpointsMatch(session.getCheckpoints(), this.checkpointsForSpec(session.getSpec()))) {
|
|
322
|
+
this.log.info(`Skipping failure upload for session ${session.getId()}: canonical content changed`, {
|
|
323
|
+
...session.getSpec()
|
|
324
|
+
});
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
314
327
|
try {
|
|
315
328
|
await this.deps.onSessionFailed(session);
|
|
316
329
|
} catch (err) {
|
|
@@ -350,7 +363,24 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
350
363
|
const live = this.allSessions().filter((s)=>!s.isTerminal()).length;
|
|
351
364
|
return live >= max;
|
|
352
365
|
}
|
|
353
|
-
|
|
366
|
+
/**
|
|
367
|
+
* Maps a reconcile trigger to the epochs whose full session should be (re)opened.
|
|
368
|
+
*
|
|
369
|
+
* This is where the "don't retry a genuinely-failed epoch, but do recover a pruned one" invariant
|
|
370
|
+
* lives — enforced by which triggers are gated by `lastTickEpoch`:
|
|
371
|
+
*
|
|
372
|
+
* - The periodic `tick` IS gated: once a tick has opened a session for an epoch, `lastTickEpoch`
|
|
373
|
+
* advances to it and later ticks skip it (`epoch <= lastTickEpoch`). So a failed attempt is never
|
|
374
|
+
* resubmitted on a loop by the tick.
|
|
375
|
+
* - `checkpoint` and `prune` are deliberately NOT gated. They only fire when the epoch's canonical
|
|
376
|
+
* content actually changes — a checkpoint arrives, or a reorg prunes/replaces one — which is
|
|
377
|
+
* exactly when re-attempting is correct.
|
|
378
|
+
*
|
|
379
|
+
* A genuine proving failure produces no content change, hence no checkpoint/prune event, so only
|
|
380
|
+
* the gated tick could reopen it — and it won't. A prune + re-add fires ungated events, so the
|
|
381
|
+
* epoch is reopened through this path (and `openFullSessionIfReady` rebuilds over the fresh
|
|
382
|
+
* provers). See the "onTick does not retry ... but recovers ... re-added" test.
|
|
383
|
+
*/ async epochsForTrigger(trigger) {
|
|
354
384
|
switch(trigger.kind){
|
|
355
385
|
case 'checkpoint':
|
|
356
386
|
return [
|
|
@@ -390,8 +420,8 @@ import { EpochSession, specKey } from './job/epoch-session.js';
|
|
|
390
420
|
}
|
|
391
421
|
return getEpochAtSlot(header.getSlot(), await this.getL1Constants());
|
|
392
422
|
}
|
|
393
|
-
|
|
394
|
-
return this.deps.checkpointStore.
|
|
423
|
+
checkpointsForSpec(spec) {
|
|
424
|
+
return this.deps.checkpointStore.listInSlotRange(spec.fromSlot, spec.toSlot);
|
|
395
425
|
}
|
|
396
426
|
fireAndForgetCancel(session, reason) {
|
|
397
427
|
void session.cancel(reason).catch((err)=>this.log.warn(`Error cancelling session ${session.getId()}`, err));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/prover-node",
|
|
3
|
-
"version": "5.0.0
|
|
3
|
+
"version": "5.0.0",
|
|
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": "5.0.0
|
|
60
|
-
"@aztec/bb-prover": "5.0.0
|
|
61
|
-
"@aztec/blob-client": "5.0.0
|
|
62
|
-
"@aztec/blob-lib": "5.0.0
|
|
63
|
-
"@aztec/constants": "5.0.0
|
|
64
|
-
"@aztec/epoch-cache": "5.0.0
|
|
65
|
-
"@aztec/ethereum": "5.0.0
|
|
66
|
-
"@aztec/foundation": "5.0.0
|
|
67
|
-
"@aztec/kv-store": "5.0.0
|
|
68
|
-
"@aztec/l1-artifacts": "5.0.0
|
|
69
|
-
"@aztec/native": "5.0.0
|
|
70
|
-
"@aztec/node-keystore": "5.0.0
|
|
71
|
-
"@aztec/node-lib": "5.0.0
|
|
72
|
-
"@aztec/noir-protocol-circuits-types": "5.0.0
|
|
73
|
-
"@aztec/p2p": "5.0.0
|
|
74
|
-
"@aztec/protocol-contracts": "5.0.0
|
|
75
|
-
"@aztec/prover-client": "5.0.0
|
|
76
|
-
"@aztec/sequencer-client": "5.0.0
|
|
77
|
-
"@aztec/simulator": "5.0.0
|
|
78
|
-
"@aztec/stdlib": "5.0.0
|
|
79
|
-
"@aztec/telemetry-client": "5.0.0
|
|
80
|
-
"@aztec/world-state": "5.0.0
|
|
59
|
+
"@aztec/archiver": "5.0.0",
|
|
60
|
+
"@aztec/bb-prover": "5.0.0",
|
|
61
|
+
"@aztec/blob-client": "5.0.0",
|
|
62
|
+
"@aztec/blob-lib": "5.0.0",
|
|
63
|
+
"@aztec/constants": "5.0.0",
|
|
64
|
+
"@aztec/epoch-cache": "5.0.0",
|
|
65
|
+
"@aztec/ethereum": "5.0.0",
|
|
66
|
+
"@aztec/foundation": "5.0.0",
|
|
67
|
+
"@aztec/kv-store": "5.0.0",
|
|
68
|
+
"@aztec/l1-artifacts": "5.0.0",
|
|
69
|
+
"@aztec/native": "5.0.0",
|
|
70
|
+
"@aztec/node-keystore": "5.0.0",
|
|
71
|
+
"@aztec/node-lib": "5.0.0",
|
|
72
|
+
"@aztec/noir-protocol-circuits-types": "5.0.0",
|
|
73
|
+
"@aztec/p2p": "5.0.0",
|
|
74
|
+
"@aztec/protocol-contracts": "5.0.0",
|
|
75
|
+
"@aztec/prover-client": "5.0.0",
|
|
76
|
+
"@aztec/sequencer-client": "5.0.0",
|
|
77
|
+
"@aztec/simulator": "5.0.0",
|
|
78
|
+
"@aztec/stdlib": "5.0.0",
|
|
79
|
+
"@aztec/telemetry-client": "5.0.0",
|
|
80
|
+
"@aztec/world-state": "5.0.0",
|
|
81
81
|
"source-map-support": "^0.5.21",
|
|
82
82
|
"tslib": "^2.4.0",
|
|
83
83
|
"viem": "npm:@aztec/viem@2.38.2"
|