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 889d1c9 commit 269acb7
Show file tree
Hide file tree
Showing 8 changed files with 240 additions and 95 deletions.
9 changes: 6 additions & 3 deletions yarn-project/simulator/src/avm/journal/journal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,18 +428,21 @@ export class AvmPersistableStateManager {
}

/**
* Accept nested world state modifications
* Accept forked world state modifications & traced side effects / hints
*/
public mergeForkedState(forkedState: AvmPersistableStateManager) {
this.publicStorage.acceptAndMerge(forkedState.publicStorage);
this.nullifiers.acceptAndMerge(forkedState.nullifiers);
this.trace.mergeSuccessfulForkedTrace(forkedState.trace);
this.trace.mergeForkedTrace(forkedState.trace, /*reverted=*/ false);
}

/**
* Reject forked world state modifications & traced side effects, keep traced hints
*/
public rejectForkedState(forkedState: AvmPersistableStateManager) {
this.publicStorage.acceptAndMerge(forkedState.publicStorage);
this.nullifiers.acceptAndMerge(forkedState.nullifiers);
this.trace.mergeRevertedForkedTrace(forkedState.trace);
this.trace.mergeForkedTrace(forkedState.trace, /*reverted=*/ true);
}

/**
Expand Down
8 changes: 2 additions & 6 deletions yarn-project/simulator/src/public/dual_side_effect_trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,8 @@ export class DualSideEffectTrace implements PublicSideEffectTraceInterface {
this.enqueuedCallTrace.traceEnqueuedCall(publicCallRequest, calldata, reverted);
}

public mergeSuccessfulForkedTrace(nestedTrace: this) {
this.enqueuedCallTrace.mergeSuccessfulForkedTrace(nestedTrace.enqueuedCallTrace);
}

public mergeRevertedForkedTrace(nestedTrace: this) {
this.enqueuedCallTrace.mergeRevertedForkedTrace(nestedTrace.enqueuedCallTrace);
public mergeForkedTrace(nestedTrace: this, reverted: boolean = false) {
this.enqueuedCallTrace.mergeForkedTrace(nestedTrace.enqueuedCallTrace, reverted);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,36 +523,24 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
this.avmCircuitHints.enqueuedCalls.items.push(new AvmEnqueuedCallHint(publicCallRequest.contractAddress, calldata));
}

public mergeSuccessfulForkedTrace(nestedTrace: this) {
public mergeForkedTrace(nestedTrace: this, reverted: boolean = false) {
// TODO(dbanks12): accept & merge nested trace's hints!
this.sideEffectCounter = nestedTrace.sideEffectCounter;

this.enqueuedCalls.push(...nestedTrace.enqueuedCalls);

this.publicDataReads.push(...nestedTrace.publicDataReads);
this.publicDataWrites.push(...nestedTrace.publicDataWrites);
this.noteHashReadRequests.push(...nestedTrace.noteHashReadRequests);
this.noteHashes.push(...nestedTrace.noteHashes);
this.nullifierReadRequests.push(...nestedTrace.nullifierReadRequests);
this.nullifierNonExistentReadRequests.push(...nestedTrace.nullifierNonExistentReadRequests);
this.log.debug(`Merging nullifiers: ${nestedTrace.nullifiers.length}`);
this.log.debug(`Into parent nullifiers: ${this.nullifiers.length}`);
this.nullifiers.push(...nestedTrace.nullifiers);
this.log.debug(`After merge: ${JSON.stringify(this.nullifiers)}`);
this.l1ToL2MsgReadRequests.push(...nestedTrace.l1ToL2MsgReadRequests);
this.l2ToL1Messages.push(...nestedTrace.l2ToL1Messages);
this.unencryptedLogs.push(...nestedTrace.unencryptedLogs);
this.unencryptedLogsHashes.push(...nestedTrace.unencryptedLogsHashes);
}

/**
* Discard accumulated side effects, but keep hints.
*/
public mergeRevertedForkedTrace(nestedTrace: this) {
// TODO(dbanks12): accept & merge nested trace's hints!
this.sideEffectCounter = nestedTrace.sideEffectCounter;

this.enqueuedCalls.push(...nestedTrace.enqueuedCalls);
if (!reverted) {
this.publicDataReads.push(...nestedTrace.publicDataReads);
this.publicDataWrites.push(...nestedTrace.publicDataWrites);
this.noteHashReadRequests.push(...nestedTrace.noteHashReadRequests);
this.noteHashes.push(...nestedTrace.noteHashes);
this.nullifierReadRequests.push(...nestedTrace.nullifierReadRequests);
this.nullifierNonExistentReadRequests.push(...nestedTrace.nullifierNonExistentReadRequests);
this.nullifiers.push(...nestedTrace.nullifiers);
this.l1ToL2MsgReadRequests.push(...nestedTrace.l1ToL2MsgReadRequests);
this.l2ToL1Messages.push(...nestedTrace.l2ToL1Messages);
this.unencryptedLogs.push(...nestedTrace.unencryptedLogs);
this.unencryptedLogsHashes.push(...nestedTrace.unencryptedLogsHashes);
}
}

