diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index 4803597e7cb7..e7194796bd1a 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -149,6 +149,7 @@ export type EnvVar = | 'PROVER_COORDINATION_NODE_URLS' | 'PROVER_FAILED_PROOF_STORE' | 'PROVER_NODE_FAILED_EPOCH_STORE' + | 'PROVER_NODE_DISABLE_PROOF_PUBLISH' | 'PROVER_ID' | 'PROVER_NODE_POLLING_INTERVAL_MS' | 'PROVER_NODE_MAX_PENDING_JOBS' diff --git a/yarn-project/prover-node/src/config.ts b/yarn-project/prover-node/src/config.ts index bf1cc7634443..33bcfd274524 100644 --- a/yarn-project/prover-node/src/config.ts +++ b/yarn-project/prover-node/src/config.ts @@ -1,7 +1,12 @@ import { type ArchiverConfig, archiverConfigMappings } from '@aztec/archiver/config'; import type { ACVMConfig, BBConfig } from '@aztec/bb-prover/config'; import { type GenesisStateConfig, genesisStateConfigMappings } from '@aztec/ethereum'; -import { type ConfigMappingsType, getConfigFromMappings, numberConfigHelper } from '@aztec/foundation/config'; +import { + type ConfigMappingsType, + booleanConfigHelper, + getConfigFromMappings, + numberConfigHelper, +} from '@aztec/foundation/config'; import { type DataStoreConfig, dataConfigMappings } from '@aztec/kv-store/config'; import { type KeyStore, type KeyStoreConfig, ethPrivateKeySchema, keyStoreConfigMappings } from '@aztec/node-keystore'; import { type SharedNodeConfig, sharedNodeConfigMappings } from '@aztec/node-lib/config'; @@ -39,6 +44,7 @@ export type SpecificProverNodeConfig = { proverNodeMaxParallelBlocksPerEpoch: number; proverNodeFailedEpochStore: string | undefined; proverNodeEpochProvingDelayMs: number | undefined; + proverNodeDisableProofPublish?: boolean; txGatheringTimeoutMs: number; txGatheringIntervalMs: number; txGatheringBatchSize: number; @@ -90,6 +96,11 @@ const specificProverNodeConfigMappings: ConfigMappingsType = { diff --git a/yarn-project/prover-node/src/job/epoch-proving-job.test.ts b/yarn-project/prover-node/src/job/epoch-proving-job.test.ts index f05b4d6b5e43..06cae5d93389 100644 --- a/yarn-project/prover-node/src/job/epoch-proving-job.test.ts +++ b/yarn-project/prover-node/src/job/epoch-proving-job.test.ts @@ -50,7 +50,7 @@ describe('epoch-proving-job', () => { const proverId = EthAddress.random(); // Subject factory - const createJob = (opts: { deadline?: Date; parallelBlockLimit?: number } = {}) => { + const createJob = (opts: { deadline?: Date; parallelBlockLimit?: number; skipSubmitProof?: boolean } = {}) => { const txsMap = new Map(txs.map(tx => [tx.getTxHash().toString(), tx])); const data: EpochProvingJobData = { @@ -70,7 +70,7 @@ describe('epoch-proving-job', () => { l2BlockSource, metrics, opts.deadline, - { parallelBlockLimit: opts.parallelBlockLimit ?? 32 }, + { parallelBlockLimit: opts.parallelBlockLimit ?? 32, skipSubmitProof: opts.skipSubmitProof }, ); }; @@ -205,4 +205,13 @@ describe('epoch-proving-job', () => { expect(publisher.submitEpochProof).not.toHaveBeenCalled(); expect(prover.cancel).toHaveBeenCalled(); }); + + it('skips publishing when skipSubmitProof is enabled', async () => { + const job = createJob({ skipSubmitProof: true }); + await job.run(); + + expect(job.getState()).toEqual('completed'); + expect(prover.finalizeEpoch).toHaveBeenCalled(); + expect(publisher.submitEpochProof).not.toHaveBeenCalled(); + }); }); diff --git a/yarn-project/prover-node/src/job/epoch-proving-job.ts b/yarn-project/prover-node/src/job/epoch-proving-job.ts index 3e36a36bde7f..55cee3905eaf 100644 --- a/yarn-project/prover-node/src/job/epoch-proving-job.ts +++ b/yarn-project/prover-node/src/job/epoch-proving-job.ts @@ -27,6 +27,12 @@ import type { ProverNodeJobMetrics } from '../metrics.js'; import type { ProverNodePublisher } from '../prover-node-publisher.js'; import { type EpochProvingJobData, validateEpochProvingJobData } from './epoch-proving-job-data.js'; +export type EpochProvingJobOptions = { + parallelBlockLimit?: number; + skipEpochCheck?: boolean; + skipSubmitProof?: boolean; +}; + /** * Job that grabs a range of blocks from the unfinalized chain from L1, gets their txs given their hashes, * re-executes their public calls, generates a rollup proof, and submits it to L1. This job will update the @@ -52,7 +58,7 @@ export class EpochProvingJob implements Traceable { private l2BlockSource: L2BlockSource | undefined, private metrics: ProverNodeJobMetrics, private deadline: Date | undefined, - private config: { parallelBlockLimit?: number; skipEpochCheck?: boolean }, + private config: EpochProvingJobOptions, ) { validateEpochProvingJobData(data); this.uuid = crypto.randomUUID(); @@ -209,6 +215,15 @@ export class EpochProvingJob implements Traceable { this.progressState('publishing-proof'); + if (this.config.skipSubmitProof) { + this.log.info( + `Proof publishing is disabled. Dropping valid proof for epoch ${epochNumber} (blocks ${fromBlock} to ${toBlock})`, + ); + this.state = 'completed'; + this.metrics.recordProvingJob(executionTime, timer.ms(), epochSizeBlocks, epochSizeTxs); + return; + } + const success = await this.publisher.submitEpochProof({ fromBlock, toBlock, diff --git a/yarn-project/prover-node/src/prover-node-publisher.ts b/yarn-project/prover-node/src/prover-node-publisher.ts index 50942f9b1b16..a0f168d4e636 100644 --- a/yarn-project/prover-node/src/prover-node-publisher.ts +++ b/yarn-project/prover-node/src/prover-node-publisher.ts @@ -99,6 +99,7 @@ export class ProverNodePublisher { }): Promise { const { epochNumber, fromBlock, toBlock } = args; const ctx = { epochNumber, fromBlock, toBlock }; + if (!this.interrupted) { const timer = new Timer(); // Validate epoch proof range and hashes are correct before submitting diff --git a/yarn-project/prover-node/src/prover-node.test.ts b/yarn-project/prover-node/src/prover-node.test.ts index e9e66fb229da..590ff5bfe12e 100644 --- a/yarn-project/prover-node/src/prover-node.test.ts +++ b/yarn-project/prover-node/src/prover-node.test.ts @@ -109,6 +109,7 @@ describe('prover-node', () => { proverNodeFailedEpochStore: undefined, txGatheringTimeoutMs: 1000, proverNodeEpochProvingDelayMs: undefined, + proverNodeDisableProofPublish: false, }; // World state returns a new mock db every time it is asked to fork diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index a120d5f85d27..7fc43b2ed106 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -367,7 +367,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable publisher: ProverNodePublisher, opts: { skipEpochCheck?: boolean } = {}, ) { - const { proverNodeMaxParallelBlocksPerEpoch: parallelBlockLimit } = this.config; + const { proverNodeMaxParallelBlocksPerEpoch: parallelBlockLimit, proverNodeDisableProofPublish } = this.config; return new EpochProvingJob( data, this.worldState, @@ -377,7 +377,7 @@ export class ProverNode implements EpochMonitorHandler, ProverNodeApi, Traceable this.l2BlockSource, this.jobMetrics, deadline, - { parallelBlockLimit, ...opts }, + { parallelBlockLimit, skipSubmitProof: proverNodeDisableProofPublish, ...opts }, ); } diff --git a/yarn-project/sequencer-client/src/publisher/config.ts b/yarn-project/sequencer-client/src/publisher/config.ts index 589e426a0ffc..b0526cf12493 100644 --- a/yarn-project/sequencer-client/src/publisher/config.ts +++ b/yarn-project/sequencer-client/src/publisher/config.ts @@ -48,7 +48,7 @@ export const getTxSenderConfigMappings: ( description: 'The private keys to be used by the publisher.', parseEnv: (val: string) => val.split(',').map(key => new SecretValue(`0x${key.replace('0x', '')}`)), defaultValue: [], - fallback: scope === 'PROVER' ? ['PROVER_PUBLISHER_PRIVATE_KEY'] : ['SEQ_PUBLISHER_PRIVATE_KEY'], + fallback: [scope === 'PROVER' ? `PROVER_PUBLISHER_PRIVATE_KEY` : `SEQ_PUBLISHER_PRIVATE_KEY`], }, publisherAddresses: { env: scope === 'PROVER' ? `PROVER_PUBLISHER_ADDRESSES` : `SEQ_PUBLISHER_ADDRESSES`,