From d45fdb36506e8ab6af1b9bd5b37f179d7d0a0a3b Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Fri, 15 Nov 2024 02:55:42 +0000 Subject: [PATCH] refactor: stop calling public kernels --- .../aztec-node/src/aztec-node/server.ts | 8 +- yarn-project/circuit-types/src/tx/tx.ts | 30 ++- .../prover-client/src/mocks/test_context.ts | 3 - yarn-project/prover-node/src/prover-node.ts | 8 +- .../src/client/sequencer-client.ts | 4 +- .../simulator/src/avm/journal/journal.ts | 4 +- .../src/public/dual_side_effect_trace.ts | 7 +- .../public/enqueued_call_side_effect_trace.ts | 13 +- yarn-project/simulator/src/public/executor.ts | 4 +- .../simulator/src/public/public_processor.ts | 28 +-- .../simulator/src/public/public_tx_context.ts | 194 ++++++++++-------- .../src/public/public_tx_simulator.test.ts | 7 - .../src/public/public_tx_simulator.ts | 109 ++++------ .../simulator/src/public/side_effect_trace.ts | 4 +- .../src/public/side_effect_trace_interface.ts | 2 +- yarn-project/simulator/src/public/utils.ts | 190 +++-------------- 16 files changed, 219 insertions(+), 396 deletions(-) diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index eec371b96fbf..f3cc8bda08f0 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -71,7 +71,7 @@ import { } from '@aztec/p2p'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; import { GlobalVariableBuilder, SequencerClient } from '@aztec/sequencer-client'; -import { PublicProcessorFactory, WASMSimulator, createSimulationProvider } from '@aztec/simulator'; +import { PublicProcessorFactory, createSimulationProvider } from '@aztec/simulator'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { createValidatorClient } from '@aztec/validator-client'; @@ -733,11 +733,7 @@ export class AztecNodeService implements AztecNode { feeRecipient, ); const prevHeader = (await this.blockSource.getBlock(-1))?.header; - const publicProcessorFactory = new PublicProcessorFactory( - this.contractDataSource, - new WASMSimulator(), - this.telemetry, - ); + const publicProcessorFactory = new PublicProcessorFactory(this.contractDataSource, this.telemetry); const fork = await this.worldStateSynchronizer.fork(); diff --git a/yarn-project/circuit-types/src/tx/tx.ts b/yarn-project/circuit-types/src/tx/tx.ts index f53f70d7dccf..ae0c49e50117 100644 --- a/yarn-project/circuit-types/src/tx/tx.ts +++ b/yarn-project/circuit-types/src/tx/tx.ts @@ -2,7 +2,8 @@ import { ClientIvcProof, ContractClassRegisteredEvent, PrivateKernelTailCircuitPublicInputs, - type PublicKernelCircuitPublicInputs, + type PrivateToPublicAccumulatedData, + type ScopedLogHash, } from '@aztec/circuits.js'; import { type Buffer32 } from '@aztec/foundation/buffer'; import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection'; @@ -344,29 +345,26 @@ export class Tx extends Gossipable { * @param logHashes the individual log hashes we want to keep * @param out the output to put passing logs in, to keep this function abstract */ - public filterRevertedLogs(kernelOutput: PublicKernelCircuitPublicInputs) { + public filterRevertedLogs( + privateNonRevertible: PrivateToPublicAccumulatedData, + unencryptedLogsHashes: ScopedLogHash[], + ) { this.encryptedLogs = this.encryptedLogs.filterScoped( - kernelOutput.endNonRevertibleData.encryptedLogsHashes, + privateNonRevertible.encryptedLogsHashes, EncryptedTxL2Logs.empty(), ); - this.unencryptedLogs = this.unencryptedLogs.filterScoped( - kernelOutput.endNonRevertibleData.unencryptedLogsHashes, - UnencryptedTxL2Logs.empty(), - ); - this.noteEncryptedLogs = this.noteEncryptedLogs.filter( - kernelOutput.endNonRevertibleData.noteEncryptedLogsHashes, + privateNonRevertible.noteEncryptedLogsHashes, EncryptedNoteTxL2Logs.empty(), ); - // See comment in enqueued_calls_processor.ts -> tx.filterRevertedLogs() - if (this.data.forPublic) { - this.contractClassLogs = this.contractClassLogs.filterScoped( - this.data.forPublic?.nonRevertibleAccumulatedData.contractClassLogsHashes, - ContractClassTxL2Logs.empty(), - ); - } + this.contractClassLogs = this.contractClassLogs.filterScoped( + privateNonRevertible.contractClassLogsHashes, + ContractClassTxL2Logs.empty(), + ); + + this.unencryptedLogs = this.unencryptedLogs.filterScoped(unencryptedLogsHashes, UnencryptedTxL2Logs.empty()); } } diff --git a/yarn-project/prover-client/src/mocks/test_context.ts b/yarn-project/prover-client/src/mocks/test_context.ts index f04621c16f22..75360e621787 100644 --- a/yarn-project/prover-client/src/mocks/test_context.ts +++ b/yarn-project/prover-client/src/mocks/test_context.ts @@ -17,7 +17,6 @@ import { PublicExecutionResultBuilder, type PublicExecutor, PublicProcessor, - RealPublicKernelCircuitSimulator, type SimulationProvider, WASMSimulator, type WorldStateDB, @@ -69,7 +68,6 @@ export class TestContext { const publicExecutor = mock(); const worldStateDB = mock(); - const publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator()); const telemetry = new NoopTelemetryClient(); // Separated dbs for public processor and prover - see public_processor for context @@ -89,7 +87,6 @@ export class TestContext { const processor = PublicProcessor.create( publicDb, publicExecutor, - publicKernel, globalVariables, Header.empty(), worldStateDB, diff --git a/yarn-project/prover-node/src/prover-node.ts b/yarn-project/prover-node/src/prover-node.ts index 1b090315c8f5..1c0c5f6611f5 100644 --- a/yarn-project/prover-node/src/prover-node.ts +++ b/yarn-project/prover-node/src/prover-node.ts @@ -56,7 +56,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler, Pr private readonly contractDataSource: ContractDataSource, private readonly worldState: WorldStateSynchronizer, private readonly coordination: ProverCoordination & Maybe, - private readonly simulator: SimulationProvider, + private readonly _simulator: SimulationProvider, private readonly quoteProvider: QuoteProvider, private readonly quoteSigner: QuoteSigner, private readonly claimsMonitor: ClaimsMonitor, @@ -243,11 +243,7 @@ export class ProverNode implements ClaimsMonitorHandler, EpochMonitorHandler, Pr const proverDb = await this.worldState.fork(fromBlock - 1); // Create a processor using the forked world state - const publicProcessorFactory = new PublicProcessorFactory( - this.contractDataSource, - this.simulator, - this.telemetryClient, - ); + const publicProcessorFactory = new PublicProcessorFactory(this.contractDataSource, this.telemetryClient); const cleanUp = async () => { await publicDb.close(); diff --git a/yarn-project/sequencer-client/src/client/sequencer-client.ts b/yarn-project/sequencer-client/src/client/sequencer-client.ts index a9618e8b9806..eae0bd3729d6 100644 --- a/yarn-project/sequencer-client/src/client/sequencer-client.ts +++ b/yarn-project/sequencer-client/src/client/sequencer-client.ts @@ -40,13 +40,13 @@ export class SequencerClient { contractDataSource: ContractDataSource, l2BlockSource: L2BlockSource, l1ToL2MessageSource: L1ToL2MessageSource, - simulationProvider: SimulationProvider, + _simulationProvider: SimulationProvider, telemetryClient: TelemetryClient, ) { const publisher = new L1Publisher(config, telemetryClient); const globalsBuilder = new GlobalVariableBuilder(config); - const publicProcessorFactory = new PublicProcessorFactory(contractDataSource, simulationProvider, telemetryClient); + const publicProcessorFactory = new PublicProcessorFactory(contractDataSource, telemetryClient); const rollup = publisher.getRollupContract(); const [l1GenesisTime, slotDuration] = await Promise.all([ diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index af9403485429..582384753af6 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -79,10 +79,10 @@ export class AvmPersistableStateManager { /** * Create a new state manager forked from this one */ - public fork(incrementSideEffectCounter: boolean = false) { + public fork() { return new AvmPersistableStateManager( this.worldStateDB, - this.trace.fork(incrementSideEffectCounter), + this.trace.fork(), this.publicStorage.fork(), this.nullifiers.fork(), this.doMerkleOperations, diff --git a/yarn-project/simulator/src/public/dual_side_effect_trace.ts b/yarn-project/simulator/src/public/dual_side_effect_trace.ts index c33820d26594..83928af67771 100644 --- a/yarn-project/simulator/src/public/dual_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/dual_side_effect_trace.ts @@ -27,11 +27,8 @@ export class DualSideEffectTrace implements PublicSideEffectTraceInterface { public readonly enqueuedCallTrace: PublicEnqueuedCallSideEffectTrace, ) {} - public fork(incrementSideEffectCounter: boolean = false) { - return new DualSideEffectTrace( - this.innerCallTrace.fork(incrementSideEffectCounter), - this.enqueuedCallTrace.fork(incrementSideEffectCounter), - ); + public fork() { + return new DualSideEffectTrace(this.innerCallTrace.fork(), this.enqueuedCallTrace.fork()); } public merge(nestedTrace: this, reverted: boolean = false) { diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 90323853d3f8..f77e6a1c8f1c 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -70,7 +70,6 @@ import { makeTuple } from '@aztec/foundation/array'; import { padArrayEnd } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; -import { type Tuple } from '@aztec/foundation/serialize'; import { assert } from 'console'; @@ -154,9 +153,9 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.avmCircuitHints = AvmExecutionHints.empty(); } - public fork(incrementSideEffectCounter: boolean = false) { + public fork() { return new PublicEnqueuedCallSideEffectTrace( - incrementSideEffectCounter ? this.sideEffectCounter + 1 : this.sideEffectCounter, + this.sideEffectCounter, new PublicValidationRequestArrayLengths( this.previousValidationRequestArrayLengths.noteHashReadRequests + this.noteHashReadRequests.length, this.previousValidationRequestArrayLengths.nullifierReadRequests + this.nullifierReadRequests.length, @@ -631,9 +630,9 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI /** How much gas was available for this public execution. */ gasLimits: GasSettings, /** Call requests for setup phase. */ - publicSetupCallRequests: Tuple, + publicSetupCallRequests: PublicCallRequest[], /** Call requests for app logic phase. */ - publicAppLogicCallRequests: Tuple, + publicAppLogicCallRequests: PublicCallRequest[], /** Call request for teardown phase. */ publicTeardownCallRequest: PublicCallRequest, /** End tree snapshots. */ @@ -653,8 +652,8 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI startTreeSnapshots, startGasUsed, gasLimits, - publicSetupCallRequests, - publicAppLogicCallRequests, + padArrayEnd(publicSetupCallRequests, PublicCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_TX), + padArrayEnd(publicAppLogicCallRequests, PublicCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_TX), publicTeardownCallRequest, /*previousNonRevertibleAccumulatedDataArrayLengths=*/ PrivateToAvmAccumulatedDataArrayLengths.empty(), /*previousRevertibleAccumulatedDataArrayLengths=*/ PrivateToAvmAccumulatedDataArrayLengths.empty(), diff --git a/yarn-project/simulator/src/public/executor.ts b/yarn-project/simulator/src/public/executor.ts index 3a90b863bdb6..162d20b7a4c8 100644 --- a/yarn-project/simulator/src/public/executor.ts +++ b/yarn-project/simulator/src/public/executor.ts @@ -43,7 +43,7 @@ export class PublicExecutor { */ public async simulate( stateManager: AvmPersistableStateManager, - executionRequest: PublicExecutionRequest, // TODO(dbanks12): CallRequest instead? + executionRequest: PublicExecutionRequest, globalVariables: GlobalVariables, allocatedGas: Gas, transactionFee: Fr = Fr.ZERO, @@ -105,6 +105,8 @@ export class PublicExecutor { * @param transactionFee - Fee offered for this TX. * @param startSideEffectCounter - The start counter to initialize the side effect trace with. * @returns The result of execution including side effect vectors. + * FIXME: this function is only used by the TXE. Ideally we would not support this as an external interface. + * Avoid using this interface as it it shouldn't really exist in the first place. */ public async simulateIsolatedEnqueuedCall( executionRequest: PublicExecutionRequest, diff --git a/yarn-project/simulator/src/public/public_processor.ts b/yarn-project/simulator/src/public/public_processor.ts index 55fce164cfb9..f1d065bb1665 100644 --- a/yarn-project/simulator/src/public/public_processor.ts +++ b/yarn-project/simulator/src/public/public_processor.ts @@ -31,12 +31,9 @@ import { Timer } from '@aztec/foundation/timer'; import { ProtocolContractAddress } from '@aztec/protocol-contracts'; import { Attributes, type TelemetryClient, type Tracer, trackSpan } from '@aztec/telemetry-client'; -import { type SimulationProvider } from '../providers/index.js'; import { PublicExecutor } from './executor.js'; import { computeFeePayerBalanceLeafSlot, computeFeePayerBalanceStorageSlot } from './fee_payment.js'; import { WorldStateDB } from './public_db_sources.js'; -import { RealPublicKernelCircuitSimulator } from './public_kernel.js'; -import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; import { PublicProcessorMetrics } from './public_processor_metrics.js'; import { PublicTxSimulator } from './public_tx_simulator.js'; @@ -44,11 +41,7 @@ import { PublicTxSimulator } from './public_tx_simulator.js'; * Creates new instances of PublicProcessor given the provided merkle tree db and contract data source. */ export class PublicProcessorFactory { - constructor( - private contractDataSource: ContractDataSource, - private simulator: SimulationProvider, - private telemetryClient: TelemetryClient, - ) {} + constructor(private contractDataSource: ContractDataSource, private telemetryClient: TelemetryClient) {} /** * Creates a new instance of a PublicProcessor. @@ -66,12 +59,10 @@ export class PublicProcessorFactory { const worldStateDB = new WorldStateDB(merkleTree, this.contractDataSource); const publicExecutor = new PublicExecutor(worldStateDB, telemetryClient); - const publicKernelSimulator = new RealPublicKernelCircuitSimulator(this.simulator); return PublicProcessor.create( merkleTree, publicExecutor, - publicKernelSimulator, globalVariables, historicalHeader, worldStateDB, @@ -91,7 +82,7 @@ export class PublicProcessor { protected globalVariables: GlobalVariables, protected historicalHeader: Header, protected worldStateDB: WorldStateDB, - protected enqueuedCallsProcessor: PublicTxSimulator, + protected publicTxSimulator: PublicTxSimulator, telemetryClient: TelemetryClient, private log = createDebugLogger('aztec:sequencer:public-processor'), ) { @@ -101,29 +92,20 @@ export class PublicProcessor { static create( db: MerkleTreeWriteOperations, publicExecutor: PublicExecutor, - publicKernelSimulator: PublicKernelCircuitSimulator, globalVariables: GlobalVariables, historicalHeader: Header, worldStateDB: WorldStateDB, telemetryClient: TelemetryClient, ) { - const enqueuedCallsProcessor = PublicTxSimulator.create( + const publicTxSimulator = PublicTxSimulator.create( db, publicExecutor, - publicKernelSimulator, globalVariables, historicalHeader, worldStateDB, ); - return new PublicProcessor( - db, - globalVariables, - historicalHeader, - worldStateDB, - enqueuedCallsProcessor, - telemetryClient, - ); + return new PublicProcessor(db, globalVariables, historicalHeader, worldStateDB, publicTxSimulator, telemetryClient); } get tracer(): Tracer { @@ -299,7 +281,7 @@ export class PublicProcessor { const timer = new Timer(); const { avmProvingRequest, gasUsed, revertCode, revertReason, processedPhases } = - await this.enqueuedCallsProcessor.process(tx); + await this.publicTxSimulator.process(tx); if (!avmProvingRequest) { this.metrics.recordFailedTx(); diff --git a/yarn-project/simulator/src/public/public_tx_context.ts b/yarn-project/simulator/src/public/public_tx_context.ts index 40f0b88fac60..be427f89afd3 100644 --- a/yarn-project/simulator/src/public/public_tx_context.ts +++ b/yarn-project/simulator/src/public/public_tx_context.ts @@ -13,16 +13,16 @@ import { Gas, type GasSettings, type GlobalVariables, + type PrivateToPublicAccumulatedData, PublicAccumulatedDataArrayLengths, type PublicCallRequest, - type PublicKernelCircuitPublicInputs, PublicValidationRequestArrayLengths, RevertCode, type StateReference, } from '@aztec/circuits.js'; import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log'; -import { assert } from 'console'; +import { strict as assert } from 'assert'; import { inspect } from 'util'; import { AvmPersistableStateManager } from '../avm/index.js'; @@ -31,34 +31,36 @@ import { PublicEnqueuedCallSideEffectTrace } from './enqueued_call_side_effect_t import { type WorldStateDB } from './public_db_sources.js'; import { PublicSideEffectTrace } from './side_effect_trace.js'; import { + convertPrivateToPublicAccumulatedData, generateAvmCircuitPublicInputs, getCallRequestsByPhase, getExecutionRequestsByPhase, - getPublicKernelCircuitPublicInputs, } from './utils.js'; export class PublicTxContext { private log: DebugLogger; - private currentPhase: TxExecutionPhase = TxExecutionPhase.SETUP; - /* Gas used including private, teardown gas _limit_, setup and app logic */ private gasUsed: Gas; /* Gas actually used during teardown (different from limit) */ public teardownGasUsed: Gas = Gas.empty(); + /* Entire transaction execution is done. */ + private halted = false; + /* Where did reverts happen (if at all)? */ public revertCode: RevertCode = RevertCode.OK; + /* What caused a revert (if one occurred)? */ public revertReason: SimulationError | undefined; public avmProvingRequest: AvmProvingRequest | undefined; // tmp hack constructor( public readonly state: PhaseStateManager, - public readonly tx: Tx, // tmp hack - public readonly globalVariables: GlobalVariables, - public readonly constants: CombinedConstantData, // tmp hack - public readonly startStateReference: StateReference, - startGasUsed: Gas, + public readonly tx: Tx, // TODO(dbanks12): remove + private readonly globalVariables: GlobalVariables, + public readonly constants: CombinedConstantData, // TODO(dbanks12): remove + private readonly startStateReference: StateReference, + private readonly startGasUsed: Gas, private readonly gasSettings: GasSettings, private readonly setupCallRequests: PublicCallRequest[], private readonly appLogicCallRequests: PublicCallRequest[], @@ -66,9 +68,9 @@ export class PublicTxContext { private readonly setupExecutionRequests: PublicExecutionRequest[], private readonly appLogicExecutionRequests: PublicExecutionRequest[], private readonly teardownExecutionRequests: PublicExecutionRequest[], - private firstPublicKernelOutput: PublicKernelCircuitPublicInputs, - public latestPublicKernelOutput: PublicKernelCircuitPublicInputs, - public trace: PublicEnqueuedCallSideEffectTrace, + private readonly nonRevertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData, + private readonly revertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData, + private trace: PublicEnqueuedCallSideEffectTrace, ) { this.log = createDebugLogger(`aztec:public_tx_context`); this.gasUsed = startGasUsed; @@ -80,29 +82,25 @@ export class PublicTxContext { tx: Tx, globalVariables: GlobalVariables, ) { - const privateKernelOutput = tx.data; - const firstPublicKernelOutput = getPublicKernelCircuitPublicInputs(privateKernelOutput, globalVariables); + const nonRevertibleAccumulatedDataFromPrivate = convertPrivateToPublicAccumulatedData( + tx.data.forPublic!.nonRevertibleAccumulatedData, + ); + const revertibleAccumulatedDataFromPrivate = convertPrivateToPublicAccumulatedData( + tx.data.forPublic!.revertibleAccumulatedData, + ); - const nonRevertibleNullifiersFromPrivate = firstPublicKernelOutput.endNonRevertibleData.nullifiers + const nonRevertibleNullifiersFromPrivate = nonRevertibleAccumulatedDataFromPrivate.nullifiers .filter(n => !n.isEmpty()) .map(n => n.value); - const _revertibleNullifiersFromPrivate = firstPublicKernelOutput.end.nullifiers + const _revertibleNullifiersFromPrivate = revertibleAccumulatedDataFromPrivate.nullifiers .filter(n => !n.isEmpty()) .map(n => n.value); - // During SETUP, non revertible side effects from private are our "previous data" - const prevAccumulatedData = firstPublicKernelOutput.endNonRevertibleData; - const previousValidationRequestArrayLengths = PublicValidationRequestArrayLengths.new( - firstPublicKernelOutput.validationRequests, - ); - - const previousAccumulatedDataArrayLengths = PublicAccumulatedDataArrayLengths.new(prevAccumulatedData); - const innerCallTrace = new PublicSideEffectTrace(); const enqueuedCallTrace = new PublicEnqueuedCallSideEffectTrace( /*startSideEffectCounter=*/ 0, - previousValidationRequestArrayLengths, - previousAccumulatedDataArrayLengths, + PublicValidationRequestArrayLengths.empty(), + PublicAccumulatedDataArrayLengths.new(nonRevertibleAccumulatedDataFromPrivate), ); const trace = new DualSideEffectTrace(innerCallTrace, enqueuedCallTrace); @@ -127,55 +125,44 @@ export class PublicTxContext { getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP), getExecutionRequestsByPhase(tx, TxExecutionPhase.APP_LOGIC), getExecutionRequestsByPhase(tx, TxExecutionPhase.TEARDOWN), - firstPublicKernelOutput, - firstPublicKernelOutput, + tx.data.forPublic!.nonRevertibleAccumulatedData, + tx.data.forPublic!.revertibleAccumulatedData, enqueuedCallTrace, ); } - getCurrentPhase(): TxExecutionPhase { - return this.currentPhase; - } - - hasPhase(phase: TxExecutionPhase = this.currentPhase): boolean { - if (phase === TxExecutionPhase.SETUP) { - return this.setupCallRequests.length > 0; - } else if (phase === TxExecutionPhase.APP_LOGIC) { - return this.appLogicCallRequests.length > 0; - } else { - // phase === TxExecutionPhase.TEARDOWN - return this.teardownCallRequests.length > 0; - } + /** + * Signal that the entire transaction execution is done. + * All phases have been processed. + * Actual transaction fee and actual total consumed gas can now be queried. + */ + halt() { + this.halted = true; } - progressToNextPhase() { - assert(this.currentPhase !== TxExecutionPhase.TEARDOWN, 'Cannot progress past teardown'); - if (this.currentPhase === TxExecutionPhase.SETUP) { - this.currentPhase = TxExecutionPhase.APP_LOGIC; - } else { - this.currentPhase = TxExecutionPhase.TEARDOWN; - } - } + /** + * Revert execution a phase. Populate revertReason & revertCode. + * If in setup, throw an error (transaction will be thrown out). + * NOTE: this does not "halt" the entire transaction execution. + */ + revert(phase: TxExecutionPhase, revertReason: SimulationError | undefined = undefined, culprit = '') { + this.log.debug(`${TxExecutionPhase[phase]} phase reverted! ${culprit} failed with reason: ${revertReason}`); - revert(revertReason: SimulationError | undefined = undefined, culprit = '') { - this.log.debug( - `${TxExecutionPhase[this.currentPhase]} phase reverted! ${culprit} failed with reason: ${revertReason}`, - ); if (revertReason && !this.revertReason) { // don't override revertReason // (if app logic and teardown both revert, we want app logic's reason) this.revertReason = revertReason; } - if (this.currentPhase === TxExecutionPhase.SETUP) { + if (phase === TxExecutionPhase.SETUP) { this.log.debug(`Setup phase reverted! The transaction will be thrown out.`); if (revertReason) { throw revertReason; } else { throw new Error(`Setup phase reverted! The transaction will be thrown out. ${culprit} failed`); } - } else if (this.currentPhase === TxExecutionPhase.APP_LOGIC) { + } else if (phase === TxExecutionPhase.APP_LOGIC) { this.revertCode = RevertCode.APP_LOGIC_REVERTED; - } else if (this.currentPhase === TxExecutionPhase.TEARDOWN) { + } else if (phase === TxExecutionPhase.TEARDOWN) { if (this.revertCode.equals(RevertCode.APP_LOGIC_REVERTED)) { this.revertCode = RevertCode.BOTH_REVERTED; } else { @@ -184,8 +171,25 @@ export class PublicTxContext { } } - getCallRequestsForCurrentPhase(): PublicCallRequest[] { - switch (this.currentPhase) { + /** + * Are there any call requests for the speciiied phase? + */ + hasPhase(phase: TxExecutionPhase): boolean { + if (phase === TxExecutionPhase.SETUP) { + return this.setupCallRequests.length > 0; + } else if (phase === TxExecutionPhase.APP_LOGIC) { + return this.appLogicCallRequests.length > 0; + } else { + // phase === TxExecutionPhase.TEARDOWN + return this.teardownCallRequests.length > 0; + } + } + + /** + * Get the call requests for the specified phase (including args hashes). + */ + getCallRequestsForPhase(phase: TxExecutionPhase): PublicCallRequest[] { + switch (phase) { case TxExecutionPhase.SETUP: return this.setupCallRequests; case TxExecutionPhase.APP_LOGIC: @@ -195,8 +199,11 @@ export class PublicTxContext { } } - getExecutionRequestsForCurrentPhase(): PublicExecutionRequest[] { - switch (this.currentPhase) { + /** + * Get the call requests for the specified phase (including actual args). + */ + getExecutionRequestsForPhase(phase: TxExecutionPhase): PublicExecutionRequest[] { + switch (phase) { case TxExecutionPhase.SETUP: return this.setupExecutionRequests; case TxExecutionPhase.APP_LOGIC: @@ -206,17 +213,22 @@ export class PublicTxContext { } } - getGasLeftForCurrentPhase(): Gas { - if (this.currentPhase === TxExecutionPhase.TEARDOWN) { + /** + * How much gas is left for the specified phase? + */ + getGasLeftForPhase(phase: TxExecutionPhase): Gas { + if (phase === TxExecutionPhase.TEARDOWN) { return this.gasSettings.teardownGasLimits; } else { return this.gasSettings.gasLimits.sub(this.gasUsed); } } - consumeGas(gas: Gas) { - if (this.currentPhase === TxExecutionPhase.TEARDOWN) { - // track teardown gas used separately + /** + * Consume gas. Track gas for teardown phase separately. + */ + consumeGas(phase: TxExecutionPhase, gas: Gas) { + if (phase === TxExecutionPhase.TEARDOWN) { this.teardownGasUsed = this.teardownGasUsed.add(gas); } else { this.gasUsed = this.gasUsed.add(gas); @@ -226,33 +238,39 @@ export class PublicTxContext { /** * Compute the gas used using the actual gas used during teardown instead * of the teardown gas limit. - * Note that this.gasUsed comes from private and private includes - * teardown gas limit in its output gasUsed. + * Note that this.gasUsed is initialized from private's gasUsed which includes + * teardown gas limit. */ getActualGasUsed(): Gas { - assert(this.currentPhase === TxExecutionPhase.TEARDOWN, 'Can only compute actual gas used after app logic'); + assert(this.halted, 'Can only compute actual gas used after tx execution ends'); const requireTeardown = this.teardownCallRequests.length > 0; const teardownGasLimits = requireTeardown ? this.gasSettings.teardownGasLimits : Gas.empty(); return this.gasUsed.sub(teardownGasLimits).add(this.teardownGasUsed); } + /** + * The gasUsed as if the entire teardown gas limit was consumed. + */ getGasUsedForFee(): Gas { return this.gasUsed; } - getTransactionFee(): Fr { - if (this.currentPhase === TxExecutionPhase.TEARDOWN) { + /** + * Get the transaction fee as is available to the specified phase. + * Only teardown should have access to the actual transaction fee. + */ + getTransactionFee(phase: TxExecutionPhase): Fr { + if (phase === TxExecutionPhase.TEARDOWN) { return this.getTransactionFeeUnsafe(); } else { return Fr.zero(); } } - getFinalTransactionFee(): Fr { - assert(this.currentPhase === TxExecutionPhase.TEARDOWN, 'Transaction fee is only known during/after teardown'); - return this.getTransactionFeeUnsafe(); - } - + /** + * Compute the transaction fee. + * Should only be called during or after teardown. + */ private getTransactionFeeUnsafe(): Fr { const txFee = this.gasUsed.computeFee(this.globalVariables.gasFees); this.log.debug(`Computed tx fee`, { @@ -263,24 +281,32 @@ export class PublicTxContext { return txFee; } + /** + * Generate the public inputs for the AVM circuit. + */ private generateAvmCircuitPublicInputs(endStateReference: StateReference): AvmCircuitPublicInputs { - assert( - this.currentPhase === TxExecutionPhase.TEARDOWN, - 'Can only get AvmCircuitPublicInputs after teardown (tx done)', - ); + assert(this.halted, 'Can only get AvmCircuitPublicInputs after tx execution ends'); return generateAvmCircuitPublicInputs( - this.tx, this.trace, this.globalVariables, this.startStateReference, + this.startGasUsed, + this.gasSettings, + this.setupCallRequests, + this.appLogicCallRequests, + this.teardownCallRequests, + this.nonRevertibleAccumulatedDataFromPrivate, + this.revertibleAccumulatedDataFromPrivate, endStateReference, - this.gasUsed, - this.getFinalTransactionFee(), + /*endGasUsed=*/ this.gasUsed, + this.getTransactionFeeUnsafe(), this.revertCode, - this.firstPublicKernelOutput, ); } + /** + * Generate the proving request for the AVM circuit. + */ generateProvingRequest(endStateReference: StateReference): AvmProvingRequest { // TODO(dbanks12): Once we actually have tx-level proving, this will generate the entire // proving request for the first time diff --git a/yarn-project/simulator/src/public/public_tx_simulator.test.ts b/yarn-project/simulator/src/public/public_tx_simulator.test.ts index 08780d7008c8..e2251e69ea45 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.test.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.test.ts @@ -31,11 +31,8 @@ import { type MockProxy, mock } from 'jest-mock-extended'; import { type AvmPersistableStateManager } from '../avm/journal/journal.js'; import { PublicExecutionResultBuilder } from '../mocks/fixtures.js'; -import { WASMSimulator } from '../providers/acvm_wasm.js'; import { type PublicExecutor } from './executor.js'; import { type WorldStateDB } from './public_db_sources.js'; -import { RealPublicKernelCircuitSimulator } from './public_kernel.js'; -import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; import { PublicTxSimulator } from './public_tx_simulator.js'; describe('public_tx_simulator', () => { @@ -53,7 +50,6 @@ describe('public_tx_simulator', () => { let db: MockProxy; let publicExecutor: MockProxy; - let publicKernel: PublicKernelCircuitSimulator; let worldStateDB: MockProxy; let root: Buffer; @@ -163,12 +159,9 @@ describe('public_tx_simulator', () => { db.getPreviousValueIndex.mockResolvedValue({ index: 0n, alreadyPresent: true }); db.getLeafPreimage.mockResolvedValue(new PublicDataTreeLeafPreimage(new Fr(0), new Fr(0), new Fr(0), 0n)); - publicKernel = new RealPublicKernelCircuitSimulator(new WASMSimulator()); - processor = PublicTxSimulator.create( db, publicExecutor, - publicKernel, GlobalVariables.from({ ...GlobalVariables.empty(), gasFees }), Header.empty(), worldStateDB, diff --git a/yarn-project/simulator/src/public/public_tx_simulator.ts b/yarn-project/simulator/src/public/public_tx_simulator.ts index 216edb63c512..9ca64c166381 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.ts @@ -14,10 +14,7 @@ import { Timer } from '@aztec/foundation/timer'; import { EnqueuedCallSimulator } from './enqueued_call_simulator.js'; import { type PublicExecutor } from './executor.js'; import { type WorldStateDB } from './public_db_sources.js'; -import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; -import { PublicKernelTailSimulator } from './public_kernel_tail_simulator.js'; import { PublicTxContext } from './public_tx_context.js'; -import { generateAvmCircuitPublicInputsDeprecated, runMergeKernelCircuit } from './utils.js'; export type ProcessedPhase = { phase: TxExecutionPhase; @@ -42,19 +39,16 @@ export class PublicTxSimulator { constructor( private db: MerkleTreeReadOperations, - private publicKernelSimulator: PublicKernelCircuitSimulator, private globalVariables: GlobalVariables, private worldStateDB: WorldStateDB, private enqueuedCallSimulator: EnqueuedCallSimulator, - private publicKernelTailSimulator: PublicKernelTailSimulator, ) { - this.log = createDebugLogger(`aztec:sequencer`); + this.log = createDebugLogger(`aztec:public_tx_simulator`); } static create( db: MerkleTreeReadOperations, publicExecutor: PublicExecutor, - publicKernelSimulator: PublicKernelCircuitSimulator, globalVariables: GlobalVariables, historicalHeader: Header, worldStateDB: WorldStateDB, @@ -69,16 +63,7 @@ export class PublicTxSimulator { realAvmProvingRequests, ); - const publicKernelTailSimulator = PublicKernelTailSimulator.create(db, publicKernelSimulator); - - return new PublicTxSimulator( - db, - publicKernelSimulator, - globalVariables, - worldStateDB, - enqueuedCallSimulator, - publicKernelTailSimulator, - ); + return new PublicTxSimulator(db, globalVariables, worldStateDB, enqueuedCallSimulator); } async process(tx: Tx): Promise { @@ -89,6 +74,7 @@ export class PublicTxSimulator { const setupResult = await this.processSetupPhase(context); const appLogicResult = await this.processAppLogicPhase(context); const teardownResult = await this.processTeardownPhase(context); + context.halt(); const processedPhases = [setupResult, appLogicResult, teardownResult].filter( result => result !== undefined, @@ -96,22 +82,17 @@ export class PublicTxSimulator { const endStateReference = await this.db.getStateReference(); - const tailKernelOutput = await this.publicKernelTailSimulator.simulate(context.latestPublicKernelOutput); + const avmProvingRequest = context.generateProvingRequest(endStateReference); + const avmCircuitPublicInputs = avmProvingRequest.inputs.output!; - generateAvmCircuitPublicInputsDeprecated( - tx, - tailKernelOutput, - context.getGasUsedForFee(), - context.getFinalTransactionFee(), + tx.filterRevertedLogs( + tx.data.forPublic!.nonRevertibleAccumulatedData, + avmCircuitPublicInputs.accumulatedData.unencryptedLogsHashes, ); - const gasUsed = { - totalGas: context.getActualGasUsed(), - teardownGas: context.teardownGasUsed, - }; return { - avmProvingRequest: context.generateProvingRequest(endStateReference), - gasUsed, + avmProvingRequest, + gasUsed: { totalGas: context.getActualGasUsed(), teardownGas: context.teardownGasUsed }, revertCode: context.revertCode, revertReason: context.revertReason, processedPhases: processedPhases, @@ -119,28 +100,25 @@ export class PublicTxSimulator { } private async processSetupPhase(context: PublicTxContext): Promise { - // Start in phase TxExecutionPhase.SETUP; - if (context.hasPhase()) { - return await this.processPhase(context); + if (context.hasPhase(TxExecutionPhase.SETUP)) { + return await this.processPhase(TxExecutionPhase.SETUP, context); } } private async processAppLogicPhase(context: PublicTxContext): Promise { - context.progressToNextPhase(); // to app logic - if (context.hasPhase()) { + if (context.hasPhase(TxExecutionPhase.APP_LOGIC)) { // Fork the state manager so that we can rollback state if app logic or teardown reverts. // Don't need to fork for setup since it's non-revertible (if setup fails, transaction is thrown out). context.state.fork(); - const result = await this.processPhase(context); + const result = await this.processPhase(TxExecutionPhase.APP_LOGIC, context); if (result.reverted) { // Drop the currently active forked state manager and rollback to end of setup. - // Fork again for teardown so that if teardown fails we can again rollback to end of setup. context.state.discardForkedState(); } else { if (!context.hasPhase(TxExecutionPhase.TEARDOWN)) { - // Nothing to do after this (no teardown), so merge state in now instead of letting teardown handle it. + // Nothing to do after this (no teardown), so merge state updates now instead of letting teardown handle it. context.state.mergeForkedState(); } } @@ -150,20 +128,20 @@ export class PublicTxSimulator { } private async processTeardownPhase(context: PublicTxContext): Promise { - context.progressToNextPhase(); // to teardown - if (context.hasPhase()) { + if (context.hasPhase(TxExecutionPhase.TEARDOWN)) { if (!context.state.isForked()) { - // if state isn't forked (app logic was empty or reverted), fork now - // so we can rollback to the end of setup on teardown revert + // If state isn't forked (app logic was empty or reverted), fork now + // so we can rollback to the end of setup if teardown reverts. context.state.fork(); } - const result = await this.processPhase(context); + const result = await this.processPhase(TxExecutionPhase.TEARDOWN, context); if (result.reverted) { // Drop the currently active forked state manager and rollback to end of setup. context.state.discardForkedState(); } else { + // Merge state updates from teardown, context.state.mergeForkedState(); } @@ -171,15 +149,13 @@ export class PublicTxSimulator { } } - private async processPhase(context: PublicTxContext): Promise { + private async processPhase(phase: TxExecutionPhase, context: PublicTxContext): Promise { const tx = context.tx; - const callRequests = context.getCallRequestsForCurrentPhase(); - const executionRequests = context.getExecutionRequestsForCurrentPhase(); + const callRequests = context.getCallRequestsForPhase(phase); + const executionRequests = context.getExecutionRequestsForPhase(phase); const txStateManager = context.state.getActiveStateManager(); - this.log.debug( - `Beginning processing in phase ${TxExecutionPhase[context.getCurrentPhase()]} for tx ${tx.getTxHash()}`, - ); + this.log.debug(`Beginning processing in phase ${TxExecutionPhase[phase]} for tx ${tx.getTxHash()}`); const returnValues: NestedProcessReturnValues[] = []; let reverted = false; @@ -202,57 +178,44 @@ export class PublicTxSimulator { // FIXME: we shouldn't need to directly modify worldStateDb here! await this.worldStateDB.addNewContracts(tx); - // each enqueued call starts with an incremented side effect counter - // FIXME: should be able to stop forking here and just trace the enqueued call (for hinting) - // and proceed with the same state manager for the entire phase - const enqueuedCallStateManager = txStateManager.fork(/*incrementSideEffectCounter=*/ true); const enqueuedCallResult = await this.enqueuedCallSimulator.simulate( callRequest, executionRequest, context.constants, - /*availableGas=*/ context.getGasLeftForCurrentPhase(), - /*transactionFee=*/ context.getTransactionFee(), - enqueuedCallStateManager, + /*availableGas=*/ context.getGasLeftForPhase(phase), + /*transactionFee=*/ context.getTransactionFee(phase), + txStateManager, ); + if (context.avmProvingRequest === undefined) { + // Propagate the very first avmProvingRequest of the tx for now. + // Eventually this will be the proof for the entire public portion of the transaction. + context.avmProvingRequest = enqueuedCallResult.avmProvingRequest; + } txStateManager.traceEnqueuedCall(callRequest, executionRequest.args, enqueuedCallResult.reverted!); - context.consumeGas(enqueuedCallResult.gasUsed); + context.consumeGas(phase, enqueuedCallResult.gasUsed); returnValues.push(enqueuedCallResult.returnValues); - // Propagate only one avmProvingRequest of a function call for now, so that we know it's still provable. - // Eventually this will be the proof for the entire public portion of the transaction. - context.avmProvingRequest = enqueuedCallResult.avmProvingRequest; + if (enqueuedCallResult.reverted) { reverted = true; const culprit = `${executionRequest.callContext.contractAddress}:${executionRequest.callContext.functionSelector}`; revertReason = enqueuedCallResult.revertReason; - context.revert(enqueuedCallResult.revertReason, culprit); // throws if in setup (non-revertible) phase + context.revert(phase, enqueuedCallResult.revertReason, culprit); // throws if in setup (non-revertible) phase // TODO(#6464): Should we allow emitting contracts in the private setup phase? // if so, this is removing contracts deployed in private setup // You can't submit contracts in public, so this is only relevant for private-created side effects // FIXME: we shouldn't need to directly modify worldStateDb here! await this.worldStateDB.removeNewContracts(tx); - // FIXME: we shouldn't be modifying the transaction here! - tx.filterRevertedLogs(context.latestPublicKernelOutput); - // Enqueeud call reverted. Discard state updates and accumulated side effects, but keep hints traced for the circuit. - txStateManager.rejectForkedState(enqueuedCallStateManager); } else { // FIXME: we shouldn't be modifying the transaction here! tx.unencryptedLogs.addFunctionLogs([enqueuedCallResult.newUnencryptedLogs]); - // Enqueued call succeeded! Merge in any state updates made in the forked state manager. - txStateManager.mergeForkedState(enqueuedCallStateManager); } - - context.latestPublicKernelOutput = await runMergeKernelCircuit( - context.latestPublicKernelOutput, - enqueuedCallResult.kernelOutput, - this.publicKernelSimulator, - ); } return { - phase: context.getCurrentPhase(), + phase, durationMs: phaseTimer.ms(), returnValues, reverted, diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts index 8cf1e32243b5..5682e7cb6cc7 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -106,8 +106,8 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.avmCircuitHints = AvmExecutionHints.empty(); } - public fork(incrementSideEffectCounter: boolean = false) { - return new PublicSideEffectTrace(incrementSideEffectCounter ? this.sideEffectCounter + 1 : this.sideEffectCounter); + public fork() { + return new PublicSideEffectTrace(this.sideEffectCounter); } public getCounter() { diff --git a/yarn-project/simulator/src/public/side_effect_trace_interface.ts b/yarn-project/simulator/src/public/side_effect_trace_interface.ts index cdcfd9c879cb..f3e427aecaab 100644 --- a/yarn-project/simulator/src/public/side_effect_trace_interface.ts +++ b/yarn-project/simulator/src/public/side_effect_trace_interface.ts @@ -17,7 +17,7 @@ import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.j import { type EnqueuedPublicCallExecutionResultWithSideEffects, type PublicFunctionCallResult } from './execution.js'; export interface PublicSideEffectTraceInterface { - fork(incrementSideEffectCounter?: boolean): PublicSideEffectTraceInterface; + fork(): PublicSideEffectTraceInterface; merge(nestedTrace: PublicSideEffectTraceInterface, reverted?: boolean): void; getCounter(): number; // all "trace*" functions can throw SideEffectLimitReachedError diff --git a/yarn-project/simulator/src/public/utils.ts b/yarn-project/simulator/src/public/utils.ts index ea45725aadb5..7fd607fd0ddc 100644 --- a/yarn-project/simulator/src/public/utils.ts +++ b/yarn-project/simulator/src/public/utils.ts @@ -1,48 +1,31 @@ import { type PublicExecutionRequest, type Tx, TxExecutionPhase } from '@aztec/circuit-types'; import { - AvmAccumulatedData, - AvmCircuitPublicInputs, - type CombinedAccumulatedData, - CombinedConstantData, - EnqueuedCallData, + type AvmCircuitPublicInputs, type Fr, type Gas, + type GasSettings, type GlobalVariables, - type KernelCircuitPublicInputs, MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, - NESTED_RECURSIVE_PROOF_LENGTH, - type PrivateKernelTailCircuitPublicInputs, PrivateToAvmAccumulatedData, PrivateToAvmAccumulatedDataArrayLengths, type PrivateToPublicAccumulatedData, PublicAccumulatedData, - type PublicCallRequest, + PublicCallRequest, PublicDataWrite, - PublicKernelCircuitPrivateInputs, - PublicKernelCircuitPublicInputs, - PublicKernelData, - PublicValidationRequests, - RevertCode, + type RevertCode, type StateReference, TreeSnapshots, - type VMCircuitPublicInputs, - VerificationKeyData, countAccumulatedItems, - makeEmptyProof, - makeEmptyRecursiveProof, mergeAccumulatedData, } from '@aztec/circuits.js'; import { computeNoteHashNonce, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; import { padArrayEnd } from '@aztec/foundation/collection'; import { assertLength } from '@aztec/foundation/serialize'; -import { getVKSiblingPath } from '@aztec/noir-protocol-circuits-types'; import { type PublicEnqueuedCallSideEffectTrace } from './enqueued_call_side_effect_trace.js'; -import { type PublicKernelCircuitSimulator } from './public_kernel_circuit_simulator.js'; export function getExecutionRequestsByPhase(tx: Tx, phase: TxExecutionPhase): PublicExecutionRequest[] { switch (phase) { @@ -74,135 +57,36 @@ export function getCallRequestsByPhase(tx: Tx, phase: TxExecutionPhase): PublicC } } -// Temporary hack to create PublicKernelCircuitPublicInputs from PrivateKernelTailCircuitPublicInputs. -export function getPublicKernelCircuitPublicInputs( - data: PrivateKernelTailCircuitPublicInputs, - globalVariables: GlobalVariables, -) { - const constants = CombinedConstantData.combine(data.constants, globalVariables); - - const validationRequest = PublicValidationRequests.empty(); - validationRequest.forRollup = data.rollupValidationRequests; - - const convertAccumulatedData = (from: PrivateToPublicAccumulatedData) => { - const to = PublicAccumulatedData.empty(); - to.noteHashes.forEach((_, i) => (to.noteHashes[i].noteHash.value = from.noteHashes[i])); - to.nullifiers.forEach((_, i) => (to.nullifiers[i].value = from.nullifiers[i])); - to.l2ToL1Msgs.forEach((_, i) => (to.l2ToL1Msgs[i] = from.l2ToL1Msgs[i])); - to.noteEncryptedLogsHashes.forEach((_, i) => (to.noteEncryptedLogsHashes[i] = from.noteEncryptedLogsHashes[i])); - to.encryptedLogsHashes.forEach((_, i) => (to.encryptedLogsHashes[i] = from.encryptedLogsHashes[i])); - to.publicCallStack.forEach((_, i) => (to.publicCallStack[i] = from.publicCallRequests[i])); - return to; - }; - - return new PublicKernelCircuitPublicInputs( - constants, - validationRequest, - convertAccumulatedData(data.forPublic!.nonRevertibleAccumulatedData), - convertAccumulatedData(data.forPublic!.revertibleAccumulatedData), - 0, - data.forPublic!.publicTeardownCallRequest, - data.feePayer, - RevertCode.OK, - ); -} - -// Temporary hack to create the AvmCircuitPublicInputs from public tail's public inputs. -export function generateAvmCircuitPublicInputsDeprecated( - tx: Tx, - tailOutput: KernelCircuitPublicInputs, - gasUsedForFee: Gas, - transactionFee: Fr, -) { - const startTreeSnapshots = new TreeSnapshots( - tailOutput.constants.historicalHeader.state.l1ToL2MessageTree, - tailOutput.startState.noteHashTree, - tailOutput.startState.nullifierTree, - tailOutput.startState.publicDataTree, - ); - - const getArrayLengths = (from: PrivateToPublicAccumulatedData) => - new PrivateToAvmAccumulatedDataArrayLengths( - countAccumulatedItems(from.noteHashes), - countAccumulatedItems(from.nullifiers), - countAccumulatedItems(from.l2ToL1Msgs), - ); - - const convertAccumulatedData = (from: PrivateToPublicAccumulatedData) => - new PrivateToAvmAccumulatedData(from.noteHashes, from.nullifiers, from.l2ToL1Msgs); - - const convertAvmAccumulatedData = (from: CombinedAccumulatedData) => - new AvmAccumulatedData( - from.noteHashes, - from.nullifiers, - from.l2ToL1Msgs, - from.unencryptedLogsHashes, - from.publicDataWrites, - ); - - // This is wrong. But this is not used or checked in the rollup at the moment. - // Should fetch the updated roots from db. - const endTreeSnapshots = startTreeSnapshots; - - const avmCircuitPublicInputs = new AvmCircuitPublicInputs( - tailOutput.constants.globalVariables, - startTreeSnapshots, - tx.data.gasUsed, - tx.data.constants.txContext.gasSettings, - tx.data.forPublic!.nonRevertibleAccumulatedData.publicCallRequests, - tx.data.forPublic!.revertibleAccumulatedData.publicCallRequests, - tx.data.forPublic!.publicTeardownCallRequest, - getArrayLengths(tx.data.forPublic!.nonRevertibleAccumulatedData), - getArrayLengths(tx.data.forPublic!.revertibleAccumulatedData), - convertAccumulatedData(tx.data.forPublic!.nonRevertibleAccumulatedData), - convertAccumulatedData(tx.data.forPublic!.revertibleAccumulatedData), - endTreeSnapshots, - gasUsedForFee, - convertAvmAccumulatedData(tailOutput.end), - transactionFee, - !tailOutput.revertCode.equals(RevertCode.OK), +export function convertPrivateToPublicAccumulatedData( + fromPrivate: PrivateToPublicAccumulatedData, +): PublicAccumulatedData { + const to = PublicAccumulatedData.empty(); + to.noteHashes.forEach((_, i) => (to.noteHashes[i].noteHash.value = fromPrivate.noteHashes[i])); + to.nullifiers.forEach((_, i) => (to.nullifiers[i].value = fromPrivate.nullifiers[i])); + to.l2ToL1Msgs.forEach((_, i) => (to.l2ToL1Msgs[i] = fromPrivate.l2ToL1Msgs[i])); + to.noteEncryptedLogsHashes.forEach( + (_, i) => (to.noteEncryptedLogsHashes[i] = fromPrivate.noteEncryptedLogsHashes[i]), ); - //console.log(`Old AvmCircuitPublicInputs:\n${inspect(avmCircuitPublicInputs)}`); - return avmCircuitPublicInputs; -} - -function getPreviousKernelData(previousOutput: PublicKernelCircuitPublicInputs): PublicKernelData { - // The proof is not used in simulation. - const proof = makeEmptyRecursiveProof(NESTED_RECURSIVE_PROOF_LENGTH); - - const vk = VerificationKeyData.makeFakeHonk(); - const vkIndex = 0; - const siblingPath = getVKSiblingPath(vkIndex); - - return new PublicKernelData(previousOutput, proof, vk, vkIndex, siblingPath); -} - -export async function runMergeKernelCircuit( - previousOutput: PublicKernelCircuitPublicInputs, - enqueuedCallData: VMCircuitPublicInputs, - publicKernelSimulator: PublicKernelCircuitSimulator, -): Promise { - const previousKernel = getPreviousKernelData(previousOutput); - - // The proof is not used in simulation. - const vmProof = makeEmptyProof(); - const callData = new EnqueuedCallData(enqueuedCallData, vmProof); - - const inputs = new PublicKernelCircuitPrivateInputs(previousKernel, callData); - - return await publicKernelSimulator.publicKernelCircuitMerge(inputs); + to.encryptedLogsHashes.forEach((_, i) => (to.encryptedLogsHashes[i] = fromPrivate.encryptedLogsHashes[i])); + to.publicCallStack.forEach((_, i) => (to.publicCallStack[i] = fromPrivate.publicCallRequests[i])); + return to; } export function generateAvmCircuitPublicInputs( - tx: Tx, trace: PublicEnqueuedCallSideEffectTrace, globalVariables: GlobalVariables, startStateReference: StateReference, + startGasUsed: Gas, + gasSettings: GasSettings, + setupCallRequests: PublicCallRequest[], + appLogicCallRequests: PublicCallRequest[], + teardownCallRequests: PublicCallRequest[], + nonRevertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData, + revertibleAccumulatedDataFromPrivate: PrivateToPublicAccumulatedData, endStateReference: StateReference, endGasUsed: Gas, transactionFee: Fr, revertCode: RevertCode, - firstPublicKernelOutput: PublicKernelCircuitPublicInputs, ): AvmCircuitPublicInputs { const startTreeSnapshots = new TreeSnapshots( startStateReference.l1ToL2MessageTree, @@ -220,11 +104,11 @@ export function generateAvmCircuitPublicInputs( const avmCircuitPublicInputs = trace.toAvmCircuitPublicInputs( globalVariables, startTreeSnapshots, - tx.data.gasUsed, - tx.data.constants.txContext.gasSettings, - tx.data.forPublic!.nonRevertibleAccumulatedData.publicCallRequests, - tx.data.forPublic!.revertibleAccumulatedData.publicCallRequests, - tx.data.forPublic!.publicTeardownCallRequest, + startGasUsed, + gasSettings, + setupCallRequests, + appLogicCallRequests, + teardownCallRequests.length ? teardownCallRequests[0] : PublicCallRequest.empty(), endTreeSnapshots, endGasUsed, transactionFee, @@ -241,16 +125,16 @@ export function generateAvmCircuitPublicInputs( new PrivateToAvmAccumulatedData(from.noteHashes, from.nullifiers, from.l2ToL1Msgs); // Temporary overrides as these entries aren't yet populated in trace avmCircuitPublicInputs.previousNonRevertibleAccumulatedDataArrayLengths = getArrayLengths( - tx.data.forPublic!.nonRevertibleAccumulatedData, + nonRevertibleAccumulatedDataFromPrivate, ); avmCircuitPublicInputs.previousRevertibleAccumulatedDataArrayLengths = getArrayLengths( - tx.data.forPublic!.revertibleAccumulatedData, + revertibleAccumulatedDataFromPrivate, ); avmCircuitPublicInputs.previousNonRevertibleAccumulatedData = convertAccumulatedData( - tx.data.forPublic!.nonRevertibleAccumulatedData, + nonRevertibleAccumulatedDataFromPrivate, ); avmCircuitPublicInputs.previousRevertibleAccumulatedData = convertAccumulatedData( - tx.data.forPublic!.revertibleAccumulatedData, + revertibleAccumulatedDataFromPrivate, ); // merge all revertible & non-revertible side effects into output accumulated data @@ -300,16 +184,6 @@ export function generateAvmCircuitPublicInputs( mergeAccumulatedData(msgsFromPrivate, avmCircuitPublicInputs.accumulatedData.l2ToL1Msgs), MAX_L2_TO_L1_MSGS_PER_TX, ); - const ulogsFromPrivate = revertCode.isOK() - ? mergeAccumulatedData( - firstPublicKernelOutput.endNonRevertibleData.unencryptedLogsHashes, - firstPublicKernelOutput.end.unencryptedLogsHashes, - ) - : firstPublicKernelOutput.endNonRevertibleData.unencryptedLogsHashes; - avmCircuitPublicInputs.accumulatedData.unencryptedLogsHashes = assertLength( - mergeAccumulatedData(ulogsFromPrivate, avmCircuitPublicInputs.accumulatedData.unencryptedLogsHashes), - MAX_UNENCRYPTED_LOGS_PER_TX, - ); const dedupedPublicDataWrites: Array = []; const leafSlotOccurences: Map = new Map();