Skip to content

Commit

Permalink
refactor: remove EnqueuedCallSimulator
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanks12 committed Nov 17, 2024
1 parent 7e3c14c commit fee500b
Show file tree
Hide file tree
Showing 7 changed files with 438 additions and 235 deletions.
4 changes: 2 additions & 2 deletions yarn-project/simulator/src/public/public_processor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ describe('public_processor', () => {

worldStateDB.storageRead.mockResolvedValue(Fr.ZERO);

publicTxProcessor.process.mockImplementation(() => {
publicTxProcessor.simulate.mockImplementation(() => {
return Promise.resolve(mockedEnqueuedCallsResult);
});

Expand Down Expand Up @@ -136,7 +136,7 @@ describe('public_processor', () => {
});

it('returns failed txs without aborting entire operation', async function () {
publicTxProcessor.process.mockRejectedValue(new SimulationError(`Failed`, []));
publicTxProcessor.simulate.mockRejectedValue(new SimulationError(`Failed`, []));

const tx = mockTxWithPublicCalls();
const [processed, failed] = await processor.process([tx], 1, handler);
Expand Down
10 changes: 2 additions & 8 deletions yarn-project/simulator/src/public/public_processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,7 @@ export class PublicProcessor {
worldStateDB: WorldStateDB,
telemetryClient: TelemetryClient,
) {
const publicTxSimulator = PublicTxSimulator.create(
db,
publicExecutor,
globalVariables,
historicalHeader,
worldStateDB,
);
const publicTxSimulator = PublicTxSimulator.create(db, publicExecutor, globalVariables, worldStateDB);

return new PublicProcessor(db, globalVariables, historicalHeader, worldStateDB, publicTxSimulator, telemetryClient);
}
Expand Down Expand Up @@ -281,7 +275,7 @@ export class PublicProcessor {
const timer = new Timer();

const { avmProvingRequest, gasUsed, revertCode, revertReason, processedPhases } =
await this.publicTxSimulator.process(tx);
await this.publicTxSimulator.simulate(tx);

if (!avmProvingRequest) {
this.metrics.recordFailedTx();
Expand Down
44 changes: 34 additions & 10 deletions yarn-project/simulator/src/public/public_tx_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import {
} from '@aztec/circuit-types';
import {
type AvmCircuitPublicInputs,
CombinedConstantData,
Fr,
Gas,
type GasSettings,
type GlobalVariables,
type Header,
type PrivateToPublicAccumulatedData,
PublicAccumulatedDataArrayLengths,
type PublicCallRequest,
Expand All @@ -29,14 +29,11 @@ import { inspect } from 'util';
import { AvmPersistableStateManager } from '../avm/index.js';
import { DualSideEffectTrace } from './dual_side_effect_trace.js';
import { PublicEnqueuedCallSideEffectTrace } from './enqueued_call_side_effect_trace.js';
import { type EnqueuedPublicCallExecutionResult } from './execution.js';
import { type WorldStateDB } from './public_db_sources.js';
import { PublicSideEffectTrace } from './side_effect_trace.js';
import {
convertPrivateToPublicAccumulatedData,
generateAvmCircuitPublicInputs,
getCallRequestsByPhase,
getExecutionRequestsByPhase,
} from './utils.js';
import { generateAvmCircuitPublicInputs, generateAvmProvingRequest } from './transitional_adapters.js';
import { convertPrivateToPublicAccumulatedData, getCallRequestsByPhase, getExecutionRequestsByPhase } from './utils.js';

export class PublicTxContext {
private log: DebugLogger;
Expand All @@ -53,12 +50,12 @@ export class PublicTxContext {
/* What caused a revert (if one occurred)? */
public revertReason: SimulationError | undefined;

public avmProvingRequest: AvmProvingRequest | undefined; // tmp hack
public avmProvingRequest: AvmProvingRequest | undefined; // FIXME(dbanks12): remove

constructor(
public readonly state: PhaseStateManager,
private readonly globalVariables: GlobalVariables,
public readonly constants: CombinedConstantData, // FIXME(dbanks12): remove
private readonly historicalHeader: Header, // FIXME(dbanks12): remove
private readonly startStateReference: StateReference,
private readonly startGasUsed: Gas,
private readonly gasSettings: GasSettings,
Expand Down Expand Up @@ -114,7 +111,7 @@ export class PublicTxContext {
return new PublicTxContext(
new PhaseStateManager(txStateManager),
globalVariables,
CombinedConstantData.combine(tx.data.constants, globalVariables),
tx.data.constants.historicalHeader,
await db.getStateReference(),
tx.data.gasUsed,
tx.data.constants.txContext.gasSettings,
Expand Down Expand Up @@ -334,6 +331,33 @@ export class PublicTxContext {
this.avmProvingRequest!.inputs.output = this.generateAvmCircuitPublicInputs(endStateReference);
return this.avmProvingRequest!;
}

// TODO(dbanks12): remove once AVM proves entire public tx
async updateProvingRequest(
real: boolean,
phase: TxExecutionPhase,
worldStateDB: WorldStateDB,
stateManager: AvmPersistableStateManager,
executionRequest: PublicExecutionRequest,
result: EnqueuedPublicCallExecutionResult,
allocatedGas: Gas,
) {
if (this.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.
this.avmProvingRequest = await generateAvmProvingRequest(
real,
worldStateDB,
stateManager,
this.historicalHeader,
this.globalVariables,
executionRequest,
result,
allocatedGas,
this.getTransactionFee(phase),
);
}
}
}

class PhaseStateManager {
Expand Down
19 changes: 9 additions & 10 deletions yarn-project/simulator/src/public/public_tx_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ describe('public_tx_simulator', () => {
db,
publicExecutor,
GlobalVariables.from({ ...GlobalVariables.empty(), gasFees }),
Header.empty(),
worldStateDB,
/*realAvmProvingRequest=*/ false,
);
Expand All @@ -174,7 +173,7 @@ describe('public_tx_simulator', () => {
numberOfSetupCalls: 2,
});

const txResult = await processor.process(tx);
const txResult = await processor.simulate(tx);

expect(txResult.processedPhases).toEqual([
expect.objectContaining({ phase: TxExecutionPhase.SETUP, revertReason: undefined }),
Expand Down Expand Up @@ -209,7 +208,7 @@ describe('public_tx_simulator', () => {
numberOfAppLogicCalls: 2,
});

const txResult = await processor.process(tx);
const txResult = await processor.simulate(tx);

expect(txResult.processedPhases).toEqual([
expect.objectContaining({ phase: TxExecutionPhase.APP_LOGIC, revertReason: undefined }),
Expand Down Expand Up @@ -244,7 +243,7 @@ describe('public_tx_simulator', () => {
hasPublicTeardownCall: true,
});

const txResult = await processor.process(tx);
const txResult = await processor.simulate(tx);

expect(txResult.processedPhases).toEqual([
expect.objectContaining({ phase: TxExecutionPhase.TEARDOWN, revertReason: undefined }),
Expand Down Expand Up @@ -279,7 +278,7 @@ describe('public_tx_simulator', () => {
hasPublicTeardownCall: true,
});

const txResult = await processor.process(tx);
const txResult = await processor.simulate(tx);

expect(txResult.processedPhases).toHaveLength(3);
expect(txResult.processedPhases).toEqual([
Expand Down Expand Up @@ -357,7 +356,7 @@ describe('public_tx_simulator', () => {
},
]);

const txResult = await processor.process(tx);
const txResult = await processor.simulate(tx);

expect(publicExecutor.simulate).toHaveBeenCalledTimes(3);

Expand Down Expand Up @@ -391,7 +390,7 @@ describe('public_tx_simulator', () => {
PublicExecutionResultBuilder.empty().withReverted(setupFailure).build(),
);

await expect(processor.process(tx)).rejects.toThrow(setupFailureMsg);
await expect(processor.simulate(tx)).rejects.toThrow(setupFailureMsg);

expect(publicExecutor.simulate).toHaveBeenCalledTimes(1);
});
Expand Down Expand Up @@ -426,7 +425,7 @@ describe('public_tx_simulator', () => {
},
]);

const txResult = await processor.process(tx);
const txResult = await processor.simulate(tx);

expect(txResult.processedPhases).toHaveLength(3);
expect(txResult.processedPhases).toEqual([
Expand Down Expand Up @@ -504,7 +503,7 @@ describe('public_tx_simulator', () => {
},
]);

const txResult = await processor.process(tx);
const txResult = await processor.simulate(tx);

expect(txResult.processedPhases).toEqual([
expect.objectContaining({ phase: TxExecutionPhase.SETUP, revertReason: undefined }),
Expand Down Expand Up @@ -586,7 +585,7 @@ describe('public_tx_simulator', () => {
},
]);

const txResult = await processor.process(tx);
const txResult = await processor.simulate(tx);

expect(txResult.processedPhases).toHaveLength(3);
expect(txResult.processedPhases).toEqual([
Expand Down
81 changes: 43 additions & 38 deletions yarn-project/simulator/src/public/public_tx_simulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import {
type AvmProvingRequest,
type GasUsed,
type MerkleTreeReadOperations,
type NestedProcessReturnValues,
NestedProcessReturnValues,
type SimulationError,
type Tx,
TxExecutionPhase,
UnencryptedFunctionL2Logs,
} from '@aztec/circuit-types';
import { type GlobalVariables, type Header, type RevertCode } from '@aztec/circuits.js';
import { Gas, type GlobalVariables, MAX_L2_GAS_PER_ENQUEUED_CALL, type RevertCode } from '@aztec/circuits.js';
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
import { Timer } from '@aztec/foundation/timer';

import { EnqueuedCallSimulator } from './enqueued_call_simulator.js';
import { type EnqueuedPublicCallExecutionResult } from './execution.js';
import { type PublicExecutor } from './executor.js';
import { type WorldStateDB } from './public_db_sources.js';
import { PublicTxContext } from './public_tx_context.js';
Expand Down Expand Up @@ -42,7 +42,8 @@ export class PublicTxSimulator {
private db: MerkleTreeReadOperations,
private globalVariables: GlobalVariables,
private worldStateDB: WorldStateDB,
private enqueuedCallSimulator: EnqueuedCallSimulator,
private publicExecutor: PublicExecutor,
private realAvmProvingRequests: boolean = true,
) {
this.log = createDebugLogger(`aztec:public_tx_simulator`);
}
Expand All @@ -51,23 +52,13 @@ export class PublicTxSimulator {
db: MerkleTreeReadOperations,
publicExecutor: PublicExecutor,
globalVariables: GlobalVariables,
historicalHeader: Header,
worldStateDB: WorldStateDB,
realAvmProvingRequests: boolean = true,
) {
const enqueuedCallSimulator = new EnqueuedCallSimulator(
db,
worldStateDB,
publicExecutor,
globalVariables,
historicalHeader,
realAvmProvingRequests,
);

return new PublicTxSimulator(db, globalVariables, worldStateDB, enqueuedCallSimulator);
return new PublicTxSimulator(db, globalVariables, worldStateDB, publicExecutor, realAvmProvingRequests);
}

async process(tx: Tx): Promise<PublicTxResult> {
async simulate(tx: Tx): Promise<PublicTxResult> {
this.log.verbose(`Processing tx ${tx.getTxHash()}`);

const context = await PublicTxContext.create(this.db, this.worldStateDB, tx, this.globalVariables);
Expand All @@ -83,15 +74,15 @@ export class PublicTxSimulator {

const processedPhases: ProcessedPhase[] = [];
if (context.hasPhase(TxExecutionPhase.SETUP)) {
const setupResult: ProcessedPhase = await this.processSetupPhase(context);
const setupResult: ProcessedPhase = await this.simulateSetupPhase(context);
processedPhases.push(setupResult);
}
if (context.hasPhase(TxExecutionPhase.APP_LOGIC)) {
const appLogicResult: ProcessedPhase = await this.processAppLogicPhase(context);
const appLogicResult: ProcessedPhase = await this.simulateAppLogicPhase(context);
processedPhases.push(appLogicResult);
}
if (context.hasPhase(TxExecutionPhase.TEARDOWN)) {
const teardownResult: ProcessedPhase = await this.processTeardownPhase(context);
const teardownResult: ProcessedPhase = await this.simulateTeardownPhase(context);
processedPhases.push(teardownResult);
}
context.halt();
Expand Down Expand Up @@ -128,16 +119,16 @@ export class PublicTxSimulator {
};
}

private async processSetupPhase(context: PublicTxContext): Promise<ProcessedPhase> {
return await this.processPhase(TxExecutionPhase.SETUP, context);
private async simulateSetupPhase(context: PublicTxContext): Promise<ProcessedPhase> {
return await this.simulatePhase(TxExecutionPhase.SETUP, context);
}

private async processAppLogicPhase(context: PublicTxContext): Promise<ProcessedPhase> {
private async simulateAppLogicPhase(context: PublicTxContext): Promise<ProcessedPhase> {
// 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(TxExecutionPhase.APP_LOGIC, context);
const result = await this.simulatePhase(TxExecutionPhase.APP_LOGIC, context);

if (result.reverted) {
// Drop the currently active forked state manager and rollback to end of setup.
Expand All @@ -152,14 +143,14 @@ export class PublicTxSimulator {
return result;
}

private async processTeardownPhase(context: PublicTxContext): Promise<ProcessedPhase> {
private async simulateTeardownPhase(context: PublicTxContext): Promise<ProcessedPhase> {
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 if teardown reverts.
context.state.fork();
}

const result = await this.processPhase(TxExecutionPhase.TEARDOWN, context);
const result = await this.simulatePhase(TxExecutionPhase.TEARDOWN, context);

if (result.reverted) {
// Drop the currently active forked state manager and rollback to end of setup.
Expand All @@ -172,7 +163,7 @@ export class PublicTxSimulator {
return result;
}

private async processPhase(phase: TxExecutionPhase, context: PublicTxContext): Promise<ProcessedPhase> {
private async simulatePhase(phase: TxExecutionPhase, context: PublicTxContext): Promise<ProcessedPhase> {
const callRequests = context.getCallRequestsForPhase(phase);
const executionRequests = context.getExecutionRequestsForPhase(phase);
const txStateManager = context.state.getActiveStateManager();
Expand All @@ -191,24 +182,38 @@ export class PublicTxSimulator {
const callRequest = callRequests[i];
const executionRequest = executionRequests[i];

const enqueuedCallResult = await this.enqueuedCallSimulator.simulate(
callRequest,
const availableGas = context.getGasLeftForPhase(phase);
// Gas allocated to an enqueued call can be different from the available gas
// if there is more gas available than the max allocation per enqueued call.
const allocatedGas = new Gas(
/*daGas=*/ availableGas.daGas,
/*l2Gas=*/ Math.min(availableGas.l2Gas, MAX_L2_GAS_PER_ENQUEUED_CALL),
);

const enqueuedCallResult = (await this.publicExecutor.simulate(
txStateManager,
executionRequest,
context.constants,
/*availableGas=*/ context.getGasLeftForPhase(phase),
/*transactionFee=*/ context.getTransactionFee(phase),
this.globalVariables, // todo get from context
allocatedGas,
context.getTransactionFee(phase),
)) as EnqueuedPublicCallExecutionResult;

// TODO(dbanks12): remove once AVM proves entire public tx
await context.updateProvingRequest(
this.realAvmProvingRequests,
phase,
this.worldStateDB,
txStateManager,
executionRequest,
enqueuedCallResult,
allocatedGas,
);
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(phase, enqueuedCallResult.gasUsed);
returnValues.push(enqueuedCallResult.returnValues);
const gasUsed = allocatedGas.sub(Gas.from(enqueuedCallResult.endGasLeft));
context.consumeGas(phase, gasUsed);
returnValues.push(new NestedProcessReturnValues(enqueuedCallResult.returnValues));

if (enqueuedCallResult.reverted) {
reverted = true;
Expand Down
Loading

0 comments on commit fee500b

Please sign in to comment.