Skip to content

Commit

Permalink
refactor: stop calling public kernels
Browse files Browse the repository at this point in the history
  • Loading branch information
dbanks12 committed Nov 14, 2024
1 parent 1ff73fb commit 0ba3950
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 55 deletions.
126 changes: 79 additions & 47 deletions yarn-project/simulator/src/public/public_tx_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
PublicValidationRequestArrayLengths,
RevertCode,
type StateReference,
AvmCircuitPublicInputs,
PrivateKernelTailCircuitPublicInputs,
} from '@aztec/circuits.js';

import { assert } from 'console';
Expand All @@ -27,40 +29,7 @@ import { DualSideEffectTrace } from './dual_side_effect_trace.js';
import { PublicEnqueuedCallSideEffectTrace } from './enqueued_call_side_effect_trace.js';
import { type WorldStateDB } from './public_db_sources.js';
import { PublicSideEffectTrace } from './side_effect_trace.js';
import { getCallRequestsByPhase, getExecutionRequestsByPhase, getPublicKernelCircuitPublicInputs } from './utils.js';

class PhaseStateManager {
private currentlyActiveStateManager: AvmPersistableStateManager | undefined;

constructor(private readonly txStateManager: AvmPersistableStateManager) {}

fork() {
assert(!this.currentlyActiveStateManager, 'Cannot fork when already forked');
this.currentlyActiveStateManager = this.txStateManager.fork();
}

getActiveStateManager() {
return this.currentlyActiveStateManager || this.txStateManager;
}

isForked() {
return !!this.currentlyActiveStateManager;
}

mergeForkedState() {
assert(this.currentlyActiveStateManager, 'No forked state to merge');
this.txStateManager.mergeForkedState(this.currentlyActiveStateManager!);
// Drop the forked state manager now that it is merged
this.currentlyActiveStateManager = undefined;
}

discardForkedState() {
assert(this.currentlyActiveStateManager, 'No forked state to discard');
this.txStateManager.rejectForkedState(this.currentlyActiveStateManager!);
// Drop the forked state manager. We don't want it!
this.currentlyActiveStateManager = undefined;
}
}
import { generateAvmCircuitPublicInputs, getCallRequestsByPhase, getExecutionRequestsByPhase, getPublicKernelCircuitPublicInputs } from './utils.js';

