Skip to content

Commit

Permalink
feat: avm side effect trace accounts for array lengths from previous …
Browse files Browse the repository at this point in the history
…kernel
  • Loading branch information
dbanks12 committed Oct 3, 2024
1 parent c970ced commit bf573de
Show file tree
Hide file tree
Showing 10 changed files with 1,286 additions and 17 deletions.
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/structs/l2_to_l1_message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@ export class L2ToL1Message {
isEmpty(): boolean {
return this.recipient.isZero() && this.content.isZero() && !this.counter;
}

scope(contractAddress: AztecAddress) {
return new ScopedL2ToL1Message(this, contractAddress);
}
}

export class ScopedL2ToL1Message {
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/structs/log_hash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export class LogHash implements Ordered {
return `value=${this.value} counter=${this.counter} length=${this.length}`;
}

scope(contractAddress: AztecAddress) {
return new ScopedLogHash(this, contractAddress);
}

[inspect.custom](): string {
return `LogHash { ${this.toString()} }`;
}
Expand Down
13 changes: 10 additions & 3 deletions yarn-project/prover-client/src/mocks/test_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ import {
type Tx,
type TxValidator,
} from '@aztec/circuit-types';
import { type Gas, type GlobalVariables, Header, type Nullifier, type TxContext } from '@aztec/circuits.js';
import {
type CombinedConstantData,
type Gas,
type GlobalVariables,
Header,
type Nullifier,
type TxContext,
} from '@aztec/circuits.js';
import { type Fr } from '@aztec/foundation/fields';
import { type DebugLogger } from '@aztec/foundation/log';
import { openTmpStore } from '@aztec/kv-store/utils';
Expand Down Expand Up @@ -155,7 +162,7 @@ export class TestContext {
) {
const defaultExecutorImplementation = (
execution: PublicExecutionRequest,
_globalVariables: GlobalVariables,
_constants: CombinedConstantData,
availableGas: Gas,
_txContext: TxContext,
_pendingNullifiers: Nullifier[],
Expand Down Expand Up @@ -195,7 +202,7 @@ export class TestContext {
txValidator?: TxValidator<ProcessedTx>,
executorMock?: (
execution: PublicExecutionRequest,
globalVariables: GlobalVariables,
constants: CombinedConstantData,
availableGas: Gas,
txContext: TxContext,
pendingNullifiers: Nullifier[],
Expand Down
169 changes: 169 additions & 0 deletions yarn-project/simulator/src/public/dual_side_effect_trace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
import { type CombinedConstantData, type Gas, type VMCircuitPublicInputs } from '@aztec/circuits.js';
import { type Fr } from '@aztec/foundation/fields';
import { type ContractInstanceWithAddress } from '@aztec/types/contracts';

import { assert } from 'console';

import { type AvmContractCallResult } from '../avm/avm_contract_call_result.js';
import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
import { type PublicEnqueuedCallSideEffectTrace } from './enqueued_call_side_effect_trace.js';
import { type PublicExecutionResult } from './execution.js';
import { type PublicSideEffectTrace } from './side_effect_trace.js';
import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js';

export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress;

export class DualSideEffectTrace implements PublicSideEffectTraceInterface {
constructor(
public readonly innerCallTrace: PublicSideEffectTrace,
public readonly enqueuedCallTrace: PublicEnqueuedCallSideEffectTrace,
) {}

public fork() {
return new DualSideEffectTrace(this.innerCallTrace.fork(), this.enqueuedCallTrace.fork());
}

public getCounter() {
assert(this.innerCallTrace.getCounter() == this.enqueuedCallTrace.getCounter());
return this.innerCallTrace.getCounter();
}

public tracePublicStorageRead(storageAddress: Fr, slot: Fr, value: Fr, exists: boolean, cached: boolean) {
this.innerCallTrace.tracePublicStorageRead(storageAddress, slot, value, exists, cached);
this.enqueuedCallTrace.tracePublicStorageRead(storageAddress, slot, value, exists, cached);
}

public tracePublicStorageWrite(storageAddress: Fr, slot: Fr, value: Fr) {
this.innerCallTrace.tracePublicStorageWrite(storageAddress, slot, value);
this.enqueuedCallTrace.tracePublicStorageWrite(storageAddress, slot, value);
}

// TODO(8287): _exists can be removed once we have the vm properly handling the equality check
public traceNoteHashCheck(_storageAddress: Fr, noteHash: Fr, leafIndex: Fr, exists: boolean) {
this.innerCallTrace.traceNoteHashCheck(_storageAddress, noteHash, leafIndex, exists);
this.enqueuedCallTrace.traceNoteHashCheck(_storageAddress, noteHash, leafIndex, exists);
}

public traceNewNoteHash(_storageAddress: Fr, noteHash: Fr) {
this.innerCallTrace.traceNewNoteHash(_storageAddress, noteHash);
this.enqueuedCallTrace.traceNewNoteHash(_storageAddress, noteHash);
}

public traceNullifierCheck(storageAddress: Fr, nullifier: Fr, leafIndex: Fr, exists: boolean, isPending: boolean) {
this.innerCallTrace.traceNullifierCheck(storageAddress, nullifier, leafIndex, exists, isPending);
this.enqueuedCallTrace.traceNullifierCheck(storageAddress, nullifier, leafIndex, exists, isPending);
}

public traceNewNullifier(storageAddress: Fr, nullifier: Fr) {
this.innerCallTrace.traceNewNullifier(storageAddress, nullifier);
this.enqueuedCallTrace.traceNewNullifier(storageAddress, nullifier);
}

public traceL1ToL2MessageCheck(contractAddress: Fr, msgHash: Fr, msgLeafIndex: Fr, exists: boolean) {
this.innerCallTrace.traceL1ToL2MessageCheck(contractAddress, msgHash, msgLeafIndex, exists);
this.enqueuedCallTrace.traceL1ToL2MessageCheck(contractAddress, msgHash, msgLeafIndex, exists);
}

public traceNewL2ToL1Message(contractAddress: Fr, recipient: Fr, content: Fr) {
this.innerCallTrace.traceNewL2ToL1Message(contractAddress, recipient, content);
this.enqueuedCallTrace.traceNewL2ToL1Message(contractAddress, recipient, content);
}

public traceUnencryptedLog(contractAddress: Fr, log: Fr[]) {
this.innerCallTrace.traceUnencryptedLog(contractAddress, log);
this.enqueuedCallTrace.traceUnencryptedLog(contractAddress, log);
}

public traceGetContractInstance(instance: TracedContractInstance) {
this.innerCallTrace.traceGetContractInstance(instance);
this.enqueuedCallTrace.traceGetContractInstance(instance);
}

/**
* Trace a nested call.
* Accept some results from a finished nested call's trace into this one.
*/
public traceNestedCall(
/** The trace of the nested call. */
nestedCallTrace: this,
/** The execution environment of the nested call. */
nestedEnvironment: AvmExecutionEnvironment,
/** How much gas was available for this public execution. */
startGasLeft: Gas,
/** How much gas was left after this public execution. */
endGasLeft: Gas,
/** Bytecode used for this execution. */
bytecode: Buffer,
/** The call's results */
avmCallResults: AvmContractCallResult,
/** Function name for logging */
functionName: string = 'unknown',
) {
this.innerCallTrace.traceNestedCall(
nestedCallTrace.innerCallTrace,
nestedEnvironment,
startGasLeft,
endGasLeft,
bytecode,
avmCallResults,
functionName,
);
this.enqueuedCallTrace.traceNestedCall(
nestedCallTrace.enqueuedCallTrace,
nestedEnvironment,
startGasLeft,
endGasLeft,
bytecode,
avmCallResults,
functionName,
);
}

/**
* Convert this trace to a PublicExecutionResult for use externally to the simulator.
*/
public toPublicExecutionResult(
/** The execution environment of the nested call. */
avmEnvironment: AvmExecutionEnvironment,
/** How much gas was available for this public execution. */
startGasLeft: Gas,
/** How much gas was left after this public execution. */
endGasLeft: Gas,
/** Bytecode used for this execution. */
bytecode: Buffer,
/** The call's results */
avmCallResults: AvmContractCallResult,
/** Function name for logging */
functionName: string = 'unknown',
): PublicExecutionResult {
return this.innerCallTrace.toPublicExecutionResult(
avmEnvironment,
startGasLeft,
endGasLeft,
bytecode,
avmCallResults,
functionName,
);
}

public toVMCircuitPublicInputs(
/** Constants */
constants: CombinedConstantData,
/** The execution environment of the nested call. */
avmEnvironment: AvmExecutionEnvironment,
/** How much gas was available for this public execution. */
startGasLeft: Gas,
/** How much gas was left after this public execution. */
endGasLeft: Gas,
/** The call's results */
avmCallResults: AvmContractCallResult,
): VMCircuitPublicInputs {
return this.enqueuedCallTrace.toVMCircuitPublicInputs(
constants,
avmEnvironment,
startGasLeft,
endGasLeft,
avmCallResults,
);
}
}
Loading

0 comments on commit bf573de

Please sign in to comment.