public getSideEffects(): SideEffects {
Expand Down Expand Up @@ -617,7 +605,6 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI
/** The call's results */
avmCallResults: AvmContractCallResult,
): VMCircuitPublicInputs {
this.log.debug(`Creating public inputs with call result: ${avmCallResults.reverted}`);
return new VMCircuitPublicInputs(
/*constants=*/ constants,
/*callRequest=*/ callRequest,
Expand Down
112 changes: 69 additions & 43 deletions yarn-project/simulator/src/public/public_tx_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
TxExecutionPhase,
} from '@aztec/circuit-types';
import {
type AvmCircuitPublicInputs,
CombinedConstantData,
Fr,
Gas,
Expand All @@ -29,40 +30,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 log: DebugLogger;
Expand Down Expand Up @@ -93,6 +61,7 @@ export class PublicTxContext {
private readonly setupExecutionRequests: PublicExecutionRequest[],
private readonly appLogicExecutionRequests: PublicExecutionRequest[],
private readonly teardownExecutionRequests: PublicExecutionRequest[],
private firstPublicKernelOutput: PublicKernelCircuitPublicInputs,
public latestPublicKernelOutput: PublicKernelCircuitPublicInputs,
public trace: PublicEnqueuedCallSideEffectTrace,
) {
Expand All @@ -107,19 +76,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 Down Expand Up @@ -153,7 +122,8 @@ export class PublicTxContext {
getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP),
getExecutionRequestsByPhase(tx, TxExecutionPhase.APP_LOGIC),
getExecutionRequestsByPhase(tx, TxExecutionPhase.TEARDOWN),
latestPublicKernelOutput,
firstPublicKernelOutput,
firstPublicKernelOutput,
enqueuedCallTrace,
);
}
Expand Down Expand Up @@ -251,7 +221,7 @@ export class PublicTxContext {
/**
* Compute the gas used using the actual gas used during teardown instead
* of the teardown gas limit.
* Note that this.startGasUsed comes from private and private includes
* Note that this.gasUsed comes from private and private includes
* teardown gas limit in its output gasUsed.
*/
getActualGasUsed(): Gas {
Expand All @@ -265,15 +235,15 @@ export class PublicTxContext {
return this.gasUsed;
}

getTransactionFeeAtCurrentPhase(): Fr {
getTransactionFee(): Fr {
if (this.currentPhase === TxExecutionPhase.TEARDOWN) {
return this.getTransactionFeeUnsafe();
} else {
return Fr.zero();
}
}

getTransactionFee(): Fr {
getFinalTransactionFee(): Fr {
assert(this.currentPhase === TxExecutionPhase.TEARDOWN, 'Transaction fee is only known during/after teardown');
return this.getTransactionFeeUnsafe();
}
Expand All @@ -287,4 +257,60 @@ export class PublicTxContext {
});
return txFee;
}

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.trace,
this.globalVariables,
this.startStateReference,
endStateReference,
this.gasUsed,
this.getFinalTransactionFee(),
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!;
}
}

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;
}
}

13 changes: 6 additions & 7 deletions yarn-project/simulator/src/public/public_tx_simulator.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,23 @@ export class PublicTxSimulator {
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.getFinalTransactionFee(),
);

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 Expand Up @@ -212,7 +211,7 @@ export class PublicTxSimulator {
executionRequest,
context.constants,
/*availableGas=*/ context.getGasLeftForCurrentPhase(),
/*transactionFee=*/ context.getTransactionFeeAtCurrentPhase(),
/*transactionFee=*/ context.getTransactionFee(),
enqueuedCallStateManager,
);

Expand Down
6 changes: 1 addition & 5 deletions yarn-project/simulator/src/public/side_effect_trace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -440,11 +440,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface {
throw new Error('Not implemented');
}

public mergeSuccessfulForkedTrace(_nestedTrace: this) {
throw new Error('Not implemented');
}

public mergeRevertedForkedTrace(_nestedTrace: this) {
public mergeForkedTrace(_nestedTrace: this, _reverted: boolean = false) {
throw new Error('Not implemented');
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { type EnqueuedPublicCallExecutionResultWithSideEffects, type PublicFunct

export interface PublicSideEffectTraceInterface {
fork(incrementSideEffectCounter?: boolean): PublicSideEffectTraceInterface;
mergeForkedTrace(nestedTrace: PublicSideEffectTraceInterface, reverted?: boolean): void;
getCounter(): number;
// all "trace*" functions can throw SideEffectLimitReachedError
tracePublicStorageRead(
Expand Down Expand Up @@ -101,8 +102,6 @@ export interface PublicSideEffectTraceInterface {
/** Did the call revert? */
reverted: boolean,
): void;
mergeSuccessfulForkedTrace(nestedTrace: PublicSideEffectTraceInterface): void;
mergeRevertedForkedTrace(nestedTrace: PublicSideEffectTraceInterface): void;
toPublicEnqueuedCallExecutionResult(
/** How much gas was left after this public execution. */
endGasLeft: Gas,
Expand Down
Loading

0 comments on commit 269acb7

Please sign in to comment.