diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index 0fb6a75f9d4..bf5e7016f0e 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -689,18 +689,11 @@ export class AztecNodeService implements AztecNode { } /** - * Returns the currently committed block header. + * Returns the currently committed block header, or the initial header if no blocks have been produced. * @returns The current committed block header. */ public async getHeader(): Promise
{ - const block = await this.getBlock(-1); - if (block) { - return block.header; - } - - // No block was not found so we build the initial header. - const committedDb = await this.#getWorldState('latest'); - return await committedDb.buildInitialHeader(); + return (await this.getBlock(-1))?.header ?? (await this.#getWorldState('latest')).getInitialHeader(); } /** @@ -733,7 +726,7 @@ export class AztecNodeService implements AztecNode { new WASMSimulator(), this.telemetry, ); - const processor = await publicProcessorFactory.create(prevHeader, newGlobalVariables); + const processor = publicProcessorFactory.create(prevHeader, newGlobalVariables); // REFACTOR: Consider merging ProcessReturnValues into ProcessedTx const [processedTxs, failedTxs, returns] = await processor.process([tx]); // REFACTOR: Consider returning the error/revert rather than throwing diff --git a/yarn-project/circuits.js/src/structs/header.ts b/yarn-project/circuits.js/src/structs/header.ts index 4b647f2b851..b8c1b26293d 100644 --- a/yarn-project/circuits.js/src/structs/header.ts +++ b/yarn-project/circuits.js/src/structs/header.ts @@ -35,6 +35,10 @@ export class Header { ] as const; } + static from(fields: FieldsOf
) { + return new Header(...Header.getFields(fields)); + } + getSize() { return ( this.lastArchive.getSize() + @@ -85,14 +89,15 @@ export class Header { ); } - static empty(): Header { - return new Header( - AppendOnlyTreeSnapshot.zero(), - ContentCommitment.empty(), - StateReference.empty(), - GlobalVariables.empty(), - Fr.ZERO, - ); + static empty(fields: Partial> = {}): Header { + return Header.from({ + lastArchive: AppendOnlyTreeSnapshot.zero(), + contentCommitment: ContentCommitment.empty(), + state: StateReference.empty(), + globalVariables: GlobalVariables.empty(), + totalFees: Fr.ZERO, + ...fields, + }); } isEmpty(): boolean { diff --git a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts index 9830256a186..a71ff1b65ba 100644 --- a/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts +++ b/yarn-project/end-to-end/src/composed/integration_l1_publisher.test.ts @@ -158,18 +158,11 @@ describe('L1Publisher integration', () => { coinbase = config.coinbase || EthAddress.random(); feeRecipient = config.feeRecipient || AztecAddress.random(); - prevHeader = await builderDb.buildInitialHeader(false); + prevHeader = builderDb.getInitialHeader(); }); - const makeEmptyProcessedTx = () => { - const tx = makeEmptyProcessedTxFromHistoricalTreeRoots( - prevHeader, - new Fr(chainId), - new Fr(config.version), - getVKTreeRoot(), - ); - return tx; - }; + const makeEmptyProcessedTx = () => + makeEmptyProcessedTxFromHistoricalTreeRoots(prevHeader, new Fr(chainId), new Fr(config.version), getVKTreeRoot()); const makeBloatedProcessedTx = (seed = 0x1): ProcessedTx => { const tx = mockTx(seed); diff --git a/yarn-project/prover-client/src/mocks/fixtures.ts b/yarn-project/prover-client/src/mocks/fixtures.ts index 16a99350135..3d743ca38ed 100644 --- a/yarn-project/prover-client/src/mocks/fixtures.ts +++ b/yarn-project/prover-client/src/mocks/fixtures.ts @@ -96,12 +96,12 @@ export async function getSimulationProvider( return new WASMSimulator(); } -export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, seed = 0x1) => { +export const makeBloatedProcessedTx = (builderDb: MerkleTreeOperations, seed = 0x1) => { seed *= MAX_NULLIFIERS_PER_TX; // Ensure no clashing given incremental seeds const tx = mockTx(seed); const kernelOutput = KernelCircuitPublicInputs.empty(); kernelOutput.constants.vkTreeRoot = getVKTreeRoot(); - kernelOutput.constants.historicalHeader = await builderDb.buildInitialHeader(); + kernelOutput.constants.historicalHeader = builderDb.getInitialHeader(); kernelOutput.end.publicDataUpdateRequests = makeTuple( MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, i => new PublicDataUpdateRequest(fr(i), fr(i + 10), i + 20), @@ -127,8 +127,8 @@ export const makeBloatedProcessedTx = async (builderDb: MerkleTreeOperations, se return processedTx; }; -export const makeEmptyProcessedTx = async (builderDb: MerkleTreeOperations, chainId: Fr, version: Fr) => { - const header = await builderDb.buildInitialHeader(); +export const makeEmptyProcessedTx = (builderDb: MerkleTreeOperations, chainId: Fr, version: Fr) => { + const header = builderDb.getInitialHeader(); return makeEmptyProcessedTxFromHistoricalTreeRoots(header, chainId, version, getVKTreeRoot()); }; @@ -178,6 +178,5 @@ export const makeGlobals = (blockNumber: number) => { ); }; -export const makeEmptyProcessedTestTx = (builderDb: MerkleTreeOperations): Promise => { - return makeEmptyProcessedTx(builderDb, Fr.ZERO, Fr.ZERO); -}; +export const makeEmptyProcessedTestTx = (builderDb: MerkleTreeOperations): ProcessedTx => + makeEmptyProcessedTx(builderDb, Fr.ZERO, Fr.ZERO); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 90c3ec5fb03..0e78d0c7a89 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -31,7 +31,6 @@ import { type BaseRollupInputs, Fr, type GlobalVariables, - type Header, type KernelCircuitPublicInputs, L1_TO_L2_MSG_SUBTREE_HEIGHT, L1_TO_L2_MSG_SUBTREE_SIBLING_PATH_LENGTH, @@ -98,12 +97,7 @@ export class ProvingOrchestrator { public readonly tracer: Tracer; - constructor( - private db: MerkleTreeOperations, - private prover: ServerCircuitProver, - telemetryClient: TelemetryClient, - private initialHeader?: Header, - ) { + constructor(private db: MerkleTreeOperations, private prover: ServerCircuitProver, telemetryClient: TelemetryClient) { this.tracer = telemetryClient.getTracer('ProvingOrchestrator'); } @@ -131,11 +125,6 @@ export class ProvingOrchestrator { globalVariables: GlobalVariables, l1ToL2Messages: Fr[], ): Promise { - // Create initial header if not done so yet - if (!this.initialHeader) { - this.initialHeader = await this.db.getInitialHeader(); - } - if (!Number.isInteger(numTxs) || numTxs < 2) { throw new Error(`Length of txs for the block should be at least two (got ${numTxs})`); } @@ -268,7 +257,7 @@ export class ProvingOrchestrator { // base rollup inputs // Then enqueue the proving of all the transactions const unprovenPaddingTx = makeEmptyProcessedTx( - this.initialHeader ?? (await this.db.getInitialHeader()), + this.db.getInitialHeader(), this.provingState.globalVariables.chainId, this.provingState.globalVariables.version, getVKTreeRoot(), @@ -564,7 +553,7 @@ export class ProvingOrchestrator { const getBaseInputsEmptyTx = async () => { const inputs = { - header: await this.db.getInitialHeader(), + header: this.db.getInitialHeader(), chainId: tx.data.constants.globalVariables.chainId, version: tx.data.constants.globalVariables.version, vkTreeRoot: tx.data.constants.vkTreeRoot, diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts index ade0c83053e..768304c77a0 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_errors.test.ts @@ -22,12 +22,12 @@ describe('prover/orchestrator/errors', () => { describe('errors', () => { it('throws if adding too many transactions', async () => { - const txs = await Promise.all([ + const txs = [ makeBloatedProcessedTx(context.actualDb, 1), makeBloatedProcessedTx(context.actualDb, 2), makeBloatedProcessedTx(context.actualDb, 3), makeBloatedProcessedTx(context.actualDb, 4), - ]); + ]; const blockTicket = await context.orchestrator.startNewBlock(txs.length, context.globalVariables, []); @@ -36,7 +36,7 @@ describe('prover/orchestrator/errors', () => { } await expect( - async () => await context.orchestrator.addNewTx(await makeEmptyProcessedTestTx(context.actualDb)), + async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx(context.actualDb)), ).rejects.toThrow('Rollup not accepting further transactions'); const result = await blockTicket.provingPromise; @@ -48,7 +48,7 @@ describe('prover/orchestrator/errors', () => { it('throws if adding a transaction before start', async () => { await expect( - async () => await context.orchestrator.addNewTx(await makeEmptyProcessedTestTx(context.actualDb)), + async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx(context.actualDb)), ).rejects.toThrow(`Invalid proving state, call startNewBlock before adding transactions`); }); @@ -94,7 +94,7 @@ describe('prover/orchestrator/errors', () => { context.orchestrator.cancelBlock(); await expect( - async () => await context.orchestrator.addNewTx(await makeEmptyProcessedTestTx(context.actualDb)), + async () => await context.orchestrator.addNewTx(makeEmptyProcessedTestTx(context.actualDb)), ).rejects.toThrow('Rollup not accepting further transactions'); }); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts index 18797c30105..f23a17c32e1 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_failures.test.ts @@ -65,11 +65,11 @@ describe('prover/orchestrator/failures', () => { ], ] as const)('handles a %s error', async (message: string, fn: () => void) => { fn(); - const txs = await Promise.all([ + const txs = [ makeBloatedProcessedTx(context.actualDb, 1), makeBloatedProcessedTx(context.actualDb, 2), makeBloatedProcessedTx(context.actualDb, 3), - ]); + ]; const blockTicket = await orchestrator.startNewBlock(txs.length, context.globalVariables, []); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts index 20fb077ebf8..4e669651a27 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_lifecycle.test.ts @@ -33,15 +33,9 @@ describe('prover/orchestrator/lifecycle', () => { describe('lifecycle', () => { it('cancels current block and switches to new ones', async () => { - const txs1 = await Promise.all([ - makeBloatedProcessedTx(context.actualDb, 1), - makeBloatedProcessedTx(context.actualDb, 2), - ]); + const txs1 = [makeBloatedProcessedTx(context.actualDb, 1), makeBloatedProcessedTx(context.actualDb, 2)]; - const txs2 = await Promise.all([ - makeBloatedProcessedTx(context.actualDb, 3), - makeBloatedProcessedTx(context.actualDb, 4), - ]); + const txs2 = [makeBloatedProcessedTx(context.actualDb, 3), makeBloatedProcessedTx(context.actualDb, 4)]; const globals1: GlobalVariables = makeGlobals(100); const globals2: GlobalVariables = makeGlobals(101); @@ -79,15 +73,8 @@ describe('prover/orchestrator/lifecycle', () => { }); it('automatically cancels an incomplete block when starting a new one', async () => { - const txs1 = await Promise.all([ - makeBloatedProcessedTx(context.actualDb, 1), - makeBloatedProcessedTx(context.actualDb, 2), - ]); - - const txs2 = await Promise.all([ - makeBloatedProcessedTx(context.actualDb, 3), - makeBloatedProcessedTx(context.actualDb, 4), - ]); + const txs1 = [makeBloatedProcessedTx(context.actualDb, 1), makeBloatedProcessedTx(context.actualDb, 2)]; + const txs2 = [makeBloatedProcessedTx(context.actualDb, 3), makeBloatedProcessedTx(context.actualDb, 4)]; const globals1: GlobalVariables = makeGlobals(100); const globals2: GlobalVariables = makeGlobals(101); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts index cf7ecd749bd..6c959bd9b43 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks.test.ts @@ -22,11 +22,11 @@ describe('prover/orchestrator/mixed-blocks', () => { describe('blocks', () => { it('builds an unbalanced L2 block', async () => { - const txs = await Promise.all([ + const txs = [ makeBloatedProcessedTx(context.actualDb, 1), makeBloatedProcessedTx(context.actualDb, 2), makeBloatedProcessedTx(context.actualDb, 3), - ]); + ]; const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts index 48d429a1e38..838433006f1 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_mixed_blocks_2.test.ts @@ -27,9 +27,7 @@ describe('prover/orchestrator/mixed-blocks', () => { describe('blocks', () => { it.each([2, 4, 5, 8] as const)('builds an L2 block with %i bloated txs', async (totalCount: number) => { - const txs = [ - ...(await Promise.all(times(totalCount, (i: number) => makeBloatedProcessedTx(context.actualDb, i)))), - ]; + const txs = times(totalCount, (i: number) => makeBloatedProcessedTx(context.actualDb, i)); const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts index b87f0a1fe2f..206f562f2a9 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multi_public_functions.test.ts @@ -34,7 +34,7 @@ describe('prover/orchestrator/public-functions', () => { }), ); for (const tx of txs) { - tx.data.constants.historicalHeader = await context.actualDb.buildInitialHeader(); + tx.data.constants.historicalHeader = context.actualDb.getInitialHeader(); tx.data.constants.vkTreeRoot = getVKTreeRoot(); } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts index 193cd667dc4..814461cd36c 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_multiple_blocks.test.ts @@ -21,10 +21,10 @@ describe('prover/orchestrator/multi-block', () => { describe('multiple blocks', () => { it('builds multiple blocks in sequence', async () => { const numBlocks = 5; - let header = await context.actualDb.buildInitialHeader(); + let header = context.actualDb.getInitialHeader(); for (let i = 0; i < numBlocks; i++) { - const tx = await makeBloatedProcessedTx(context.actualDb, i + 1); + const tx = makeBloatedProcessedTx(context.actualDb, i + 1); tx.data.constants.historicalHeader = header; tx.data.constants.vkTreeRoot = getVKTreeRoot(); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts index 73365e3c3e6..0d31974f936 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_public_functions.test.ts @@ -34,7 +34,7 @@ describe('prover/orchestrator/public-functions', () => { numberOfNonRevertiblePublicCallRequests, numberOfRevertiblePublicCallRequests, }); - tx.data.constants.historicalHeader = await context.actualDb.buildInitialHeader(); + tx.data.constants.historicalHeader = context.actualDb.getInitialHeader(); tx.data.constants.vkTreeRoot = getVKTreeRoot(); const [processed, _] = await context.processPublicFunctions([tx], 1, undefined); diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts index b2dca6f6bb2..6afccf9312b 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator_single_blocks.test.ts @@ -39,7 +39,7 @@ describe('prover/orchestrator/blocks', () => { }); it('builds a block with 1 transaction', async () => { - const txs = await Promise.all([makeBloatedProcessedTx(context.actualDb, 1)]); + const txs = [makeBloatedProcessedTx(context.actualDb, 1)]; await updateExpectedTreesFromTxs(expectsDb, txs); @@ -61,12 +61,12 @@ describe('prover/orchestrator/blocks', () => { }); it('builds a block concurrently with transaction simulation', async () => { - const txs = await Promise.all([ + const txs = [ makeBloatedProcessedTx(context.actualDb, 1), makeBloatedProcessedTx(context.actualDb, 2), makeBloatedProcessedTx(context.actualDb, 3), makeBloatedProcessedTx(context.actualDb, 4), - ]); + ]; const l1ToL2Messages = range(NUMBER_OF_L1_L2_MESSAGES_PER_ROLLUP, 1 + 0x400).map(fr); diff --git a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts index 1cab8f282fa..e2b11a1338e 100644 --- a/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_base_rollup.test.ts @@ -27,7 +27,7 @@ describe('prover/bb_prover/base-rollup', () => { }); it('proves the base rollup', async () => { - const header = await context.actualDb.buildInitialHeader(); + const header = context.actualDb.getInitialHeader(); const chainId = context.globalVariables.chainId; const version = context.globalVariables.version; const vkTreeRoot = getVKTreeRoot(); diff --git a/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts b/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts index 266bf7fd4e9..089f6a72270 100644 --- a/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts +++ b/yarn-project/prover-client/src/test/bb_prover_full_rollup.test.ts @@ -32,7 +32,7 @@ describe('prover/bb_prover/full-rollup', () => { const nonEmptyTxs = 0; logger.info(`Proving a private-only full rollup with ${nonEmptyTxs}/${totalTxs} non-empty transactions`); - const initialHeader = await context.actualDb.buildInitialHeader(); + const initialHeader = context.actualDb.getInitialHeader(); const txs = times(nonEmptyTxs, (i: number) => { const tx = mockTx(1000 * (i + 1), { numberOfNonRevertiblePublicCallRequests: 0, @@ -79,7 +79,7 @@ describe('prover/bb_prover/full-rollup', () => { }), ); for (const tx of txs) { - tx.data.constants.historicalHeader = await context.actualDb.buildInitialHeader(); + tx.data.constants.historicalHeader = context.actualDb.getInitialHeader(); } const l1ToL2Messages = makeTuple( diff --git a/yarn-project/prover-client/src/tx-prover/tx-prover.ts b/yarn-project/prover-client/src/tx-prover/tx-prover.ts index 6f2a99107ee..013ca478187 100644 --- a/yarn-project/prover-client/src/tx-prover/tx-prover.ts +++ b/yarn-project/prover-client/src/tx-prover/tx-prover.ts @@ -7,7 +7,7 @@ import { type ProvingTicket, type ServerCircuitProver, } from '@aztec/circuit-types/interfaces'; -import { type Fr, type GlobalVariables, type Header } from '@aztec/circuits.js'; +import { type Fr, type GlobalVariables } from '@aztec/circuits.js'; import { NativeACVMSimulator } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { type WorldStateSynchronizer } from '@aztec/world-state'; @@ -30,15 +30,9 @@ export class TxProver implements ProverClient { private worldStateSynchronizer: WorldStateSynchronizer, private telemetry: TelemetryClient, private agent?: ProverAgent, - initialHeader?: Header, ) { this.queue = new MemoryProvingQueue(config.proverJobTimeoutMs, config.proverJobPollIntervalMs); - this.orchestrator = new ProvingOrchestrator( - worldStateSynchronizer.getLatest(), - this.queue, - telemetry, - initialHeader, - ); + this.orchestrator = new ProvingOrchestrator(worldStateSynchronizer.getLatest(), this.queue, telemetry); } async updateProverConfig(config: Partial): Promise { @@ -107,8 +101,7 @@ export class TxProver implements ProverClient { ) : undefined; - const initialHeader = await worldStateSynchronizer.getCommitted().getInitialHeader(); - const prover = new TxProver(config, worldStateSynchronizer, telemetry, agent, initialHeader); + const prover = new TxProver(config, worldStateSynchronizer, telemetry, agent); await prover.start(); return prover; } diff --git a/yarn-project/prover-node/src/job/block-proving-job.ts b/yarn-project/prover-node/src/job/block-proving-job.ts index e1c4c99dcb6..1857a26bd71 100644 --- a/yarn-project/prover-node/src/job/block-proving-job.ts +++ b/yarn-project/prover-node/src/job/block-proving-job.ts @@ -66,7 +66,7 @@ export class BlockProvingJob { ...globalVariables, }); const provingTicket = await this.prover.startNewBlock(txCount, globalVariables, l1ToL2Messages); - const publicProcessor = await this.publicProcessorFactory.create(historicalHeader, globalVariables); + const publicProcessor = this.publicProcessorFactory.create(historicalHeader, globalVariables); const txs = await this.getTxs(txHashes); await this.processTxs(publicProcessor, txs, txCount); diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts index 68e42e82136..6a3189e2a40 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.test.ts @@ -87,7 +87,7 @@ describe('sequencer', () => { }); publicProcessorFactory = mock({ - create: (_a, _b_) => Promise.resolve(publicProcessor), + create: (_a, _b_) => publicProcessor, }); l2BlockSource = mock({ diff --git a/yarn-project/sequencer-client/src/sequencer/sequencer.ts b/yarn-project/sequencer-client/src/sequencer/sequencer.ts index 88ef405ae46..45e7c7437dc 100644 --- a/yarn-project/sequencer-client/src/sequencer/sequencer.ts +++ b/yarn-project/sequencer-client/src/sequencer/sequencer.ts @@ -263,7 +263,7 @@ export class Sequencer { ); // We create a fresh processor each time to reset any cached state (eg storage writes) - const processor = await this.publicProcessorFactory.create(historicalHeader, newGlobalVariables); + const processor = this.publicProcessorFactory.create(historicalHeader, newGlobalVariables); const numRealTxs = validTxs.length; const blockSize = Math.max(2, numRealTxs); diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index f8281f9ae6d..b47d347b464 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -59,11 +59,8 @@ export class PublicProcessorFactory { * @param newContracts - Provides access to contract bytecode for public executions. * @returns A new instance of a PublicProcessor. */ - public async create( - historicalHeader: Header | undefined, - globalVariables: GlobalVariables, - ): Promise { - historicalHeader = historicalHeader ?? (await this.merkleTree.buildInitialHeader()); + public create(historicalHeader: Header | undefined, globalVariables: GlobalVariables): PublicProcessor { + historicalHeader = historicalHeader ?? this.merkleTree.getInitialHeader(); const publicContractsDB = new ContractsDataSourcePublicDB(this.contractDataSource); const worldStatePublicDB = new WorldStatePublicDB(this.merkleTree); diff --git a/yarn-project/world-state/src/world-state-db/merkle_tree_operations.ts b/yarn-project/world-state/src/world-state-db/merkle_tree_operations.ts index b3887f34269..ecddc43dcc6 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_tree_operations.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_tree_operations.ts @@ -75,13 +75,7 @@ export interface MerkleTreeOperations { /** * Gets the initial header. */ - getInitialHeader(): Promise
; - - /** - * Builds the initial header. - * @deprecated Use `getInitialHeader` instead. - */ - buildInitialHeader(): Promise
; + getInitialHeader(): Header; /** * Gets sibling path for a leaf. diff --git a/yarn-project/world-state/src/world-state-db/merkle_tree_operations_facade.ts b/yarn-project/world-state/src/world-state-db/merkle_tree_operations_facade.ts index 1aba0010b8a..b67636866db 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_tree_operations_facade.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_tree_operations_facade.ts @@ -37,14 +37,10 @@ export class MerkleTreeOperationsFacade implements MerkleTreeOperations { } /** - * Builds the initial header. + * Returns the initial header for the chain before the first block. * @returns The initial header. */ - buildInitialHeader(): Promise
{ - return this.trees.buildInitialHeader(this.includeUncommitted); - } - - getInitialHeader(): Promise
{ + getInitialHeader(): Header { return this.trees.getInitialHeader(this.includeUncommitted); } diff --git a/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts b/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts index c8ea4c1c3a0..3f72c680732 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_tree_snapshot_operations_facade.ts @@ -166,11 +166,7 @@ export class MerkleTreeSnapshotOperationsFacade implements MerkleTreeOperations return Promise.reject(new Error('Tree snapshot operations are read-only')); } - buildInitialHeader(): Promise
{ - throw new Error('Building initial header not supported on snapshot.'); - } - - getInitialHeader(): Promise
{ + getInitialHeader(): Header { throw new Error('Getting initial header not supported on snapshot.'); } } diff --git a/yarn-project/world-state/src/world-state-db/merkle_trees.ts b/yarn-project/world-state/src/world-state-db/merkle_trees.ts index 30d7ed5d209..79d7754c3c8 100644 --- a/yarn-project/world-state/src/world-state-db/merkle_trees.ts +++ b/yarn-project/world-state/src/world-state-db/merkle_trees.ts @@ -2,9 +2,7 @@ import { type L2Block, MerkleTreeId, PublicDataWrite, type SiblingPath, TxEffect import { ARCHIVE_HEIGHT, AppendOnlyTreeSnapshot, - ContentCommitment, Fr, - GlobalVariables, Header, L1_TO_L2_MSG_TREE_HEIGHT, MAX_NOTE_HASHES_PER_TX, @@ -27,7 +25,7 @@ import { padArrayEnd } from '@aztec/foundation/collection'; import { SerialQueue } from '@aztec/foundation/fifo'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; import { type IndexedTreeLeafPreimage } from '@aztec/foundation/trees'; -import { type AztecKVStore } from '@aztec/kv-store'; +import { type AztecKVStore, type AztecSingleton } from '@aztec/kv-store'; import { type AppendOnlyTree, type BatchInsertionResult, @@ -99,9 +97,11 @@ export class MerkleTrees implements MerkleTreeDb { // gets initialized in #init private trees: MerkleTreeMap = null as any; private jobQueue = new SerialQueue(); - private initialHeader!: Header; + private initialStateReference: AztecSingleton; - private constructor(private store: AztecKVStore, private log: DebugLogger) {} + private constructor(private store: AztecKVStore, private log: DebugLogger) { + this.initialStateReference = store.openSingleton('merkle_trees_initial_state_reference'); + } /** * Method to asynchronously create and initialize a MerkleTrees instance. @@ -170,34 +170,18 @@ export class MerkleTrees implements MerkleTreeDb { this.jobQueue.start(); if (!fromDb) { - // We are not initializing from db so we need to populate the first leaf of the archive tree which is a hash of - // the initial header. - const initialHeader = await this.buildInitialHeader(true); - this.initialHeader = initialHeader; - await this.#updateArchive(initialHeader, true); - } else { - // TODO(palla/prover-node) Running buildInitialHeader here yields a WRONG initial header, - // we need to reconstruct it from an empty state reference. - this.initialHeader = await this.buildInitialHeader(true); + // We are not initializing from db so we need to populate the first leaf of the archive tree which is a hash of the initial header, + // and persist the initial header state reference so we can later load it when requested. + const initialState = await this.getStateReference(true); + await this.#saveInitialStateReference(initialState); + await this.#updateArchive(this.getInitialHeader(), true); } await this.#commit(); } - // TODO(palla/prover-node): Make this private. It only makes sense if called at the beginning of the lifecycle of the object. - public async buildInitialHeader(includeUncommitted: boolean): Promise
{ - const state = await this.getStateReference(includeUncommitted); - return new Header( - AppendOnlyTreeSnapshot.zero(), - ContentCommitment.empty(), - state, - GlobalVariables.empty(), - Fr.ZERO, - ); - } - - public getInitialHeader(): Promise
{ - return Promise.resolve(this.initialHeader); + public getInitialHeader(): Header { + return Header.empty({ state: this.#loadInitialStateReference() }); } /** @@ -461,6 +445,18 @@ export class MerkleTrees implements MerkleTreeDb { return await this.jobQueue.put(fn); } + #saveInitialStateReference(state: StateReference) { + return this.initialStateReference.set(state.toBuffer()); + } + + #loadInitialStateReference(): StateReference { + const serialized = this.initialStateReference.get(); + if (!serialized) { + throw new Error('Initial state reference not found'); + } + return StateReference.fromBuffer(serialized); + } + async #updateArchive(header: Header, includeUncommitted: boolean) { const state = await this.getStateReference(includeUncommitted);