@aztec/prover-client 0.0.1-commit.d3ec352c → 0.0.1-commit.d58ff9d0
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/config.d.ts +2 -2
- package/dest/config.d.ts.map +1 -1
- package/dest/config.js +17 -3
- package/dest/light/index.d.ts +2 -0
- package/dest/light/index.d.ts.map +1 -0
- package/dest/light/index.js +1 -0
- package/dest/light/lightweight_checkpoint_builder.d.ts +38 -15
- package/dest/light/lightweight_checkpoint_builder.d.ts.map +1 -1
- package/dest/light/lightweight_checkpoint_builder.js +162 -36
- package/dest/mocks/fixtures.d.ts +1 -1
- package/dest/mocks/fixtures.d.ts.map +1 -1
- package/dest/mocks/fixtures.js +4 -3
- package/dest/mocks/test_context.d.ts +15 -13
- package/dest/mocks/test_context.d.ts.map +1 -1
- package/dest/mocks/test_context.js +50 -36
- package/dest/orchestrator/block-building-helpers.d.ts +6 -6
- package/dest/orchestrator/block-building-helpers.d.ts.map +1 -1
- package/dest/orchestrator/block-building-helpers.js +5 -5
- package/dest/orchestrator/block-proving-state.d.ts +5 -2
- package/dest/orchestrator/block-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/block-proving-state.js +8 -1
- package/dest/orchestrator/checkpoint-proving-state.d.ts +20 -23
- package/dest/orchestrator/checkpoint-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/checkpoint-proving-state.js +23 -87
- package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts +161 -0
- package/dest/orchestrator/checkpoint-sub-tree-orchestrator.d.ts.map +1 -0
- package/dest/orchestrator/checkpoint-sub-tree-orchestrator.js +1066 -0
- package/dest/orchestrator/chonk-cache.d.ts +39 -0
- package/dest/orchestrator/chonk-cache.d.ts.map +1 -0
- package/dest/orchestrator/chonk-cache.js +80 -0
- package/dest/orchestrator/index.d.ts +4 -2
- package/dest/orchestrator/index.d.ts.map +1 -1
- package/dest/orchestrator/index.js +3 -1
- package/dest/orchestrator/orchestrator_metrics.d.ts +1 -3
- package/dest/orchestrator/orchestrator_metrics.d.ts.map +1 -1
- package/dest/orchestrator/orchestrator_metrics.js +2 -15
- package/dest/orchestrator/proving-scheduler.d.ts +81 -0
- package/dest/orchestrator/proving-scheduler.d.ts.map +1 -0
- package/dest/orchestrator/proving-scheduler.js +120 -0
- package/dest/orchestrator/top-tree-orchestrator.d.ts +88 -0
- package/dest/orchestrator/top-tree-orchestrator.d.ts.map +1 -0
- package/dest/orchestrator/top-tree-orchestrator.js +232 -0
- package/dest/orchestrator/top-tree-proving-state.d.ts +61 -0
- package/dest/orchestrator/top-tree-proving-state.d.ts.map +1 -0
- package/dest/orchestrator/top-tree-proving-state.js +185 -0
- package/dest/orchestrator/tx-proving-state.d.ts +7 -6
- package/dest/orchestrator/tx-proving-state.d.ts.map +1 -1
- package/dest/orchestrator/tx-proving-state.js +8 -8
- package/dest/prover-client/factory.d.ts +3 -3
- package/dest/prover-client/factory.d.ts.map +1 -1
- package/dest/prover-client/prover-client.d.ts +65 -8
- package/dest/prover-client/prover-client.d.ts.map +1 -1
- package/dest/prover-client/prover-client.js +66 -14
- package/dest/proving_broker/broker_prover_facade.d.ts +8 -6
- package/dest/proving_broker/broker_prover_facade.d.ts.map +1 -1
- package/dest/proving_broker/broker_prover_facade.js +18 -31
- package/dest/proving_broker/config.d.ts +13 -65
- package/dest/proving_broker/config.d.ts.map +1 -1
- package/dest/proving_broker/config.js +23 -6
- package/dest/proving_broker/fixtures.js +1 -1
- package/dest/proving_broker/index.d.ts +2 -1
- package/dest/proving_broker/index.d.ts.map +1 -1
- package/dest/proving_broker/index.js +1 -0
- package/dest/proving_broker/proof_store/factory.d.ts +2 -5
- package/dest/proving_broker/proof_store/factory.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/factory.js +7 -30
- package/dest/proving_broker/proof_store/file_store_proof_store.d.ts +18 -0
- package/dest/proving_broker/proof_store/file_store_proof_store.d.ts.map +1 -0
- package/dest/proving_broker/proof_store/file_store_proof_store.js +60 -0
- package/dest/proving_broker/proof_store/index.d.ts +2 -2
- package/dest/proving_broker/proof_store/index.d.ts.map +1 -1
- package/dest/proving_broker/proof_store/index.js +1 -1
- package/dest/proving_broker/proving_agent.d.ts +5 -9
- package/dest/proving_broker/proving_agent.d.ts.map +1 -1
- package/dest/proving_broker/proving_agent.js +4 -19
- package/dest/proving_broker/proving_broker.d.ts +8 -5
- package/dest/proving_broker/proving_broker.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker.js +72 -21
- package/dest/proving_broker/proving_broker_database/persisted.d.ts +3 -2
- package/dest/proving_broker/proving_broker_database/persisted.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_database/persisted.js +391 -3
- package/dest/proving_broker/proving_broker_instrumentation.d.ts +3 -1
- package/dest/proving_broker/proving_broker_instrumentation.d.ts.map +1 -1
- package/dest/proving_broker/proving_broker_instrumentation.js +22 -35
- package/dest/proving_broker/proving_job_controller.d.ts +4 -3
- package/dest/proving_broker/proving_job_controller.d.ts.map +1 -1
- package/dest/proving_broker/proving_job_controller.js +8 -6
- package/dest/proving_broker/rpc.d.ts +6 -2
- package/dest/proving_broker/rpc.d.ts.map +1 -1
- package/dest/proving_broker/rpc.js +87 -23
- package/dest/test/epoch_settlement.d.ts +36 -0
- package/dest/test/epoch_settlement.d.ts.map +1 -0
- package/dest/test/epoch_settlement.js +52 -0
- package/dest/test/index.d.ts +2 -0
- package/dest/test/index.d.ts.map +1 -0
- package/dest/test/index.js +1 -0
- package/dest/test/mock_proof_store.d.ts +3 -3
- package/dest/test/mock_proof_store.d.ts.map +1 -1
- package/dest/test/mock_prover.d.ts +5 -5
- package/dest/test/mock_prover.d.ts.map +1 -1
- package/dest/test/mock_prover.js +4 -4
- package/package.json +23 -22
- package/src/config.ts +19 -3
- package/src/light/index.ts +1 -0
- package/src/light/lightweight_checkpoint_builder.ts +229 -50
- package/src/mocks/fixtures.ts +4 -3
- package/src/mocks/test_context.ts +44 -48
- package/src/orchestrator/block-building-helpers.ts +5 -5
- package/src/orchestrator/block-proving-state.ts +10 -1
- package/src/orchestrator/checkpoint-proving-state.ts +22 -116
- package/src/orchestrator/checkpoint-sub-tree-orchestrator.ts +1044 -0
- package/src/orchestrator/chonk-cache.ts +99 -0
- package/src/orchestrator/index.ts +8 -1
- package/src/orchestrator/orchestrator_metrics.ts +2 -25
- package/src/orchestrator/proving-scheduler.ts +160 -0
- package/src/orchestrator/top-tree-orchestrator.ts +384 -0
- package/src/orchestrator/top-tree-proving-state.ts +219 -0
- package/src/orchestrator/tx-proving-state.ts +11 -15
- package/src/prover-client/factory.ts +6 -2
- package/src/prover-client/prover-client.ts +148 -29
- package/src/proving_broker/broker_prover_facade.ts +27 -37
- package/src/proving_broker/config.ts +26 -3
- package/src/proving_broker/fixtures.ts +1 -1
- package/src/proving_broker/index.ts +1 -0
- package/src/proving_broker/proof_store/factory.ts +10 -32
- package/src/proving_broker/proof_store/file_store_proof_store.ts +78 -0
- package/src/proving_broker/proof_store/index.ts +1 -1
- package/src/proving_broker/proving_agent.ts +6 -19
- package/src/proving_broker/proving_broker.ts +68 -16
- package/src/proving_broker/proving_broker_database/persisted.ts +17 -3
- package/src/proving_broker/proving_broker_instrumentation.ts +23 -35
- package/src/proving_broker/proving_job_controller.ts +11 -6
- package/src/proving_broker/rpc.ts +46 -20
- package/src/test/epoch_settlement.ts +82 -0
- package/src/test/index.ts +1 -0
- package/src/test/mock_prover.ts +3 -15
- package/dest/block-factory/index.d.ts +0 -2
- package/dest/block-factory/index.d.ts.map +0 -1
- package/dest/block-factory/index.js +0 -1
- package/dest/block-factory/light.d.ts +0 -38
- package/dest/block-factory/light.d.ts.map +0 -1
- package/dest/block-factory/light.js +0 -108
- package/dest/orchestrator/epoch-proving-state.d.ts +0 -74
- package/dest/orchestrator/epoch-proving-state.d.ts.map +0 -1
- package/dest/orchestrator/epoch-proving-state.js +0 -233
- package/dest/orchestrator/orchestrator.d.ts +0 -113
- package/dest/orchestrator/orchestrator.d.ts.map +0 -1
- package/dest/orchestrator/orchestrator.js +0 -842
- package/dest/prover-client/server-epoch-prover.d.ts +0 -32
- package/dest/prover-client/server-epoch-prover.d.ts.map +0 -1
- package/dest/prover-client/server-epoch-prover.js +0 -40
- package/dest/proving_broker/proof_store/gcs_proof_store.d.ts +0 -14
- package/dest/proving_broker/proof_store/gcs_proof_store.d.ts.map +0 -1
- package/dest/proving_broker/proof_store/gcs_proof_store.js +0 -52
- package/dest/proving_broker/proving_agent_instrumentation.d.ts +0 -8
- package/dest/proving_broker/proving_agent_instrumentation.d.ts.map +0 -1
- package/dest/proving_broker/proving_agent_instrumentation.js +0 -16
- package/src/block-factory/index.ts +0 -1
- package/src/block-factory/light.ts +0 -137
- package/src/orchestrator/epoch-proving-state.ts +0 -330
- package/src/orchestrator/orchestrator.ts +0 -1265
- package/src/prover-client/server-epoch-prover.ts +0 -69
- package/src/proving_broker/proof_store/gcs_proof_store.ts +0 -76
- package/src/proving_broker/proving_agent_instrumentation.ts +0 -21
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbortError } from '@aztec/foundation/error';
|
|
2
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
2
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { RunningPromise } from '@aztec/foundation/running-promise';
|
|
4
4
|
import { truncate } from '@aztec/foundation/string';
|
|
5
5
|
import { ProvingError } from '@aztec/stdlib/errors';
|
|
@@ -13,27 +13,17 @@ import type {
|
|
|
13
13
|
ServerCircuitProver,
|
|
14
14
|
} from '@aztec/stdlib/interfaces/server';
|
|
15
15
|
import { ProvingRequestType } from '@aztec/stdlib/proofs';
|
|
16
|
-
import {
|
|
17
|
-
type TelemetryClient,
|
|
18
|
-
type Traceable,
|
|
19
|
-
type Tracer,
|
|
20
|
-
getTelemetryClient,
|
|
21
|
-
trackSpan,
|
|
22
|
-
} from '@aztec/telemetry-client';
|
|
23
16
|
|
|
24
17
|
import type { ProofStore } from './proof_store/index.js';
|
|
25
|
-
import { ProvingAgentInstrumentation } from './proving_agent_instrumentation.js';
|
|
26
18
|
import { ProvingJobController, ProvingJobControllerStatus } from './proving_job_controller.js';
|
|
27
19
|
|
|
28
20
|
/**
|
|
29
21
|
* A helper class that encapsulates a circuit prover and connects it to a job source.
|
|
30
22
|
*/
|
|
31
|
-
export class ProvingAgent
|
|
23
|
+
export class ProvingAgent {
|
|
32
24
|
private currentJobController?: ProvingJobController;
|
|
33
25
|
private runningPromise: RunningPromise;
|
|
34
|
-
private
|
|
35
|
-
|
|
36
|
-
public readonly tracer: Tracer;
|
|
26
|
+
private log: Logger;
|
|
37
27
|
|
|
38
28
|
constructor(
|
|
39
29
|
/** The source of proving jobs */
|
|
@@ -46,12 +36,9 @@ export class ProvingAgent implements Traceable {
|
|
|
46
36
|
private proofAllowList: Array<ProvingRequestType> = [],
|
|
47
37
|
/** How long to wait between jobs */
|
|
48
38
|
private pollIntervalMs = 1000,
|
|
49
|
-
|
|
50
|
-
client: TelemetryClient = getTelemetryClient(),
|
|
51
|
-
private log = createLogger('prover-client:proving-agent'),
|
|
39
|
+
bindings?: LoggerBindings,
|
|
52
40
|
) {
|
|
53
|
-
this.
|
|
54
|
-
this.instrumentation = new ProvingAgentInstrumentation(client);
|
|
41
|
+
this.log = createLogger('prover-client:proving-agent', bindings);
|
|
55
42
|
this.runningPromise = new RunningPromise(this.work.bind(this), this.log, this.pollIntervalMs);
|
|
56
43
|
}
|
|
57
44
|
|
|
@@ -85,7 +72,6 @@ export class ProvingAgent implements Traceable {
|
|
|
85
72
|
return this.runningPromise.isRunning() ? { status: 'running' } : { status: 'stopped' };
|
|
86
73
|
}
|
|
87
74
|
|
|
88
|
-
@trackSpan('ProvingAgent.safeWork')
|
|
89
75
|
private async work() {
|
|
90
76
|
// every tick we need to take one of the following actions:
|
|
91
77
|
// 1. send a hearbeat to the broker that we're working on some job
|
|
@@ -175,6 +161,7 @@ export class ProvingAgent implements Traceable {
|
|
|
175
161
|
// no need to await this here. The controller will stay alive (in DONE state) until the result is send to the broker
|
|
176
162
|
void this.runningPromise.trigger();
|
|
177
163
|
},
|
|
164
|
+
this.log.getBindings(),
|
|
178
165
|
);
|
|
179
166
|
|
|
180
167
|
if (abortedProofJobId) {
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
type GetProvingJobResponse,
|
|
8
8
|
type ProofUri,
|
|
9
9
|
type ProvingJob,
|
|
10
|
+
type ProvingJobBrokerDebug,
|
|
10
11
|
type ProvingJobConsumer,
|
|
11
12
|
type ProvingJobFilter,
|
|
12
13
|
type ProvingJobId,
|
|
@@ -16,13 +17,7 @@ import {
|
|
|
16
17
|
tryStop,
|
|
17
18
|
} from '@aztec/stdlib/interfaces/server';
|
|
18
19
|
import { ProvingRequestType } from '@aztec/stdlib/proofs';
|
|
19
|
-
import {
|
|
20
|
-
type TelemetryClient,
|
|
21
|
-
type Traceable,
|
|
22
|
-
type Tracer,
|
|
23
|
-
getTelemetryClient,
|
|
24
|
-
trackSpan,
|
|
25
|
-
} from '@aztec/telemetry-client';
|
|
20
|
+
import { type TelemetryClient, type Traceable, type Tracer, getTelemetryClient } from '@aztec/telemetry-client';
|
|
26
21
|
|
|
27
22
|
import assert from 'assert';
|
|
28
23
|
|
|
@@ -42,7 +37,7 @@ type EnqueuedProvingJob = Pick<ProvingJob, 'id' | 'epochNumber'>;
|
|
|
42
37
|
* A broker that manages proof requests and distributes them to workers based on their priority.
|
|
43
38
|
* It takes a backend that is responsible for storing and retrieving proof requests and results.
|
|
44
39
|
*/
|
|
45
|
-
export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Traceable {
|
|
40
|
+
export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, ProvingJobBrokerDebug, Traceable {
|
|
46
41
|
private queues: ProvingQueues = {
|
|
47
42
|
[ProvingRequestType.PUBLIC_VM]: new PriorityMemoryQueue<EnqueuedProvingJob>(provingJobComparator),
|
|
48
43
|
[ProvingRequestType.PUBLIC_CHONK_VERIFIER]: new PriorityMemoryQueue<EnqueuedProvingJob>(provingJobComparator),
|
|
@@ -120,6 +115,8 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
120
115
|
|
|
121
116
|
private started = false;
|
|
122
117
|
|
|
118
|
+
private debugReplayEnabled: boolean;
|
|
119
|
+
|
|
123
120
|
public constructor(
|
|
124
121
|
private database: ProvingBrokerDatabase,
|
|
125
122
|
{
|
|
@@ -127,6 +124,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
127
124
|
proverBrokerPollIntervalMs,
|
|
128
125
|
proverBrokerJobMaxRetries,
|
|
129
126
|
proverBrokerMaxEpochsToKeepResultsFor,
|
|
127
|
+
proverBrokerDebugReplayEnabled,
|
|
130
128
|
}: Required<
|
|
131
129
|
Pick<
|
|
132
130
|
ProverBrokerConfig,
|
|
@@ -134,6 +132,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
134
132
|
| 'proverBrokerPollIntervalMs'
|
|
135
133
|
| 'proverBrokerJobMaxRetries'
|
|
136
134
|
| 'proverBrokerMaxEpochsToKeepResultsFor'
|
|
135
|
+
| 'proverBrokerDebugReplayEnabled'
|
|
137
136
|
>
|
|
138
137
|
> = defaultProverBrokerConfig,
|
|
139
138
|
client: TelemetryClient = getTelemetryClient(),
|
|
@@ -145,6 +144,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
145
144
|
this.jobTimeoutMs = proverBrokerJobTimeoutMs!;
|
|
146
145
|
this.maxRetries = proverBrokerJobMaxRetries!;
|
|
147
146
|
this.maxEpochsToKeepResultsFor = proverBrokerMaxEpochsToKeepResultsFor!;
|
|
147
|
+
this.debugReplayEnabled = proverBrokerDebugReplayEnabled ?? false;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
private measureQueueDepth: MonitorCallback = (type: ProvingRequestType) => {
|
|
@@ -247,6 +247,29 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
247
247
|
return Promise.resolve(this.#reportProvingJobProgress(id, startedAt, filter));
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
public async replayProvingJob(
|
|
251
|
+
jobId: ProvingJobId,
|
|
252
|
+
type: ProvingRequestType,
|
|
253
|
+
epochNumber: EpochNumber,
|
|
254
|
+
inputsUri: ProofUri,
|
|
255
|
+
): Promise<ProvingJobStatus> {
|
|
256
|
+
if (!this.debugReplayEnabled) {
|
|
257
|
+
throw new Error('Debug replay not enabled. Set PROVER_BROKER_DEBUG_REPLAY_ENABLED=true');
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
this.logger.info(`Replaying proving job`, { provingJobId: jobId, epochNumber, inputsUri });
|
|
261
|
+
|
|
262
|
+
// Clear existing state and enqueue
|
|
263
|
+
this.cleanUpProvingJobState([jobId]);
|
|
264
|
+
|
|
265
|
+
const job: ProvingJob = { id: jobId, type, epochNumber, inputsUri };
|
|
266
|
+
this.jobsCache.set(jobId, job);
|
|
267
|
+
await this.database.addProvingJob(job);
|
|
268
|
+
this.enqueueJobInternal(job);
|
|
269
|
+
|
|
270
|
+
return { status: 'in-queue' };
|
|
271
|
+
}
|
|
272
|
+
|
|
250
273
|
async #enqueueProvingJob(job: ProvingJob): Promise<ProvingJobStatus> {
|
|
251
274
|
// We return the job status at the start of this call
|
|
252
275
|
const jobStatus = this.#getProvingJobStatus(job.id);
|
|
@@ -291,18 +314,25 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
291
314
|
// notify listeners of the cancellation
|
|
292
315
|
if (!this.resultsCache.has(id)) {
|
|
293
316
|
this.logger.info(`Cancelling job id=${id}`, { provingJobId: id });
|
|
294
|
-
await this.#reportProvingJobError(id, 'Aborted', false);
|
|
317
|
+
await this.#reportProvingJobError(id, 'Aborted', false, undefined, true);
|
|
295
318
|
}
|
|
296
319
|
}
|
|
297
320
|
|
|
298
321
|
private cleanUpProvingJobState(ids: ProvingJobId[]) {
|
|
322
|
+
const idsToClean = new Set(ids);
|
|
299
323
|
for (const id of ids) {
|
|
300
324
|
this.jobsCache.delete(id);
|
|
325
|
+
const deferred = this.promises.get(id);
|
|
326
|
+
if (deferred) {
|
|
327
|
+
deferred.resolve({ status: 'rejected', reason: 'Proving job cleaned up' });
|
|
328
|
+
}
|
|
301
329
|
this.promises.delete(id);
|
|
302
330
|
this.resultsCache.delete(id);
|
|
303
331
|
this.inProgress.delete(id);
|
|
304
332
|
this.retries.delete(id);
|
|
333
|
+
this.enqueuedAt.delete(id);
|
|
305
334
|
}
|
|
335
|
+
this.completedJobNotifications = this.completedJobNotifications.filter(id => !idsToClean.has(id));
|
|
306
336
|
}
|
|
307
337
|
|
|
308
338
|
#getProvingJobStatus(id: ProvingJobId): ProvingJobStatus {
|
|
@@ -354,6 +384,8 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
354
384
|
const enqueuedAt = this.enqueuedAt.get(job.id);
|
|
355
385
|
if (enqueuedAt) {
|
|
356
386
|
this.instrumentation.recordJobWait(job.type, enqueuedAt);
|
|
387
|
+
// we can clear this flag now.
|
|
388
|
+
this.enqueuedAt.delete(job.id);
|
|
357
389
|
}
|
|
358
390
|
|
|
359
391
|
return { job, time };
|
|
@@ -369,6 +401,7 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
369
401
|
err: string,
|
|
370
402
|
retry = false,
|
|
371
403
|
filter?: ProvingJobFilter,
|
|
404
|
+
aborted = false,
|
|
372
405
|
): Promise<GetProvingJobResponse | undefined> {
|
|
373
406
|
const info = this.inProgress.get(id);
|
|
374
407
|
const item = this.jobsCache.get(id);
|
|
@@ -429,7 +462,11 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
429
462
|
this.promises.get(id)!.resolve(result);
|
|
430
463
|
this.completedJobNotifications.push(id);
|
|
431
464
|
|
|
432
|
-
|
|
465
|
+
if (aborted) {
|
|
466
|
+
this.instrumentation.incAbortedJobs(item.type);
|
|
467
|
+
} else {
|
|
468
|
+
this.instrumentation.incRejectedJobs(item.type);
|
|
469
|
+
}
|
|
433
470
|
if (info) {
|
|
434
471
|
const duration = this.msTimeSource() - info.startedAt;
|
|
435
472
|
this.instrumentation.recordJobDuration(item.type, duration);
|
|
@@ -562,23 +599,22 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
562
599
|
return this.#getProvingJob(filter);
|
|
563
600
|
}
|
|
564
601
|
|
|
565
|
-
@trackSpan('ProvingBroker.cleanupPass')
|
|
566
602
|
private async cleanupPass() {
|
|
567
|
-
this.cleanupStaleJobs();
|
|
568
603
|
this.reEnqueueExpiredJobs();
|
|
569
604
|
const oldestEpochToKeep = this.oldestEpochToKeep();
|
|
570
605
|
if (oldestEpochToKeep > 0) {
|
|
606
|
+
this.cleanupJobsOlderThanEpoch(EpochNumber(oldestEpochToKeep));
|
|
571
607
|
await this.database.deleteAllProvingJobsOlderThanEpoch(EpochNumber(oldestEpochToKeep));
|
|
572
608
|
this.logger.trace(`Deleted all epochs older than ${oldestEpochToKeep}`);
|
|
573
609
|
}
|
|
574
610
|
}
|
|
575
611
|
|
|
576
|
-
private
|
|
612
|
+
private cleanupJobsOlderThanEpoch(epochNumber: EpochNumber) {
|
|
577
613
|
const jobIds = Array.from(this.jobsCache.keys());
|
|
578
614
|
const jobsToClean: ProvingJobId[] = [];
|
|
579
615
|
for (const id of jobIds) {
|
|
580
616
|
const job = this.jobsCache.get(id)!;
|
|
581
|
-
if (
|
|
617
|
+
if (job.epochNumber < epochNumber) {
|
|
582
618
|
jobsToClean.push(id);
|
|
583
619
|
}
|
|
584
620
|
}
|
|
@@ -602,10 +638,26 @@ export class ProvingBroker implements ProvingJobProducer, ProvingJobConsumer, Tr
|
|
|
602
638
|
const now = this.msTimeSource();
|
|
603
639
|
const msSinceLastUpdate = now - metadata.lastUpdatedAt;
|
|
604
640
|
if (msSinceLastUpdate >= this.jobTimeoutMs) {
|
|
605
|
-
this.logger.warn(`Proving job id=${id} timed out. Adding it back to the queue.`, { provingJobId: id });
|
|
606
641
|
this.inProgress.delete(id);
|
|
607
|
-
this.enqueueJobInternal(item);
|
|
608
642
|
this.instrumentation.incTimedOutJobs(item.type);
|
|
643
|
+
|
|
644
|
+
const retries = this.retries.get(id) ?? 0;
|
|
645
|
+
if (retries + 1 < this.maxRetries && !this.isJobStale(item)) {
|
|
646
|
+
this.logger.warn(`Proving job id=${id} timed out. Re-enqueueing (retry ${retries + 1}/${this.maxRetries}).`, {
|
|
647
|
+
provingJobId: id,
|
|
648
|
+
});
|
|
649
|
+
this.retries.set(id, retries + 1);
|
|
650
|
+
this.enqueueJobInternal(item);
|
|
651
|
+
} else {
|
|
652
|
+
this.logger.error(`Proving job id=${id} timed out after ${retries + 1} attempts. Marking as failed.`, {
|
|
653
|
+
provingJobId: id,
|
|
654
|
+
});
|
|
655
|
+
const result: ProvingJobSettledResult = { status: 'rejected', reason: 'Timed out' };
|
|
656
|
+
this.resultsCache.set(id, result);
|
|
657
|
+
this.promises.get(id)?.resolve(result);
|
|
658
|
+
this.completedJobNotifications.push(id);
|
|
659
|
+
this.instrumentation.incRejectedJobs(item.type);
|
|
660
|
+
}
|
|
609
661
|
}
|
|
610
662
|
}
|
|
611
663
|
}
|
|
@@ -11,7 +11,14 @@ import {
|
|
|
11
11
|
ProvingJobSettledResult,
|
|
12
12
|
getEpochFromProvingJobId,
|
|
13
13
|
} from '@aztec/stdlib/interfaces/server';
|
|
14
|
-
import {
|
|
14
|
+
import {
|
|
15
|
+
Attributes,
|
|
16
|
+
LmdbMetrics,
|
|
17
|
+
type TelemetryClient,
|
|
18
|
+
type Tracer,
|
|
19
|
+
getTelemetryClient,
|
|
20
|
+
trackSpan,
|
|
21
|
+
} from '@aztec/telemetry-client';
|
|
15
22
|
|
|
16
23
|
import { mkdir, readdir } from 'fs/promises';
|
|
17
24
|
import { join } from 'path';
|
|
@@ -78,6 +85,8 @@ export class KVBrokerDatabase implements ProvingBrokerDatabase {
|
|
|
78
85
|
|
|
79
86
|
private batchQueue: BatchQueue<ProvingJob | [ProvingJobId, ProvingJobSettledResult], number>;
|
|
80
87
|
|
|
88
|
+
public readonly tracer: Tracer;
|
|
89
|
+
|
|
81
90
|
private constructor(
|
|
82
91
|
private epochs: Map<number, SingleEpochDatabase>,
|
|
83
92
|
private config: ProverBrokerConfig,
|
|
@@ -92,6 +101,8 @@ export class KVBrokerDatabase implements ProvingBrokerDatabase {
|
|
|
92
101
|
() => this.estimateSize(),
|
|
93
102
|
);
|
|
94
103
|
|
|
104
|
+
this.tracer = client.getTracer('KVBrokerDatabase');
|
|
105
|
+
|
|
95
106
|
this.batchQueue = new BatchQueue(
|
|
96
107
|
(items, key) => this.commitWrites(items, key),
|
|
97
108
|
config.proverBrokerBatchSize,
|
|
@@ -143,7 +154,7 @@ export class KVBrokerDatabase implements ProvingBrokerDatabase {
|
|
|
143
154
|
const db = await openVersionedStoreAt(
|
|
144
155
|
fullDirectory,
|
|
145
156
|
SingleEpochDatabase.SCHEMA_VERSION,
|
|
146
|
-
config.
|
|
157
|
+
config.rollupAddress,
|
|
147
158
|
config.dataStoreMapSizeKb,
|
|
148
159
|
);
|
|
149
160
|
const epochDb = new SingleEpochDatabase(db);
|
|
@@ -165,6 +176,9 @@ export class KVBrokerDatabase implements ProvingBrokerDatabase {
|
|
|
165
176
|
}
|
|
166
177
|
}
|
|
167
178
|
|
|
179
|
+
@trackSpan('KVBrokerDatabase.deleteAllProvingJobsOlderThanEpoch', epochNumber => ({
|
|
180
|
+
[Attributes.EPOCH_NUMBER]: epochNumber,
|
|
181
|
+
}))
|
|
168
182
|
async deleteAllProvingJobsOlderThanEpoch(epochNumber: EpochNumber): Promise<void> {
|
|
169
183
|
const oldEpochs = Array.from(this.epochs.keys()).filter(e => e < Number(epochNumber));
|
|
170
184
|
for (const old of oldEpochs) {
|
|
@@ -208,7 +222,7 @@ export class KVBrokerDatabase implements ProvingBrokerDatabase {
|
|
|
208
222
|
const db = await openVersionedStoreAt(
|
|
209
223
|
newEpochDirectory,
|
|
210
224
|
SingleEpochDatabase.SCHEMA_VERSION,
|
|
211
|
-
this.config.
|
|
225
|
+
this.config.rollupAddress,
|
|
212
226
|
this.config.dataStoreMapSizeKb,
|
|
213
227
|
);
|
|
214
228
|
epochDb = new SingleEpochDatabase(db);
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
type ObservableResult,
|
|
9
9
|
type TelemetryClient,
|
|
10
10
|
type UpDownCounter,
|
|
11
|
-
|
|
11
|
+
createUpDownCounterWithDefault,
|
|
12
12
|
} from '@aztec/telemetry-client';
|
|
13
13
|
|
|
14
14
|
export type MonitorCallback = (proofType: ProvingRequestType) => number;
|
|
@@ -18,6 +18,7 @@ export class ProvingBrokerInstrumentation {
|
|
|
18
18
|
private activeJobs: ObservableGauge;
|
|
19
19
|
private resolvedJobs: UpDownCounter;
|
|
20
20
|
private rejectedJobs: UpDownCounter;
|
|
21
|
+
private abortedJobs: UpDownCounter;
|
|
21
22
|
private timedOutJobs: UpDownCounter;
|
|
22
23
|
private cachedJobs: UpDownCounter;
|
|
23
24
|
private totalJobs: UpDownCounter;
|
|
@@ -28,49 +29,30 @@ export class ProvingBrokerInstrumentation {
|
|
|
28
29
|
constructor(client: TelemetryClient, name = 'ProvingBroker') {
|
|
29
30
|
const meter = client.getMeter(name);
|
|
30
31
|
|
|
31
|
-
this.queueSize = meter.createObservableGauge(Metrics.PROVING_QUEUE_SIZE
|
|
32
|
-
valueType: ValueType.INT,
|
|
33
|
-
});
|
|
32
|
+
this.queueSize = meter.createObservableGauge(Metrics.PROVING_QUEUE_SIZE);
|
|
34
33
|
|
|
35
|
-
this.activeJobs = meter.createObservableGauge(Metrics.PROVING_QUEUE_ACTIVE_JOBS
|
|
36
|
-
valueType: ValueType.INT,
|
|
37
|
-
});
|
|
34
|
+
this.activeJobs = meter.createObservableGauge(Metrics.PROVING_QUEUE_ACTIVE_JOBS);
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
});
|
|
36
|
+
const provingJobTypes = Object.values(ProvingRequestType).filter(v => typeof v === 'string');
|
|
37
|
+
const provingJobAttrs = { [Attributes.PROVING_JOB_TYPE]: provingJobTypes };
|
|
42
38
|
|
|
43
|
-
this.
|
|
44
|
-
valueType: ValueType.INT,
|
|
45
|
-
});
|
|
39
|
+
this.resolvedJobs = createUpDownCounterWithDefault(meter, Metrics.PROVING_QUEUE_RESOLVED_JOBS, provingJobAttrs);
|
|
46
40
|
|
|
47
|
-
this.
|
|
48
|
-
valueType: ValueType.INT,
|
|
49
|
-
});
|
|
41
|
+
this.rejectedJobs = createUpDownCounterWithDefault(meter, Metrics.PROVING_QUEUE_REJECTED_JOBS, provingJobAttrs);
|
|
50
42
|
|
|
51
|
-
this.
|
|
52
|
-
valueType: ValueType.INT,
|
|
53
|
-
});
|
|
43
|
+
this.abortedJobs = createUpDownCounterWithDefault(meter, Metrics.PROVING_QUEUE_ABORTED_JOBS, provingJobAttrs);
|
|
54
44
|
|
|
55
|
-
this.
|
|
56
|
-
valueType: ValueType.INT,
|
|
57
|
-
});
|
|
45
|
+
this.retriedJobs = createUpDownCounterWithDefault(meter, Metrics.PROVING_QUEUE_RETRIED_JOBS, provingJobAttrs);
|
|
58
46
|
|
|
59
|
-
this.
|
|
60
|
-
valueType: ValueType.INT,
|
|
61
|
-
});
|
|
47
|
+
this.timedOutJobs = createUpDownCounterWithDefault(meter, Metrics.PROVING_QUEUE_TIMED_OUT_JOBS, provingJobAttrs);
|
|
62
48
|
|
|
63
|
-
this.
|
|
64
|
-
description: 'Records how long a job sits in the queue',
|
|
65
|
-
unit: 'ms',
|
|
66
|
-
valueType: ValueType.INT,
|
|
67
|
-
});
|
|
49
|
+
this.cachedJobs = createUpDownCounterWithDefault(meter, Metrics.PROVING_QUEUE_CACHED_JOBS, provingJobAttrs);
|
|
68
50
|
|
|
69
|
-
this.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
51
|
+
this.totalJobs = createUpDownCounterWithDefault(meter, Metrics.PROVING_QUEUE_TOTAL_JOBS, provingJobAttrs);
|
|
52
|
+
|
|
53
|
+
this.jobWait = meter.createHistogram(Metrics.PROVING_QUEUE_JOB_WAIT);
|
|
54
|
+
|
|
55
|
+
this.jobDuration = meter.createHistogram(Metrics.PROVING_QUEUE_JOB_DURATION);
|
|
74
56
|
}
|
|
75
57
|
|
|
76
58
|
monitorQueueDepth(fn: MonitorCallback) {
|
|
@@ -93,6 +75,12 @@ export class ProvingBrokerInstrumentation {
|
|
|
93
75
|
});
|
|
94
76
|
}
|
|
95
77
|
|
|
78
|
+
incAbortedJobs(proofType: ProvingRequestType) {
|
|
79
|
+
this.abortedJobs.add(1, {
|
|
80
|
+
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
96
84
|
incRetriedJobs(proofType: ProvingRequestType) {
|
|
97
85
|
this.retriedJobs.add(1, {
|
|
98
86
|
[Attributes.PROVING_JOB_TYPE]: ProvingRequestType[proofType],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EpochNumber } from '@aztec/foundation/branded-types';
|
|
2
|
-
import { randomBytes } from '@aztec/foundation/crypto';
|
|
2
|
+
import { randomBytes } from '@aztec/foundation/crypto/random';
|
|
3
3
|
import { AbortError } from '@aztec/foundation/error';
|
|
4
|
-
import { createLogger } from '@aztec/foundation/log';
|
|
4
|
+
import { type Logger, type LoggerBindings, createLogger } from '@aztec/foundation/log';
|
|
5
5
|
import type {
|
|
6
6
|
ProvingJobId,
|
|
7
7
|
ProvingJobInputs,
|
|
@@ -21,6 +21,7 @@ export class ProvingJobController {
|
|
|
21
21
|
private promise?: Promise<void>;
|
|
22
22
|
private abortController = new AbortController();
|
|
23
23
|
private result?: ProvingJobResultsMap[ProvingRequestType] | Error;
|
|
24
|
+
private log: Logger;
|
|
24
25
|
|
|
25
26
|
constructor(
|
|
26
27
|
private jobId: ProvingJobId,
|
|
@@ -29,8 +30,13 @@ export class ProvingJobController {
|
|
|
29
30
|
private startedAt: number,
|
|
30
31
|
private circuitProver: ServerCircuitProver,
|
|
31
32
|
private onComplete: () => void,
|
|
32
|
-
|
|
33
|
-
) {
|
|
33
|
+
bindings?: LoggerBindings,
|
|
34
|
+
) {
|
|
35
|
+
this.log = createLogger('prover-client:proving-agent:job-controller', {
|
|
36
|
+
instanceId: randomBytes(4).toString('hex'),
|
|
37
|
+
...bindings,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
34
40
|
|
|
35
41
|
public start(): void {
|
|
36
42
|
if (this.status !== ProvingJobControllerStatus.IDLE) {
|
|
@@ -125,8 +131,7 @@ export class ProvingJobController {
|
|
|
125
131
|
const signal = this.abortController.signal;
|
|
126
132
|
switch (type) {
|
|
127
133
|
case ProvingRequestType.PUBLIC_VM: {
|
|
128
|
-
|
|
129
|
-
return await this.circuitProver.getAvmProof(inputs, undefined, signal, this.epochNumber);
|
|
134
|
+
return await this.circuitProver.getAvmProof(inputs, signal, this.epochNumber);
|
|
130
135
|
}
|
|
131
136
|
|
|
132
137
|
case ProvingRequestType.PUBLIC_CHONK_VERIFIER: {
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import { EpochNumberSchema } from '@aztec/foundation/branded-types';
|
|
1
2
|
import { createSafeJsonRpcClient } from '@aztec/foundation/json-rpc/client';
|
|
2
3
|
import {
|
|
3
4
|
type GetProvingJobResponse,
|
|
4
5
|
ProofUri,
|
|
5
6
|
ProvingJob,
|
|
6
7
|
type ProvingJobBroker,
|
|
8
|
+
type ProvingJobBrokerDebug,
|
|
7
9
|
type ProvingJobConsumer,
|
|
8
10
|
ProvingJobId,
|
|
9
11
|
type ProvingJobProducer,
|
|
@@ -16,6 +18,15 @@ import { makeTracedFetch } from '@aztec/telemetry-client';
|
|
|
16
18
|
|
|
17
19
|
import { z } from 'zod';
|
|
18
20
|
|
|
21
|
+
/** Indefinite backoff for broker communication: 1, 1, 1, 2, 4, 4, 4, ... seconds. */
|
|
22
|
+
export function* proverBrokerBackoff() {
|
|
23
|
+
const v = [1, 1, 1, 2, 4];
|
|
24
|
+
let i = 0;
|
|
25
|
+
while (true) {
|
|
26
|
+
yield v[Math.min(i++, v.length - 1)];
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
19
30
|
const ProvingJobFilterSchema = z.object({
|
|
20
31
|
allowList: z.array(z.nativeEnum(ProvingRequestType)),
|
|
21
32
|
});
|
|
@@ -26,26 +37,29 @@ const GetProvingJobResponse = z.object({
|
|
|
26
37
|
});
|
|
27
38
|
|
|
28
39
|
export const ProvingJobProducerSchema: ApiSchemaFor<ProvingJobProducer> = {
|
|
29
|
-
enqueueProvingJob: z.function(
|
|
30
|
-
getProvingJobStatus: z.function(
|
|
31
|
-
cancelProvingJob: z.function(
|
|
32
|
-
getCompletedJobs: z.function(
|
|
40
|
+
enqueueProvingJob: z.function({ input: z.tuple([ProvingJob]), output: ProvingJobStatus }),
|
|
41
|
+
getProvingJobStatus: z.function({ input: z.tuple([ProvingJobId]), output: ProvingJobStatus }),
|
|
42
|
+
cancelProvingJob: z.function({ input: z.tuple([ProvingJobId]), output: z.void() }),
|
|
43
|
+
getCompletedJobs: z.function({ input: z.tuple([z.array(ProvingJobId)]), output: z.array(ProvingJobId) }),
|
|
33
44
|
};
|
|
34
45
|
|
|
35
46
|
export const ProvingJobConsumerSchema: ApiSchemaFor<ProvingJobConsumer> = {
|
|
36
|
-
getProvingJob: z.function(
|
|
37
|
-
|
|
38
|
-
.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
.
|
|
47
|
-
|
|
48
|
-
|
|
47
|
+
getProvingJob: z.function({
|
|
48
|
+
input: z.tuple([optional(ProvingJobFilterSchema)]),
|
|
49
|
+
output: GetProvingJobResponse.optional(),
|
|
50
|
+
}),
|
|
51
|
+
reportProvingJobError: z.function({
|
|
52
|
+
input: z.tuple([ProvingJobId, z.string(), optional(z.boolean()), optional(ProvingJobFilterSchema)]),
|
|
53
|
+
output: GetProvingJobResponse.optional(),
|
|
54
|
+
}),
|
|
55
|
+
reportProvingJobProgress: z.function({
|
|
56
|
+
input: z.tuple([ProvingJobId, z.number(), optional(ProvingJobFilterSchema)]),
|
|
57
|
+
output: GetProvingJobResponse.optional(),
|
|
58
|
+
}),
|
|
59
|
+
reportProvingJobSuccess: z.function({
|
|
60
|
+
input: z.tuple([ProvingJobId, ProofUri, optional(ProvingJobFilterSchema)]),
|
|
61
|
+
output: GetProvingJobResponse.optional(),
|
|
62
|
+
}),
|
|
49
63
|
};
|
|
50
64
|
|
|
51
65
|
export const ProvingJobBrokerSchema: ApiSchemaFor<ProvingJobBroker> = {
|
|
@@ -53,10 +67,22 @@ export const ProvingJobBrokerSchema: ApiSchemaFor<ProvingJobBroker> = {
|
|
|
53
67
|
...ProvingJobProducerSchema,
|
|
54
68
|
};
|
|
55
69
|
|
|
70
|
+
export const ProvingJobBrokerDebugSchema: ApiSchemaFor<ProvingJobBrokerDebug> = {
|
|
71
|
+
replayProvingJob: z.function({
|
|
72
|
+
input: z.tuple([ProvingJobId, z.nativeEnum(ProvingRequestType), EpochNumberSchema, ProofUri]),
|
|
73
|
+
output: ProvingJobStatus,
|
|
74
|
+
}),
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const ProvingJobBrokerSchemaWithDebug: ApiSchemaFor<ProvingJobBroker & ProvingJobBrokerDebug> = {
|
|
78
|
+
...ProvingJobBrokerSchema,
|
|
79
|
+
...ProvingJobBrokerDebugSchema,
|
|
80
|
+
};
|
|
81
|
+
|
|
56
82
|
export function createProvingJobBrokerClient(
|
|
57
83
|
url: string,
|
|
58
84
|
versions: Partial<ComponentsVersions>,
|
|
59
|
-
fetch = makeTracedFetch(
|
|
85
|
+
fetch = makeTracedFetch(proverBrokerBackoff, false),
|
|
60
86
|
): ProvingJobBroker {
|
|
61
87
|
return createSafeJsonRpcClient(url, ProvingJobBrokerSchema, {
|
|
62
88
|
namespaceMethods: 'proverBroker',
|
|
@@ -68,7 +94,7 @@ export function createProvingJobBrokerClient(
|
|
|
68
94
|
export function createProvingJobProducerClient(
|
|
69
95
|
url: string,
|
|
70
96
|
versions: Partial<ComponentsVersions>,
|
|
71
|
-
fetch = makeTracedFetch(
|
|
97
|
+
fetch = makeTracedFetch(proverBrokerBackoff, false),
|
|
72
98
|
): ProvingJobProducer {
|
|
73
99
|
return createSafeJsonRpcClient(url, ProvingJobProducerSchema, {
|
|
74
100
|
namespaceMethods: 'provingJobProducer',
|
|
@@ -80,7 +106,7 @@ export function createProvingJobProducerClient(
|
|
|
80
106
|
export function createProvingJobConsumerClient(
|
|
81
107
|
url: string,
|
|
82
108
|
versions: Partial<ComponentsVersions>,
|
|
83
|
-
fetch = makeTracedFetch(
|
|
109
|
+
fetch = makeTracedFetch(proverBrokerBackoff, false),
|
|
84
110
|
): ProvingJobConsumer {
|
|
85
111
|
return createSafeJsonRpcClient(url, ProvingJobConsumerSchema, {
|
|
86
112
|
namespaceMethods: 'provingJobConsumer',
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { RollupCheatCodes } from '@aztec/ethereum/test';
|
|
2
|
+
import type { CheckpointNumber, EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
|
|
3
|
+
import type { Fr } from '@aztec/foundation/curves/bn254';
|
|
4
|
+
import type { Logger } from '@aztec/foundation/log';
|
|
5
|
+
import type { L2BlockSource } from '@aztec/stdlib/block';
|
|
6
|
+
import { computeEpochOutHash } from '@aztec/stdlib/messaging';
|
|
7
|
+
|
|
8
|
+
/** Arguments for {@link settleEpochOutbox}. */
|
|
9
|
+
export type SettleEpochOutboxArgs = {
|
|
10
|
+
/** Cheat codes used to write the computed out hash directly into the L1 Outbox storage. */
|
|
11
|
+
rollupCheatCodes: RollupCheatCodes;
|
|
12
|
+
/** Source of checkpointed L2 blocks for the epoch being settled. */
|
|
13
|
+
l2BlockSource: L2BlockSource;
|
|
14
|
+
/** Epoch to settle. */
|
|
15
|
+
epoch: EpochNumber;
|
|
16
|
+
/**
|
|
17
|
+
* When set, only checkpoints up to and including this number are covered. Used to settle a partial
|
|
18
|
+
* epoch (the AZIP-14 Outbox keeps one root per `numCheckpointsInEpoch`, so a prefix of an epoch can
|
|
19
|
+
* be settled and consumed before the epoch completes). When omitted, every checkpointed block in the
|
|
20
|
+
* epoch is covered.
|
|
21
|
+
*/
|
|
22
|
+
maxCheckpoint?: CheckpointNumber;
|
|
23
|
+
log: Logger;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Computes the epoch out hash over the checkpointed blocks of an epoch (optionally only up to
|
|
28
|
+
* `maxCheckpoint`) and writes it into the L1 Outbox via cheat codes. This is the synthetic,
|
|
29
|
+
* no-prover equivalent of an epoch root proof landing on L1: it makes the L2-to-L1 messages in the
|
|
30
|
+
* covered checkpoints consumable. It does NOT advance the rollup's proven tip — callers
|
|
31
|
+
* `markAsProven` separately so a single prove call can settle multiple epochs before marking proven.
|
|
32
|
+
*
|
|
33
|
+
* Used by the test-only proving drivers: the `AutomineSequencer`'s auto-settle loop and the standalone
|
|
34
|
+
* `EpochTestSettler`. Lives here (rather than in either consumer) so both share one implementation.
|
|
35
|
+
*
|
|
36
|
+
* @returns The last checkpoint number covered by the settled range, or `undefined` if the epoch has
|
|
37
|
+
* no checkpointed blocks (within the `maxCheckpoint` bound).
|
|
38
|
+
*/
|
|
39
|
+
export async function settleEpochOutbox({
|
|
40
|
+
rollupCheatCodes,
|
|
41
|
+
l2BlockSource,
|
|
42
|
+
epoch,
|
|
43
|
+
maxCheckpoint,
|
|
44
|
+
log,
|
|
45
|
+
}: SettleEpochOutboxArgs): Promise<CheckpointNumber | undefined> {
|
|
46
|
+
let blocks = await l2BlockSource.getBlocks({ epoch, onlyCheckpointed: true });
|
|
47
|
+
if (maxCheckpoint !== undefined) {
|
|
48
|
+
blocks = blocks.filter(block => block.checkpointNumber <= maxCheckpoint);
|
|
49
|
+
}
|
|
50
|
+
if (blocks.length === 0) {
|
|
51
|
+
return undefined;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
log.info(
|
|
55
|
+
`Settling epoch ${epoch}${maxCheckpoint !== undefined ? ` up to checkpoint ${maxCheckpoint}` : ''} with blocks ${blocks[0]?.header.getBlockNumber()} to ${blocks.at(-1)?.header.getBlockNumber()}`,
|
|
56
|
+
{ epoch, maxCheckpoint, blocks: blocks.map(block => block.toBlockInfo()) },
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const messagesInEpoch: Fr[][][][] = [];
|
|
60
|
+
// Undefined (not SlotNumber.ZERO) so a first checkpointed block at slot 0 still opens checkpoint 0.
|
|
61
|
+
let previousSlotNumber: SlotNumber | undefined;
|
|
62
|
+
let checkpointIndex = -1;
|
|
63
|
+
|
|
64
|
+
for (const block of blocks) {
|
|
65
|
+
const slotNumber = block.header.globalVariables.slotNumber;
|
|
66
|
+
if (slotNumber !== previousSlotNumber) {
|
|
67
|
+
checkpointIndex++;
|
|
68
|
+
messagesInEpoch[checkpointIndex] = [];
|
|
69
|
+
previousSlotNumber = slotNumber;
|
|
70
|
+
}
|
|
71
|
+
messagesInEpoch[checkpointIndex].push(block.body.txEffects.map(txEffect => txEffect.l2ToL1Msgs));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const outHash = computeEpochOutHash(messagesInEpoch);
|
|
75
|
+
if (!outHash.isZero()) {
|
|
76
|
+
await rollupCheatCodes.insertOutbox(epoch, messagesInEpoch.length, outHash.toBigInt());
|
|
77
|
+
} else {
|
|
78
|
+
log.info(`No L2 to L1 messages in epoch ${epoch}`, { epoch });
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return blocks.at(-1)?.checkpointNumber;
|
|
82
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { settleEpochOutbox, type SettleEpochOutboxArgs } from './epoch_settlement.js';
|