export class PublicTxContext {
private currentPhase: TxExecutionPhase = TxExecutionPhase.SETUP;
Expand All @@ -76,7 +45,7 @@ export class PublicTxContext {
public avmProvingRequest: AvmProvingRequest | undefined; // tmp hack

constructor(
public readonly state: PhaseStateManager,
public readonly state: PhaseStateForker,
public readonly tx: Tx, // tmp hack
public readonly globalVariables: GlobalVariables,
public readonly constants: CombinedConstantData, // tmp hack
Expand All @@ -89,7 +58,9 @@ export class PublicTxContext {
private readonly setupExecutionRequests: PublicExecutionRequest[],
private readonly appLogicExecutionRequests: PublicExecutionRequest[],
private readonly teardownExecutionRequests: PublicExecutionRequest[],
private firstPublicKernelOutput: PublicKernelCircuitPublicInputs,
public latestPublicKernelOutput: PublicKernelCircuitPublicInputs,
private enqueuedCallTrace: PublicEnqueuedCallSideEffectTrace,
) {
this.gasUsed = startGasUsed;
}
Expand All @@ -101,19 +72,19 @@ export class PublicTxContext {
globalVariables: GlobalVariables,
) {
const privateKernelOutput = tx.data;
const latestPublicKernelOutput = getPublicKernelCircuitPublicInputs(privateKernelOutput, globalVariables);
const firstPublicKernelOutput = getPublicKernelCircuitPublicInputs(privateKernelOutput, globalVariables);

const nonRevertibleNullifiersFromPrivate = latestPublicKernelOutput.endNonRevertibleData.nullifiers
const nonRevertibleNullifiersFromPrivate = firstPublicKernelOutput.endNonRevertibleData.nullifiers
.filter(n => !n.isEmpty())
.map(n => n.value);
const _revertibleNullifiersFromPrivate = latestPublicKernelOutput.end.nullifiers
const _revertibleNullifiersFromPrivate = firstPublicKernelOutput.end.nullifiers
.filter(n => !n.isEmpty())
.map(n => n.value);

// During SETUP, non revertible side effects from private are our "previous data"
const prevAccumulatedData = latestPublicKernelOutput.endNonRevertibleData;
const prevAccumulatedData = firstPublicKernelOutput.endNonRevertibleData;
const previousValidationRequestArrayLengths = PublicValidationRequestArrayLengths.new(
latestPublicKernelOutput.validationRequests,
firstPublicKernelOutput.validationRequests,
);

const previousAccumulatedDataArrayLengths = PublicAccumulatedDataArrayLengths.new(prevAccumulatedData);
Expand All @@ -134,7 +105,7 @@ export class PublicTxContext {
);

return new PublicTxContext(
new PhaseStateManager(txStateManager),
new PhaseStateForker(txStateManager),
tx,
globalVariables,
CombinedConstantData.combine(tx.data.constants, globalVariables),
Expand All @@ -147,7 +118,9 @@ export class PublicTxContext {
getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP),
getExecutionRequestsByPhase(tx, TxExecutionPhase.APP_LOGIC),
getExecutionRequestsByPhase(tx, TxExecutionPhase.TEARDOWN),
latestPublicKernelOutput,
firstPublicKernelOutput,
firstPublicKernelOutput,
enqueuedCallTrace
);
}

Expand Down Expand Up @@ -176,11 +149,6 @@ export class PublicTxContext {
}

revert(revertReason: SimulationError | undefined = undefined, culprit = '') {
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) {
throw new Error(
`Setup phase reverted! The transaction will be thrown out. ${culprit} failed with reason: ${revertReason}`,
Expand All @@ -194,6 +162,11 @@ export class PublicTxContext {
this.revertCode = RevertCode.TEARDOWN_REVERTED;
}
}
if (revertReason && !this.revertReason) {
// don't override revertReason
// (if app logic and teardown both revert, we want app logic's reason)
this.revertReason = revertReason;
}
}

getCallRequestsForCurrentPhase(): PublicCallRequest[] {
Expand Down Expand Up @@ -266,4 +239,63 @@ export class PublicTxContext {
//this.log.debug(`Computed tx fee`, { txFee, gasUsed: inspect(phaseGasUsed), gasFees: inspect(gasFees) });
return this.gasUsed.computeFee(this.globalVariables.gasFees);
}

private async generateAvmCircuitPublicInputs(endStateReference: StateReference): Promise<AvmCircuitPublicInputs> {
assert(this.currentPhase === TxExecutionPhase.TEARDOWN, 'Can only get AvmCircuitPublicInputs after teardown (tx done)');
return generateAvmCircuitPublicInputs(
this.tx,
this.enqueuedCallTrace,
this.globalVariables,
this.startStateReference,
endStateReference,
this.getActualGasUsed(),
this.getTransactionFee(),
this.revertCode,
this.firstPublicKernelOutput,
);
}

async generateProvingRequest(endStateReference: StateReference): Promise<AvmProvingRequest> {
// TODO(dbanks12): Once we actually have tx-level proving, this will generate the entire
// proving request for the first time
this.avmProvingRequest!.inputs.output = await this.generateAvmCircuitPublicInputs(endStateReference);
return this.avmProvingRequest!;
}
}

/**
* A thin wrapper for the state manager for forking and merging state per phase.
* This lets us keep track of
*/
class PhaseStateForker {
private currentlyActiveStateManager: AvmPersistableStateManager | undefined;

constructor(private readonly txStateManager: AvmPersistableStateManager) {}

fork() {
assert(!this.currentlyActiveStateManager, 'Cannot fork when already forked');
this.currentlyActiveStateManager = this.txStateManager.fork();
}

getActiveStateManager() {
return this.currentlyActiveStateManager || this.txStateManager;
}

isForked() {
return !!this.currentlyActiveStateManager;
}

mergeForkedState() {
assert(this.currentlyActiveStateManager, 'No forked state to merge');
this.txStateManager.mergeForkedState(this.currentlyActiveStateManager!);
// Drop the forked state manager now that it is merged
this.currentlyActiveStateManager = undefined;
}

discardForkedState() {
assert(this.currentlyActiveStateManager, 'No forked state to discard');
this.txStateManager.rejectForkedState(this.currentlyActiveStateManager!);
// Drop the forked state manager. We don't want it!
this.currentlyActiveStateManager = undefined;
}
}
12 changes: 5 additions & 7 deletions yarn-project/simulator/src/public/public_tx_processor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ 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 { generateAvmCircuitPublicInputs, runMergeKernelCircuit } from './utils.js';
import { generateAvmCircuitPublicInputs, generateAvmCircuitPublicInputsDeprecated, runMergeKernelCircuit } from './utils.js';

export type ProcessedPhase = {
phase: TxExecutionPhase;
Expand Down Expand Up @@ -94,24 +94,22 @@ export class PublicTxProcessor {
result => result !== undefined,
) as ProcessedPhase[];

const _endStateReference = await this.db.getStateReference();
const transactionFee = context.getTransactionFee();
const endStateReference = await this.db.getStateReference();

const tailKernelOutput = await this.publicKernelTailSimulator.simulate(context.latestPublicKernelOutput);

context.avmProvingRequest!.inputs.output = generateAvmCircuitPublicInputs(
generateAvmCircuitPublicInputsDeprecated(
tx,
tailKernelOutput,
context.getGasUsedForFee(),
transactionFee,
context.getTransactionFee(),
);

const gasUsed = {
totalGas: context.getActualGasUsed(),
teardownGas: context.teardownGasUsed,
};
return {
avmProvingRequest: context.avmProvingRequest!,
avmProvingRequest: await context.generateProvingRequest(endStateReference),
gasUsed,
revertCode: context.revertCode,
revertReason: context.revertReason,
Expand Down
Loading

0 comments on commit 0ba3950

Please sign in to comment.