Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions yarn-project/circuit-types/src/logs/unencrypted_l2_log.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ export class UnencryptedL2Log {
constructor(
/**
* Address of the contract that emitted the event
* NOTE: It would make sense to have the address only in `FunctionL2Logs` because contract address is shared for all
* function logs. I didn't do this because it would require us to have 2 FunctionL2Logs classes (one with contract
* address and one without) for unencrypted and encrypted because encrypted logs can't expose the address in an
* unencrypted form. For this reason separating the classes seems like a premature optimization.
* TODO: Optimize this once it makes sense.
*/
public readonly contractAddress: AztecAddress,
/** The data contents of the log. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ import { Gas } from '../gas.js';
import { ScopedL2ToL1Message } from '../l2_to_l1_message.js';
import { LogHash, ScopedLogHash } from '../log_hash.js';
import { ScopedNoteHash } from '../note_hash.js';
import { Nullifier } from '../nullifier.js';
import { ScopedNullifier } from '../nullifier.js';
import { PublicCallRequest } from '../public_call_request.js';
import { PublicDataUpdateRequest } from '../public_data_update_request.js';
import { ContractStorageUpdateRequest } from '../contract_storage_update_request.js';

export class PublicAccumulatedData {
constructor(
Expand All @@ -34,7 +34,7 @@ export class PublicAccumulatedData {
/**
* The new nullifiers made in this transaction.
*/
public readonly nullifiers: Tuple<Nullifier, typeof MAX_NULLIFIERS_PER_TX>,
public readonly nullifiers: Tuple<ScopedNullifier, typeof MAX_NULLIFIERS_PER_TX>,
/**
* All the new L2 to L1 messages created in this transaction.
*/
Expand All @@ -58,7 +58,7 @@ export class PublicAccumulatedData {
* All the public data update requests made in this transaction.
*/
public readonly publicDataUpdateRequests: Tuple<
PublicDataUpdateRequest,
ContractStorageUpdateRequest,
typeof MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX
>,
/**
Expand Down Expand Up @@ -164,12 +164,12 @@ export class PublicAccumulatedData {
const reader = BufferReader.asReader(buffer);
return new this(
reader.readArray(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash),
reader.readArray(MAX_NULLIFIERS_PER_TX, Nullifier),
reader.readArray(MAX_NULLIFIERS_PER_TX, ScopedNullifier),
reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message),
reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash),
reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash),
reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash),
reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest),
reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ContractStorageUpdateRequest),
reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest),
reader.readObject(Gas),
);
Expand All @@ -179,12 +179,12 @@ export class PublicAccumulatedData {
const reader = FieldReader.asReader(fields);
return new this(
reader.readArray(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash),
reader.readArray(MAX_NULLIFIERS_PER_TX, Nullifier),
reader.readArray(MAX_NULLIFIERS_PER_TX, ScopedNullifier),
reader.readArray(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message),
reader.readArray(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash),
reader.readArray(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash),
reader.readArray(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash),
reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest),
reader.readArray(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ContractStorageUpdateRequest),
reader.readArray(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest),
reader.readObject(Gas),
);
Expand All @@ -202,12 +202,12 @@ export class PublicAccumulatedData {
static empty() {
return new this(
makeTuple(MAX_NOTE_HASHES_PER_TX, ScopedNoteHash.empty),
makeTuple(MAX_NULLIFIERS_PER_TX, Nullifier.empty),
makeTuple(MAX_NULLIFIERS_PER_TX, ScopedNullifier.empty),
makeTuple(MAX_L2_TO_L1_MSGS_PER_TX, ScopedL2ToL1Message.empty),
makeTuple(MAX_NOTE_ENCRYPTED_LOGS_PER_TX, LogHash.empty),
makeTuple(MAX_ENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty),
makeTuple(MAX_UNENCRYPTED_LOGS_PER_TX, ScopedLogHash.empty),
makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, PublicDataUpdateRequest.empty),
makeTuple(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, ContractStorageUpdateRequest.empty),
makeTuple(MAX_PUBLIC_CALL_STACK_LENGTH_PER_TX, PublicCallRequest.empty),
Gas.empty(),
);
Expand Down
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
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import {
NUM_PUBLIC_VALIDATION_REQUEST_ARRAYS,
} from '../constants.gen.js';
import { countAccumulatedItems } from '../utils/index.js';
import { PublicDataRead } from './public_data_read.js';
import { ScopedReadRequest } from './read_request.js';
import { RollupValidationRequests } from './rollup_validation_requests.js';
import { TreeLeafReadRequest } from './tree_leaf_read_request.js';
import { ContractStorageRead } from './contract_storage_read.js';

/**
* Validation requests accumulated during the execution of the transaction.
Expand Down Expand Up @@ -45,7 +45,7 @@ export class PublicValidationRequests {
/**
* All the public data reads made in this transaction.
*/
public publicDataReads: Tuple<PublicDataRead, typeof MAX_PUBLIC_DATA_READS_PER_TX>,
public publicDataReads: Tuple<ContractStorageRead, typeof MAX_PUBLIC_DATA_READS_PER_TX>,
) {}

getSize() {
Expand Down Expand Up @@ -82,7 +82,7 @@ export class PublicValidationRequests {
reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest),
reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest),
reader.readArray(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, TreeLeafReadRequest),
reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead),
reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, ContractStorageRead),
);
}

Expand All @@ -99,7 +99,7 @@ export class PublicValidationRequests {
reader.readArray(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest),
reader.readArray(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest),
reader.readArray(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, TreeLeafReadRequest),
reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead),
reader.readArray(MAX_PUBLIC_DATA_READS_PER_TX, ContractStorageRead),
);
}

Expand All @@ -119,7 +119,7 @@ export class PublicValidationRequests {
makeTuple(MAX_NULLIFIER_READ_REQUESTS_PER_TX, ScopedReadRequest.empty),
makeTuple(MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, ScopedReadRequest.empty),
makeTuple(MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, TreeLeafReadRequest.empty),
makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, PublicDataRead.empty),
makeTuple(MAX_PUBLIC_DATA_READS_PER_TX, ContractStorageRead.empty),
);
}

Expand Down
179 changes: 179 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,179 @@
import {
Gas,
VMCircuitPublicInputs,
CombinedConstantData,
} from '@aztec/circuits.js';
import { Fr } from '@aztec/foundation/fields';
import { type ContractInstanceWithAddress } from '@aztec/types/contracts';

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

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,
/** Bytecode used for this execution. */
bytecode: Buffer,
/** The call's results */
avmCallResults: AvmContractCallResult,
/** Function name for logging */
functionName: string = 'unknown',
): VMCircuitPublicInputs {
return this.enqueuedCallTrace.toVMCircuitPublicInputs(
constants,
avmEnvironment,
startGasLeft,
endGasLeft,
bytecode,
avmCallResults,
functionName,
);
}
}

Loading