diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 79d3e5511f9..0ff6e1363db 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -608,7 +608,6 @@ void avm_prove(const std::filesystem::path& public_inputs_path, vinfo("hints.note_hash_read_hints size: ", avm_hints.note_hash_read_hints.size()); vinfo("hints.note_hash_write_hints size: ", avm_hints.note_hash_write_hints.size()); vinfo("hints.l1_to_l2_message_read_hints size: ", avm_hints.l1_to_l2_message_read_hints.size()); - vinfo("hints.externalcall_hints size: ", avm_hints.externalcall_hints.size()); vinfo("hints.contract_instance_hints size: ", avm_hints.contract_instance_hints.size()); vinfo("hints.contract_bytecode_hints size: ", avm_hints.all_contract_bytecode.size()); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp index f14b252f829..ffb1ed18406 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/tests/execution.test.cpp @@ -1958,10 +1958,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageLoadOpcodeSimple) std::vector calldata = {}; std::vector returndata = {}; - // Generate Hint for Sload operation - // side effect counter 0 = value 42 - auto execution_hints = ExecutionHints().with_storage_value_hints({ { 0, 42 } }); - + ExecutionHints execution_hints; auto trace = gen_trace(bytecode, calldata, public_inputs, returndata, execution_hints); // CHECK SLOAD @@ -2089,10 +2086,7 @@ TEST_F(AvmExecutionTests, kernelOutputStorageOpcodes) std::vector calldata = {}; std::vector returndata = {}; - // Generate Hint for Sload operation - // side effect counter 0 = value 42 - auto execution_hints = ExecutionHints().with_storage_value_hints({ { 0, 42 } }); - + ExecutionHints execution_hints; auto trace = gen_trace(bytecode, calldata, public_inputs, returndata, execution_hints); // CHECK SLOAD @@ -2178,9 +2172,7 @@ TEST_F(AvmExecutionTests, kernelOutputHashExistsOpcodes) std::vector returndata = {}; // Generate Hint for hash exists operation - auto execution_hints = ExecutionHints() - .with_storage_value_hints({ { 0, 1 }, { 1, 1 }, { 2, 1 } }) - .with_note_hash_exists_hints({ { 0, 1 }, { 1, 1 }, { 2, 1 } }); + ExecutionHints execution_hints; auto trace = gen_trace(bytecode, calldata, public_inputs, returndata, execution_hints); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution_hints.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution_hints.hpp index 463e1060643..be57dc4da6d 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution_hints.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution_hints.hpp @@ -233,11 +233,6 @@ inline void read(uint8_t const*& it, AvmEnqueuedCallHint& hint) struct ExecutionHints { std::vector enqueued_call_hints; - std::vector> storage_value_hints; - std::vector> note_hash_exists_hints; - std::vector> nullifier_exists_hints; - std::vector> l1_to_l2_message_exists_hints; - std::vector externalcall_hints; std::map contract_instance_hints; // We could make this address-indexed std::vector all_contract_bytecode; @@ -251,32 +246,6 @@ struct ExecutionHints { ExecutionHints() = default; - // Builder. - ExecutionHints& with_storage_value_hints(std::vector> storage_value_hints) - { - this->storage_value_hints = std::move(storage_value_hints); - return *this; - } - ExecutionHints& with_note_hash_exists_hints(std::vector> note_hash_exists_hints) - { - this->note_hash_exists_hints = std::move(note_hash_exists_hints); - return *this; - } - ExecutionHints& with_nullifier_exists_hints(std::vector> nullifier_exists_hints) - { - this->nullifier_exists_hints = std::move(nullifier_exists_hints); - return *this; - } - ExecutionHints& with_l1_to_l2_message_exists_hints(std::vector> l1_to_l2_message_exists_hints) - { - this->l1_to_l2_message_exists_hints = std::move(l1_to_l2_message_exists_hints); - return *this; - } - ExecutionHints& with_externalcall_hints(std::vector externalcall_hints) - { - this->externalcall_hints = std::move(externalcall_hints); - return *this; - } ExecutionHints& with_contract_instance_hints(std::map contract_instance_hints) { this->contract_instance_hints = std::move(contract_instance_hints); @@ -296,45 +265,13 @@ struct ExecutionHints { } } - // TODO: Cache. - // Side effect counter -> value - std::unordered_map get_side_effect_hints() const - { - std::unordered_map hints_map; - push_vec_into_map(hints_map, storage_value_hints); - push_vec_into_map(hints_map, nullifier_exists_hints); - return hints_map; - } - - // Leaf index -> exists - std::unordered_map get_leaf_index_hints() const - { - std::unordered_map hints_map; - push_vec_into_map(hints_map, note_hash_exists_hints); - push_vec_into_map(hints_map, l1_to_l2_message_exists_hints); - return hints_map; - } - static ExecutionHints from(const std::vector& data) { - std::vector> storage_value_hints; - std::vector> note_hash_exists_hints; - std::vector> nullifier_exists_hints; - std::vector> l1_to_l2_message_exists_hints; - using serialize::read; const auto* it = data.data(); std::vector enqueued_call_hints; read(it, enqueued_call_hints); - read(it, storage_value_hints); - read(it, note_hash_exists_hints); - read(it, nullifier_exists_hints); - read(it, l1_to_l2_message_exists_hints); - - std::vector externalcall_hints; - read(it, externalcall_hints); - std::vector contract_instance_hints_vec; read(it, contract_instance_hints_vec); std::map contract_instance_hints; @@ -371,32 +308,17 @@ struct ExecutionHints { " bytes out of " + std::to_string(data.size()) + " bytes"); } - return { std::move(enqueued_call_hints), - std::move(storage_value_hints), - std::move(note_hash_exists_hints), - std::move(nullifier_exists_hints), - std::move(l1_to_l2_message_exists_hints), - std::move(externalcall_hints), - std::move(contract_instance_hints), - std::move(all_contract_bytecode), - std::move(storage_read_hints), - std::move(storage_write_hints), - std::move(nullifier_read_hints), - std::move(nullifier_write_hints), - std::move(note_hash_read_hints), - std::move(note_hash_write_hints), - std::move(l1_to_l2_message_read_hints) + return { std::move(enqueued_call_hints), std::move(contract_instance_hints), + std::move(all_contract_bytecode), std::move(storage_read_hints), + std::move(storage_write_hints), std::move(nullifier_read_hints), + std::move(nullifier_write_hints), std::move(note_hash_read_hints), + std::move(note_hash_write_hints), std::move(l1_to_l2_message_read_hints) }; } private: ExecutionHints(std::vector enqueued_call_hints, - std::vector> storage_value_hints, - std::vector> note_hash_exists_hints, - std::vector> nullifier_exists_hints, - std::vector> l1_to_l2_message_exists_hints, - std::vector externalcall_hints, std::map contract_instance_hints, std::vector all_contract_bytecode, std::vector storage_read_hints, @@ -408,11 +330,6 @@ struct ExecutionHints { std::vector l1_to_l2_message_read_hints) : enqueued_call_hints(std::move(enqueued_call_hints)) - , storage_value_hints(std::move(storage_value_hints)) - , note_hash_exists_hints(std::move(note_hash_exists_hints)) - , nullifier_exists_hints(std::move(nullifier_exists_hints)) - , l1_to_l2_message_exists_hints(std::move(l1_to_l2_message_exists_hints)) - , externalcall_hints(std::move(externalcall_hints)) , contract_instance_hints(std::move(contract_instance_hints)) , all_contract_bytecode(std::move(all_contract_bytecode)) , storage_read_hints(std::move(storage_read_hints)) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index c7247f64871..a370f42e5ba 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -2448,155 +2448,6 @@ RowWithError AvmTraceBuilder::create_kernel_output_opcode_with_metadata(uint8_t .error = error }; } -/** - * @brief Create a kernel output opcode with set metadata output object - * - * Used for writing output opcode where one metadata value is written and comes from a hint - * {note_hash_exists, nullifier_exists, etc. } Where a boolean output if it exists must also be written - * - * @param indirect - Perform indirect memory resolution - * @param clk - The trace clk - * @param data_offset - The offset of the main value to output - * @param metadata_offset - The offset of the metadata (slot in the sload example) - * @return Row - */ -Row AvmTraceBuilder::create_kernel_output_opcode_with_set_metadata_output_from_hint( - uint32_t clk, uint32_t data_offset, [[maybe_unused]] uint32_t address_offset, uint32_t metadata_offset) -{ - FF exists = execution_hints.get_side_effect_hints().at(side_effect_counter); - - auto read_a = constrained_read_from_memory( - call_ptr, clk, data_offset, AvmMemoryTag::FF, AvmMemoryTag::U1, IntermRegister::IA); - - auto write_b = constrained_write_to_memory( - call_ptr, clk, metadata_offset, exists, AvmMemoryTag::FF, AvmMemoryTag::U1, IntermRegister::IB); - bool tag_match = read_a.tag_match && write_b.tag_match; - - return Row{ - .main_clk = clk, - .main_ia = read_a.val, - .main_ib = write_b.val, - .main_ind_addr_a = FF(read_a.indirect_address), - .main_ind_addr_b = FF(write_b.indirect_address), - .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = FF(read_a.direct_address), - .main_mem_addr_b = FF(write_b.direct_address), - .main_pc = pc, - .main_r_in_tag = static_cast(AvmMemoryTag::FF), - .main_rwa = 0, - .main_rwb = 1, - .main_sel_mem_op_a = 1, - .main_sel_mem_op_b = 1, - .main_sel_q_kernel_output_lookup = 1, - .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), - .main_sel_resolve_ind_addr_b = FF(static_cast(write_b.is_indirect)), - .main_tag_err = static_cast(!tag_match), - .main_w_in_tag = static_cast(AvmMemoryTag::U1), - }; -} - -// Specifically for handling the L1TOL2MSGEXISTS and NOTEHASHEXISTS opcodes -Row AvmTraceBuilder::create_kernel_output_opcode_for_leaf_index(uint32_t clk, - uint32_t data_offset, - uint32_t leaf_index, - uint32_t metadata_offset) -{ - // If doesnt exist, should not read_a, but instead get from public inputs - FF exists = execution_hints.get_leaf_index_hints().at(leaf_index); - - auto read_a = constrained_read_from_memory( - call_ptr, clk, data_offset, AvmMemoryTag::FF, AvmMemoryTag::U1, IntermRegister::IA); - - auto write_b = constrained_write_to_memory( - call_ptr, clk, metadata_offset, exists, AvmMemoryTag::FF, AvmMemoryTag::U1, IntermRegister::IB); - bool tag_match = read_a.tag_match && write_b.tag_match; - - return Row{ - .main_clk = clk, - .main_ia = read_a.val, - .main_ib = write_b.val, - .main_ind_addr_a = FF(read_a.indirect_address), - .main_ind_addr_b = FF(write_b.indirect_address), - .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = FF(read_a.direct_address), - .main_mem_addr_b = FF(write_b.direct_address), - .main_pc = pc, - .main_r_in_tag = static_cast(AvmMemoryTag::FF), - .main_rwa = 0, - .main_rwb = 1, - .main_sel_mem_op_a = 1, - .main_sel_mem_op_b = 1, - .main_sel_q_kernel_output_lookup = 1, - .main_sel_resolve_ind_addr_a = FF(static_cast(read_a.is_indirect)), - .main_sel_resolve_ind_addr_b = FF(static_cast(write_b.is_indirect)), - .main_tag_err = static_cast(!tag_match), - .main_w_in_tag = static_cast(AvmMemoryTag::U1), - }; -} - -/** - * @brief Create a kernel output opcode with set metadata output object - * - * Used for writing output opcode where one value is written and comes from a hint - * {sload} - * - * @param indirect - Perform indirect memory resolution - * @param clk - The trace clk - * @param data_offset - The offset of the main value to output - * @param metadata_offset - The offset of the metadata (slot in the sload example) - * @return Row - */ -RowWithError AvmTraceBuilder::create_kernel_output_opcode_with_set_value_from_hint(uint8_t indirect, - uint32_t clk, - uint32_t data_offset, - uint32_t metadata_offset) -{ - FF value = execution_hints.get_side_effect_hints().at(side_effect_counter); - // TODO: throw error if incorrect - - // We keep the first encountered error - AvmError error = AvmError::NO_ERROR; - auto [resolved_addrs, res_error] = - Addressing<2>::fromWire(indirect, call_ptr).resolve({ data_offset, metadata_offset }, mem_trace_builder); - auto [resolved_data, resolved_metadata] = resolved_addrs; - error = res_error; - - auto write_a = constrained_write_to_memory( - call_ptr, clk, resolved_data, value, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IA); - auto read_b = constrained_read_from_memory( - call_ptr, clk, resolved_metadata, AvmMemoryTag::FF, AvmMemoryTag::FF, IntermRegister::IB); - bool tag_match = write_a.tag_match && read_b.tag_match; - - if (is_ok(error) && !tag_match) { - error = AvmError::CHECK_TAG_ERROR; - } - - return RowWithError{ .row = - Row{ - .main_clk = clk, - .main_ia = write_a.val, - .main_ib = read_b.val, - .main_ind_addr_a = FF(write_a.indirect_address), - .main_ind_addr_b = FF(read_b.indirect_address), - .main_internal_return_ptr = internal_return_ptr, - .main_mem_addr_a = FF(write_a.direct_address), - .main_mem_addr_b = FF(read_b.direct_address), - .main_op_err = FF(static_cast(!is_ok(error))), - .main_pc = pc, // No PC increment here since we do it in the specific ops - .main_r_in_tag = static_cast(AvmMemoryTag::FF), - .main_rwa = 1, - .main_rwb = 0, - .main_sel_mem_op_a = 1, - .main_sel_mem_op_b = 1, - .main_sel_q_kernel_output_lookup = 1, - .main_sel_resolve_ind_addr_a = FF(static_cast(write_a.is_indirect)), - .main_sel_resolve_ind_addr_b = FF(static_cast(read_b.is_indirect)), - .main_tag_err = static_cast(!tag_match), - .main_w_in_tag = static_cast(AvmMemoryTag::FF), - }, - .error = error }; -} - /************************************************************************************************** * WORLD STATE **************************************************************************************************/ diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index 68666f38419..660b26e7484 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -326,21 +326,6 @@ class AvmTraceBuilder { uint32_t metadata_offset, AvmMemoryTag metadata_r_tag); - Row create_kernel_output_opcode_with_set_metadata_output_from_hint(uint32_t clk, - uint32_t data_offset, - uint32_t address_offset, - uint32_t metadata_offset); - - Row create_kernel_output_opcode_for_leaf_index(uint32_t clk, - uint32_t data_offset, - uint32_t leaf_index, - uint32_t metadata_offset); - - RowWithError create_kernel_output_opcode_with_set_value_from_hint(uint8_t indirect, - uint32_t clk, - uint32_t data_offset, - uint32_t metadata_offset); - AvmError constrain_external_call(OpCode opcode, uint16_t indirect, uint32_t gas_offset, diff --git a/yarn-project/circuits.js/src/structs/avm/avm.ts b/yarn-project/circuits.js/src/structs/avm/avm.ts index 6e7728b9bed..4447516818d 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.ts @@ -8,7 +8,6 @@ import { type FieldsOf } from '@aztec/foundation/types'; import { type ContractClassIdPreimage } from '../../contract/contract_class_id.js'; import { PublicKeys } from '../../types/public_keys.js'; -import { Gas } from '../gas.js'; import { PublicCircuitPublicInputs } from '../public_circuit_public_inputs.js'; import { Vector } from '../shared.js'; import { NullifierLeafPreimage } from '../trees/nullifier_leaf.js'; @@ -84,172 +83,6 @@ export class AvmEnqueuedCallHint { } } -// TODO: Consider just using Tuple. -export class AvmKeyValueHint { - constructor(public readonly key: Fr, public readonly value: Fr) {} - - /** - * Serializes the inputs to a buffer. - * @returns - The inputs serialized to a buffer. - */ - toBuffer() { - return serializeToBuffer(...AvmKeyValueHint.getFields(this)); - } - - /** - * Serializes the inputs to a hex string. - * @returns The instance serialized to a hex string. - */ - toString() { - return bufferToHex(this.toBuffer()); - } - - /** - * Is the struct empty? - * @returns whether all members are empty. - */ - isEmpty(): boolean { - return this.key.isEmpty() && this.value.isEmpty(); - } - - /** - * Creates a new instance from fields. - * @param fields - Fields to create the instance from. - * @returns A new AvmHint instance. - */ - static from(fields: FieldsOf): AvmKeyValueHint { - return new AvmKeyValueHint(...AvmKeyValueHint.getFields(fields)); - } - - /** - * Extracts fields from an instance. - * @param fields - Fields to create the instance from. - * @returns An array of fields. - */ - static getFields(fields: FieldsOf) { - return [fields.key, fields.value] as const; - } - - /** - * Deserializes from a buffer or reader. - * @param buffer - Buffer or reader to read from. - * @returns The deserialized instance. - */ - static fromBuffer(buff: Buffer | BufferReader) { - const reader = BufferReader.asReader(buff); - return new AvmKeyValueHint(Fr.fromBuffer(reader), Fr.fromBuffer(reader)); - } - - /** - * Deserializes from a hex string. - * @param str - Hex string to read from. - * @returns The deserialized instance. - */ - static fromString(str: string): AvmKeyValueHint { - return AvmKeyValueHint.fromBuffer(hexToBuffer(str)); - } -} - -export class AvmExternalCallHint { - public readonly returnData: Vector; - - /** - * Creates a new instance. - * @param success whether the external call was successful (= did NOT revert). - * @param returnData the data returned by the external call. - * @param gasUsed gas used by the external call (not including the cost of the CALL opcode itself). - * @param endSideEffectCounter value of side effect counter at the end of the external call. - */ - constructor( - public readonly success: Fr, - returnData: Fr[], - public readonly gasUsed: Gas, - public readonly endSideEffectCounter: Fr, - public readonly contractAddress: AztecAddress, - ) { - this.returnData = new Vector(returnData); - } - - /** - * Serializes the inputs to a buffer. - * @returns - The inputs serialized to a buffer. - */ - toBuffer() { - return serializeToBuffer(...AvmExternalCallHint.getFields(this)); - } - - /** - * Serializes the inputs to a hex string. - * @returns The instance serialized to a hex string. - */ - toString() { - return bufferToHex(this.toBuffer()); - } - - /** - * Is the struct empty? - * @returns whether all members are empty. - */ - isEmpty(): boolean { - return ( - this.success.isZero() && - this.returnData.items.length == 0 && - this.gasUsed.isEmpty() && - this.endSideEffectCounter.isZero() && - this.contractAddress.isZero() - ); - } - - /** - * Creates a new instance from fields. - * @param fields - Fields to create the instance from. - * @returns A new AvmHint instance. - */ - static from(fields: FieldsOf): AvmExternalCallHint { - return new AvmExternalCallHint( - fields.success, - fields.returnData.items, - fields.gasUsed, - fields.endSideEffectCounter, - fields.contractAddress, - ); - } - - /** - * Extracts fields from an instance. - * @param fields - Fields to create the instance from. - * @returns An array of fields. - */ - static getFields(fields: FieldsOf) { - return [fields.success, fields.returnData, fields.gasUsed, fields.endSideEffectCounter, fields.contractAddress]; - } - - /** - * Deserializes from a buffer or reader. - * @param buffer - Buffer or reader to read from. - * @returns The deserialized instance. - */ - static fromBuffer(buff: Buffer | BufferReader): AvmExternalCallHint { - const reader = BufferReader.asReader(buff); - return new AvmExternalCallHint( - Fr.fromBuffer(reader), - reader.readVector(Fr), - reader.readObject(Gas), - Fr.fromBuffer(reader), - AztecAddress.fromBuffer(reader), - ); - } - - /** - * Deserializes from a hex string. - * @param str - Hex string to read from. - * @returns The deserialized instance. - */ - static fromString(str: string): AvmExternalCallHint { - return AvmExternalCallHint.fromBuffer(hexToBuffer(str)); - } -} - export class AvmContractInstanceHint { constructor( public readonly address: AztecAddress, @@ -849,13 +682,6 @@ export class AvmPublicDataWriteTreeHint { export class AvmExecutionHints { public readonly enqueuedCalls: Vector; - public readonly storageValues: Vector; - public readonly noteHashExists: Vector; - public readonly nullifierExists: Vector; - public readonly l1ToL2MessageExists: Vector; - - public readonly externalCalls: Vector; - public readonly contractInstances: Vector; public readonly contractBytecodeHints: Vector; @@ -869,11 +695,6 @@ export class AvmExecutionHints { constructor( enqueuedCalls: AvmEnqueuedCallHint[], - storageValues: AvmKeyValueHint[], - noteHashExists: AvmKeyValueHint[], - nullifierExists: AvmKeyValueHint[], - l1ToL2MessageExists: AvmKeyValueHint[], - externalCalls: AvmExternalCallHint[], contractInstances: AvmContractInstanceHint[], contractBytecodeHints: AvmContractBytecodeHints[], publicDataReads: AvmPublicDataReadTreeHint[], @@ -885,11 +706,6 @@ export class AvmExecutionHints { l1ToL2MessageReads: AvmAppendTreeHint[], ) { this.enqueuedCalls = new Vector(enqueuedCalls); - this.storageValues = new Vector(storageValues); - this.noteHashExists = new Vector(noteHashExists); - this.nullifierExists = new Vector(nullifierExists); - this.l1ToL2MessageExists = new Vector(l1ToL2MessageExists); - this.externalCalls = new Vector(externalCalls); this.contractInstances = new Vector(contractInstances); this.contractBytecodeHints = new Vector(contractBytecodeHints); this.publicDataReads = new Vector(publicDataReads); @@ -906,7 +722,7 @@ export class AvmExecutionHints { * @returns an empty instance. */ static empty() { - return new AvmExecutionHints([], [], [], [], [], [], [], [], [], [], [], [], [], [], []); + return new AvmExecutionHints([], [], [], [], [], [], [], [], [], []); } /** @@ -932,11 +748,6 @@ export class AvmExecutionHints { isEmpty(): boolean { return ( this.enqueuedCalls.items.length == 0 && - this.storageValues.items.length == 0 && - this.noteHashExists.items.length == 0 && - this.nullifierExists.items.length == 0 && - this.l1ToL2MessageExists.items.length == 0 && - this.externalCalls.items.length == 0 && this.contractInstances.items.length == 0 && this.contractBytecodeHints.items.length == 0 && this.publicDataReads.items.length == 0 && @@ -957,11 +768,6 @@ export class AvmExecutionHints { static from(fields: FieldsOf): AvmExecutionHints { return new AvmExecutionHints( fields.enqueuedCalls.items, - fields.storageValues.items, - fields.noteHashExists.items, - fields.nullifierExists.items, - fields.l1ToL2MessageExists.items, - fields.externalCalls.items, fields.contractInstances.items, fields.contractBytecodeHints.items, fields.publicDataReads.items, @@ -982,11 +788,6 @@ export class AvmExecutionHints { static getFields(fields: FieldsOf) { return [ fields.enqueuedCalls, - fields.storageValues, - fields.noteHashExists, - fields.nullifierExists, - fields.l1ToL2MessageExists, - fields.externalCalls, fields.contractInstances, fields.contractBytecodeHints, fields.publicDataReads, @@ -1008,11 +809,6 @@ export class AvmExecutionHints { const reader = BufferReader.asReader(buff); return new AvmExecutionHints( reader.readVector(AvmEnqueuedCallHint), - reader.readVector(AvmKeyValueHint), - reader.readVector(AvmKeyValueHint), - reader.readVector(AvmKeyValueHint), - reader.readVector(AvmKeyValueHint), - reader.readVector(AvmExternalCallHint), reader.readVector(AvmContractInstanceHint), reader.readVector(AvmContractBytecodeHints), reader.readVector(AvmPublicDataReadTreeHint), diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 52bbcd9b535..59fce246f20 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -24,8 +24,6 @@ import { AvmCircuitInputs, AvmContractInstanceHint, AvmExecutionHints, - AvmExternalCallHint, - AvmKeyValueHint, BaseOrMergeRollupPublicInputs, BaseParityInputs, CallContext, @@ -1235,30 +1233,6 @@ export function makeVector(length: number, fn: (i: number) return new Vector(makeArray(length, fn, offset)); } -/** - * Makes arbitrary AvmKeyValueHint. - * @param seed - The seed to use for generating the state reference. - * @returns AvmKeyValueHint. - */ -export function makeAvmKeyValueHint(seed = 0): AvmKeyValueHint { - return new AvmKeyValueHint(new Fr(seed), new Fr(seed + 1)); -} - -/** - * Makes arbitrary AvmExternalCallHint. - * @param seed - The seed to use for generating the state reference. - * @returns AvmExternalCallHint. - */ -export function makeAvmExternalCallHint(seed = 0): AvmExternalCallHint { - return new AvmExternalCallHint( - new Fr(seed % 2), - makeArray((seed % 100) + 10, i => new Fr(i), seed + 0x1000), - new Gas(seed + 0x200, seed), - new Fr(seed + 0x300), - new AztecAddress(new Fr(seed + 0x400)), - ); -} - export function makeContractInstanceFromClassId(classId: Fr, seed = 0): ContractInstanceWithAddress { const salt = new Fr(seed); const initializationHash = new Fr(seed + 1); @@ -1393,11 +1367,6 @@ export function makeAvmExecutionHints( return AvmExecutionHints.from({ enqueuedCalls: makeVector(baseLength, makeAvmEnqueuedCallHint, seed + 0x4100), - storageValues: makeVector(baseLength, makeAvmKeyValueHint, seed + 0x4200), - noteHashExists: makeVector(baseLength + 1, makeAvmKeyValueHint, seed + 0x4300), - nullifierExists: makeVector(baseLength + 2, makeAvmKeyValueHint, seed + 0x4400), - l1ToL2MessageExists: makeVector(baseLength + 3, makeAvmKeyValueHint, seed + 0x4500), - externalCalls: makeVector(baseLength + 4, makeAvmExternalCallHint, seed + 0x4600), contractInstances: makeVector(baseLength + 5, makeAvmContractInstanceHint, seed + 0x4700), contractBytecodeHints: makeVector(baseLength + 6, makeAvmBytecodeHints, seed + 0x4800), publicDataReads: makeVector(baseLength + 7, makeAvmStorageReadTreeHints, seed + 0x4900), diff --git a/yarn-project/simulator/src/avm/avm_simulator.test.ts b/yarn-project/simulator/src/avm/avm_simulator.test.ts index 8770a389c8d..6c621470172 100644 --- a/yarn-project/simulator/src/avm/avm_simulator.test.ts +++ b/yarn-project/simulator/src/avm/avm_simulator.test.ts @@ -27,7 +27,6 @@ import { MockedAvmTestContractDataSource } from '../public/fixtures/index.js'; import { WorldStateDB } from '../public/public_db_sources.js'; import { type PublicSideEffectTraceInterface } from '../public/side_effect_trace_interface.js'; import { type AvmContext } from './avm_context.js'; -import { type AvmExecutionEnvironment } from './avm_execution_environment.js'; import { type MemoryValue, TypeTag, type Uint8, type Uint64 } from './avm_memory_types.js'; import { AvmSimulator } from './avm_simulator.js'; import { AvmEphemeralForest } from './avm_tree.js'; @@ -876,31 +875,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); describe('Nested external calls', () => { - const expectTracedNestedCall = ( - environment: AvmExecutionEnvironment, - nestedTrace: PublicSideEffectTraceInterface, - isStaticCall: boolean = false, - exists: boolean = true, - ) => { - expect(trace.traceNestedCall).toHaveBeenCalledTimes(1); - expect(trace.traceNestedCall).toHaveBeenCalledWith( - /*nestedCallTrace=*/ nestedTrace, - /*nestedEnvironment=*/ expect.objectContaining({ - sender: environment.address, // sender is top-level call - contractCallDepth: new Fr(1), // top call is depth 0, nested is depth 1 - globals: environment.globals, // just confirming that nested env looks roughly right - isStaticCall: isStaticCall, - // top-level calls forward args in these tests, - // but nested calls in these tests use public_dispatch, so selector is inserted as first arg - calldata: expect.arrayContaining([/*selector=*/ expect.anything(), ...environment.calldata]), - }), - /*startGasLeft=*/ expect.anything(), - /*bytecode=*/ exists ? expect.anything() : undefined, - /*avmCallResults=*/ expect.anything(), // we don't have the NESTED call's results to check - /*functionName=*/ expect.anything(), - ); - }; - it(`Nested call to non-existent contract`, async () => { const calldata = [value0, value1]; const context = createContext(calldata); @@ -914,8 +888,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { const results = await new AvmSimulator(context).executeBytecode(callBytecode); expect(results.reverted).toBe(true); expect(results.output).toEqual([]); - - expectTracedNestedCall(context.environment, nestedTrace, /*isStaticCall=*/ false, /*exists=*/ false); }); it(`Nested call`, async () => { @@ -940,8 +912,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { const results = await new AvmSimulator(context).executeBytecode(callBytecode); expect(results.reverted).toBe(false); expect(results.output).toEqual([value0.add(value1)]); - - expectTracedNestedCall(context.environment, nestedTrace); }); it(`Nested static call`, async () => { @@ -966,8 +936,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { const results = await new AvmSimulator(context).executeBytecode(callBytecode); expect(results.reverted).toBe(false); expect(results.output).toEqual([value0.add(value1)]); - - expectTracedNestedCall(context.environment, nestedTrace, /*isStaticCall=*/ true); }); it(`Nested call with not enough gas (expect failure)`, async () => { @@ -994,9 +962,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { const results = await new AvmSimulator(context).executeBytecode(artifact.bytecode); expect(results.reverted).toBe(true); expect(results.revertReason?.message).toMatch('Not enough L2GAS gas left'); - - // Nested call should have been made (and failed). - expect(trace.traceNestedCall).toHaveBeenCalledTimes(1); }); it(`Nested static call which modifies storage (expect failure)`, async () => { @@ -1024,8 +989,6 @@ describe('AVM simulator: transpiled Noir contracts', () => { 'Static call cannot update the state, emit L2->L1 messages or generate logs', ); - expectTracedNestedCall(context.environment, nestedTrace, /*isStaticCall=*/ true); - // Nested call should NOT have been able to write storage expect(trace.tracePublicStorageWrite).toHaveBeenCalledTimes(0); }); @@ -1117,6 +1080,7 @@ describe('AVM simulator: transpiled Noir contracts', () => { }); }); }); + describe('Side effects including merkle checks', () => { const address = AztecAddress.fromNumber(1); const sender = AztecAddress.fromNumber(42); diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 62a351878f8..5a2a6737d64 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -4,7 +4,6 @@ import { CANONICAL_AUTH_REGISTRY_ADDRESS, DEPLOYER_CONTRACT_ADDRESS, FEE_JUICE_ADDRESS, - type Gas, MULTI_CALL_ENTRYPOINT_ADDRESS, NullifierLeafPreimage, type PublicCallRequest, @@ -23,7 +22,6 @@ import { strict as assert } from 'assert'; import { getPublicFunctionDebugName } from '../../common/debug_fn_name.js'; import { type WorldStateDB } from '../../public/public_db_sources.js'; import { type PublicSideEffectTraceInterface } from '../../public/side_effect_trace_interface.js'; -import { type AvmContractCallResult } from '../avm_contract_call_result.js'; import { type AvmExecutionEnvironment } from '../avm_execution_environment.js'; import { AvmEphemeralForest } from '../avm_tree.js'; import { NullifierCollisionError, NullifierManager } from './nullifiers.js'; @@ -685,31 +683,6 @@ export class AvmPersistableStateManager { } } - public async traceNestedCall( - forkedState: AvmPersistableStateManager, - nestedEnvironment: AvmExecutionEnvironment, - startGasLeft: Gas, - bytecode: Buffer, - avmCallResults: AvmContractCallResult, - ) { - const functionName = await getPublicFunctionDebugName( - this.worldStateDB, - nestedEnvironment.address, - nestedEnvironment.calldata, - ); - - this.log.verbose(`[AVM] Tracing nested external contract call ${functionName}`); - - this.trace.traceNestedCall( - forkedState.trace, - nestedEnvironment, - startGasLeft, - bytecode, - avmCallResults, - functionName, - ); - } - public traceEnqueuedCall(publicCallRequest: PublicCallRequest, calldata: Fr[], reverted: boolean) { this.trace.traceEnqueuedCall(publicCallRequest, calldata, reverted); } diff --git a/yarn-project/simulator/src/avm/opcodes/external_calls.ts b/yarn-project/simulator/src/avm/opcodes/external_calls.ts index 30284375e35..b774c7f4cfc 100644 --- a/yarn-project/simulator/src/avm/opcodes/external_calls.ts +++ b/yarn-project/simulator/src/avm/opcodes/external_calls.ts @@ -1,5 +1,3 @@ -import { Gas } from '@aztec/circuits.js'; - import type { AvmContext } from '../avm_context.js'; import { type AvmContractCallResult } from '../avm_contract_call_result.js'; import { type Field, TypeTag, Uint1 } from '../avm_memory_types.js'; @@ -96,14 +94,6 @@ abstract class ExternalCall extends Instruction { } else { context.persistableState.reject(nestedContext.persistableState); } - await context.persistableState.traceNestedCall( - /*nestedState=*/ nestedContext.persistableState, - /*nestedEnvironment=*/ nestedContext.environment, - /*startGasLeft=*/ Gas.from(allocatedGas), - /*bytecode=*/ simulator.getBytecode()!, - /*avmCallResults=*/ nestedCallResults, - ); - memory.assert({ reads: calldataSize + 4, writes: 1, addressing }); } diff --git a/yarn-project/simulator/src/public/dual_side_effect_trace.ts b/yarn-project/simulator/src/public/dual_side_effect_trace.ts deleted file mode 100644 index 1500ba12cf1..00000000000 --- a/yarn-project/simulator/src/public/dual_side_effect_trace.ts +++ /dev/null @@ -1,280 +0,0 @@ -import { type UnencryptedL2Log } from '@aztec/circuit-types'; -import { - type ContractClassIdPreimage, - type Gas, - type NullifierLeafPreimage, - type PublicCallRequest, - type PublicDataTreeLeafPreimage, - type SerializableContractInstance, -} from '@aztec/circuits.js'; -import { type AztecAddress } from '@aztec/foundation/aztec-address'; -import { type Fr } from '@aztec/foundation/fields'; - -import { assert } from 'console'; - -import { type AvmContractCallResult, type AvmFinalizedCallResult } 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 EnqueuedPublicCallExecutionResultWithSideEffects, type PublicFunctionCallResult } from './execution.js'; -import { type PublicSideEffectTrace } from './side_effect_trace.js'; -import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js'; - -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 merge(nestedTrace: this, reverted: boolean = false) { - this.enqueuedCallTrace.merge(nestedTrace.enqueuedCallTrace, reverted); - } - - public getCounter() { - assert(this.innerCallTrace.getCounter() == this.enqueuedCallTrace.getCounter()); - return this.innerCallTrace.getCounter(); - } - - public tracePublicStorageRead( - contractAddress: AztecAddress, - slot: Fr, - value: Fr, - leafPreimage: PublicDataTreeLeafPreimage, - leafIndex: Fr, - path: Fr[], - ) { - this.innerCallTrace.tracePublicStorageRead(contractAddress, slot, value, leafPreimage, leafIndex, path); - this.enqueuedCallTrace.tracePublicStorageRead(contractAddress, slot, value, leafPreimage, leafIndex, path); - } - - public tracePublicStorageWrite( - contractAddress: AztecAddress, - slot: Fr, - value: Fr, - lowLeafPreimage: PublicDataTreeLeafPreimage, - lowLeafIndex: Fr, - lowLeafPath: Fr[], - newLeafPreimage: PublicDataTreeLeafPreimage, - insertionPath: Fr[], - ) { - this.innerCallTrace.tracePublicStorageWrite( - contractAddress, - slot, - value, - lowLeafPreimage, - lowLeafIndex, - lowLeafPath, - newLeafPreimage, - insertionPath, - ); - this.enqueuedCallTrace.tracePublicStorageWrite( - contractAddress, - slot, - value, - lowLeafPreimage, - lowLeafIndex, - lowLeafPath, - newLeafPreimage, - insertionPath, - ); - } - - // TODO(8287): _exists can be removed once we have the vm properly handling the equality check - public traceNoteHashCheck(contractAddress: AztecAddress, noteHash: Fr, leafIndex: Fr, exists: boolean, path: Fr[]) { - this.innerCallTrace.traceNoteHashCheck(contractAddress, noteHash, leafIndex, exists, path); - this.enqueuedCallTrace.traceNoteHashCheck(contractAddress, noteHash, leafIndex, exists, path); - } - - public traceNewNoteHash(contractAddress: AztecAddress, noteHash: Fr, leafIndex: Fr, path: Fr[]) { - this.innerCallTrace.traceNewNoteHash(contractAddress, noteHash, leafIndex, path); - this.enqueuedCallTrace.traceNewNoteHash(contractAddress, noteHash, leafIndex, path); - } - - public traceNullifierCheck( - siloedNullifier: Fr, - exists: boolean, - lowLeafPreimage: NullifierLeafPreimage, - lowLeafIndex: Fr, - lowLeafPath: Fr[], - ) { - this.innerCallTrace.traceNullifierCheck(siloedNullifier, exists, lowLeafPreimage, lowLeafIndex, lowLeafPath); - this.enqueuedCallTrace.traceNullifierCheck(siloedNullifier, exists, lowLeafPreimage, lowLeafIndex, lowLeafPath); - } - - public traceNewNullifier( - siloedNullifier: Fr, - lowLeafPreimage: NullifierLeafPreimage, - lowLeafIndex: Fr, - lowLeafPath: Fr[], - insertionPath: Fr[], - ) { - this.innerCallTrace.traceNewNullifier(siloedNullifier, lowLeafPreimage, lowLeafIndex, lowLeafPath, insertionPath); - this.enqueuedCallTrace.traceNewNullifier( - siloedNullifier, - lowLeafPreimage, - lowLeafIndex, - lowLeafPath, - insertionPath, - ); - } - - traceL1ToL2MessageCheck(contractAddress: AztecAddress, msgHash: Fr, msgLeafIndex: Fr, exists: boolean, path: Fr[]) { - this.innerCallTrace.traceL1ToL2MessageCheck(contractAddress, msgHash, msgLeafIndex, exists, path); - this.enqueuedCallTrace.traceL1ToL2MessageCheck(contractAddress, msgHash, msgLeafIndex, exists, path); - } - - public traceNewL2ToL1Message(contractAddress: AztecAddress, recipient: Fr, content: Fr) { - this.innerCallTrace.traceNewL2ToL1Message(contractAddress, recipient, content); - this.enqueuedCallTrace.traceNewL2ToL1Message(contractAddress, recipient, content); - } - - public traceUnencryptedLog(contractAddress: AztecAddress, log: Fr[]) { - this.innerCallTrace.traceUnencryptedLog(contractAddress, log); - this.enqueuedCallTrace.traceUnencryptedLog(contractAddress, log); - } - - public traceGetContractInstance( - contractAddress: AztecAddress, - exists: boolean, - instance: SerializableContractInstance | undefined, - lowLeafPreimage: NullifierLeafPreimage | undefined, - lowLeafIndex: Fr | undefined, - lowLeafPath: Fr[] | undefined, - ) { - this.innerCallTrace.traceGetContractInstance( - contractAddress, - exists, - instance, - lowLeafPreimage, - lowLeafIndex, - lowLeafPath, - ); - this.enqueuedCallTrace.traceGetContractInstance( - contractAddress, - exists, - instance, - lowLeafPreimage, - lowLeafIndex, - lowLeafPath, - ); - } - - public traceGetBytecode( - contractAddress: AztecAddress, - exists: boolean, - bytecode: Buffer, - contractInstance: SerializableContractInstance | undefined, - contractClass: ContractClassIdPreimage | undefined, - lowLeafPreimage: NullifierLeafPreimage | undefined, - lowLeafIndex: Fr | undefined, - lowLeafPath: Fr[] | undefined, - ) { - this.innerCallTrace.traceGetBytecode( - contractAddress, - exists, - bytecode, - contractInstance, - contractClass, - lowLeafPreimage, - lowLeafIndex, - lowLeafPath, - ); - this.enqueuedCallTrace.traceGetBytecode( - contractAddress, - exists, - bytecode, - contractInstance, - contractClass, - lowLeafPreimage, - lowLeafIndex, - lowLeafPath, - ); - } - - /** - * 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, - /** 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, - bytecode, - avmCallResults, - functionName, - ); - this.enqueuedCallTrace.traceNestedCall( - nestedCallTrace.enqueuedCallTrace, - nestedEnvironment, - startGasLeft, - bytecode, - avmCallResults, - functionName, - ); - } - - public traceEnqueuedCall( - /** The call request from private that enqueued this call. */ - publicCallRequest: PublicCallRequest, - /** The call's calldata */ - calldata: Fr[], - /** Did the call revert? */ - reverted: boolean, - ) { - this.enqueuedCallTrace.traceEnqueuedCall(publicCallRequest, calldata, reverted); - } - - /** - * Convert this trace to a PublicExecutionResult for use externally to the simulator. - */ - public toPublicEnqueuedCallExecutionResult( - /** The call's results */ - avmCallResults: AvmFinalizedCallResult, - ): EnqueuedPublicCallExecutionResultWithSideEffects { - return this.enqueuedCallTrace.toPublicEnqueuedCallExecutionResult(avmCallResults); - } - /** - * Convert this trace to a PublicExecutionResult for use externally to the simulator. - */ - public toPublicFunctionCallResult( - /** The execution environment of the nested call. */ - avmEnvironment: AvmExecutionEnvironment, - /** How much gas was available for this public execution. */ - startGasLeft: Gas, - /** Bytecode used for this execution. */ - bytecode: Buffer, - /** The call's results */ - avmCallResults: AvmFinalizedCallResult, - /** Function name for logging */ - functionName: string = 'unknown', - ): PublicFunctionCallResult { - return this.innerCallTrace.toPublicFunctionCallResult( - avmEnvironment, - startGasLeft, - bytecode, - avmCallResults, - functionName, - ); - } - - public getUnencryptedLogs(): UnencryptedL2Log[] { - return this.enqueuedCallTrace.getUnencryptedLogs(); - } -} diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts index 60b73bc5439..6db2f0ed32f 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.test.ts @@ -351,11 +351,6 @@ describe('Enqueued-call Side Effect Trace', () => { const parentHints = trace.getAvmCircuitHints(); const childHints = nestedTrace.getAvmCircuitHints(); expect(parentHints.enqueuedCalls.items).toEqual(childHints.enqueuedCalls.items); - expect(parentHints.storageValues.items).toEqual(childHints.storageValues.items); - expect(parentHints.noteHashExists.items).toEqual(childHints.noteHashExists.items); - expect(parentHints.nullifierExists.items).toEqual(childHints.nullifierExists.items); - expect(parentHints.l1ToL2MessageExists.items).toEqual(childHints.l1ToL2MessageExists.items); - expect(parentHints.externalCalls.items).toEqual(childHints.externalCalls.items); expect(parentHints.contractInstances.items).toEqual(childHints.contractInstances.items); expect(parentHints.contractBytecodeHints.items).toEqual(childHints.contractBytecodeHints.items); expect(parentHints.publicDataReads.items).toEqual(childHints.publicDataReads.items); diff --git a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts index 9b30dd016f3..4963632c5e7 100644 --- a/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts +++ b/yarn-project/simulator/src/public/enqueued_call_side_effect_trace.ts @@ -7,7 +7,6 @@ import { AvmContractInstanceHint, AvmEnqueuedCallHint, AvmExecutionHints, - AvmExternalCallHint, AvmNullifierReadTreeHint, AvmNullifierWriteTreeHint, AvmPublicDataReadTreeHint, @@ -53,7 +52,7 @@ import { createLogger } from '@aztec/foundation/log'; import { strict as assert } from 'assert'; -import { type AvmContractCallResult, type AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js'; +import { type AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js'; import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; import { type EnqueuedPublicCallExecutionResultWithSideEffects, type PublicFunctionCallResult } from './execution.js'; import { SideEffectLimitReachedError } from './side_effect_errors.js'; @@ -169,13 +168,6 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI private mergeHints(forkedTrace: this) { this.avmCircuitHints.enqueuedCalls.items.push(...forkedTrace.avmCircuitHints.enqueuedCalls.items); - this.avmCircuitHints.storageValues.items.push(...forkedTrace.avmCircuitHints.storageValues.items); - this.avmCircuitHints.noteHashExists.items.push(...forkedTrace.avmCircuitHints.noteHashExists.items); - this.avmCircuitHints.nullifierExists.items.push(...forkedTrace.avmCircuitHints.nullifierExists.items); - this.avmCircuitHints.l1ToL2MessageExists.items.push(...forkedTrace.avmCircuitHints.l1ToL2MessageExists.items); - - this.avmCircuitHints.externalCalls.items.push(...forkedTrace.avmCircuitHints.externalCalls.items); - this.avmCircuitHints.contractInstances.items.push(...forkedTrace.avmCircuitHints.contractInstances.items); this.avmCircuitHints.contractBytecodeHints.items.push(...forkedTrace.avmCircuitHints.contractBytecodeHints.items); @@ -416,45 +408,6 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI ); } - /** - * 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, - /** Bytecode used for this execution. */ - _bytecode: Buffer, - /** The call's results */ - avmCallResults: AvmContractCallResult, - /** Function name for logging */ - _functionName: string = 'unknown', - ) { - // TODO(4805): check if some threshold is reached for max nested calls (to unique contracts?) - // - // Store end side effect counter before it gets updated by absorbing nested call trace - const endSideEffectCounter = new Fr(this.sideEffectCounter); - - const gasUsed = new Gas( - startGasLeft.daGas - avmCallResults.gasLeft.daGas, - startGasLeft.l2Gas - avmCallResults.gasLeft.l2Gas, - ); - - this.avmCircuitHints.externalCalls.items.push( - new AvmExternalCallHint( - /*success=*/ new Fr(avmCallResults.reverted ? 0 : 1), - avmCallResults.output, - gasUsed, - endSideEffectCounter, - nestedEnvironment.address, - ), - ); - } - /** * Trace an enqueued call. * Accept some results from a finished call's trace into this one. diff --git a/yarn-project/simulator/src/public/index.ts b/yarn-project/simulator/src/public/index.ts index b7a3a5929f5..fb2fe3986a8 100644 --- a/yarn-project/simulator/src/public/index.ts +++ b/yarn-project/simulator/src/public/index.ts @@ -4,6 +4,5 @@ export { type EnqueuedPublicCallExecutionResult, type PublicFunctionCallResult } export * from './fee_payment.js'; export * from './public_db_sources.js'; export { PublicProcessor, PublicProcessorFactory } from './public_processor.js'; -export { PublicSideEffectTrace } from './side_effect_trace.js'; export { PublicEnqueuedCallSideEffectTrace } from './enqueued_call_side_effect_trace.js'; export { getExecutionRequestsByPhase } from './utils.js'; diff --git a/yarn-project/simulator/src/public/public_tx_context.ts b/yarn-project/simulator/src/public/public_tx_context.ts index e7f25ae64a0..23d0a14bd53 100644 --- a/yarn-project/simulator/src/public/public_tx_context.ts +++ b/yarn-project/simulator/src/public/public_tx_context.ts @@ -31,10 +31,8 @@ import { strict as assert } from 'assert'; import { inspect } from 'util'; import { AvmPersistableStateManager } from '../avm/index.js'; -import { DualSideEffectTrace } from './dual_side_effect_trace.js'; import { PublicEnqueuedCallSideEffectTrace, SideEffectArrayLengths } from './enqueued_call_side_effect_trace.js'; import { type WorldStateDB } from './public_db_sources.js'; -import { PublicSideEffectTrace } from './side_effect_trace.js'; import { generateAvmCircuitPublicInputs } from './transitional_adapters.js'; import { getCallRequestsByPhase, getExecutionRequestsByPhase } from './utils.js'; @@ -87,7 +85,6 @@ export class PublicTxContext { ) { const nonRevertibleAccumulatedDataFromPrivate = tx.data.forPublic!.nonRevertibleAccumulatedData; - const innerCallTrace = new PublicSideEffectTrace(); const previousAccumulatedDataArrayLengths = new SideEffectArrayLengths( /*publicDataWrites*/ 0, countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.noteHashes), @@ -99,10 +96,9 @@ export class PublicTxContext { /*startSideEffectCounter=*/ 0, previousAccumulatedDataArrayLengths, ); - const trace = new DualSideEffectTrace(innerCallTrace, enqueuedCallTrace); // Transaction level state manager that will be forked for revertible phases. - const txStateManager = await AvmPersistableStateManager.create(worldStateDB, trace, doMerkleOperations); + const txStateManager = await AvmPersistableStateManager.create(worldStateDB, enqueuedCallTrace, doMerkleOperations); return new PublicTxContext( new PhaseStateManager(txStateManager), diff --git a/yarn-project/simulator/src/public/side_effect_trace.test.ts b/yarn-project/simulator/src/public/side_effect_trace.test.ts deleted file mode 100644 index 528c7dac1a4..00000000000 --- a/yarn-project/simulator/src/public/side_effect_trace.test.ts +++ /dev/null @@ -1,425 +0,0 @@ -import { UnencryptedL2Log } from '@aztec/circuit-types'; -import { - AztecAddress, - EthAddress, - Gas, - L2ToL1Message, - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, - MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, - MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIERS_PER_TX, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, - NullifierLeafPreimage, - PublicDataTreeLeafPreimage, - SerializableContractInstance, -} from '@aztec/circuits.js'; -import { Fr } from '@aztec/foundation/fields'; - -import { randomBytes, randomInt } from 'crypto'; - -import { AvmContractCallResult } from '../avm/avm_contract_call_result.js'; -import { initExecutionEnvironment } from '../avm/fixtures/index.js'; -import { SideEffectLimitReachedError } from './side_effect_errors.js'; -import { PublicSideEffectTrace } from './side_effect_trace.js'; - -describe('Side Effect Trace', () => { - const address = AztecAddress.random(); - const utxo = Fr.random(); - const leafIndex = Fr.random(); - const slot = Fr.random(); - const value = Fr.random(); - const recipient = Fr.random(); - const content = Fr.random(); - const log = [Fr.random(), Fr.random(), Fr.random()]; - const contractInstance = SerializableContractInstance.default(); - - const startGasLeft = Gas.fromFields([new Fr(randomInt(10000)), new Fr(randomInt(10000))]); - const endGasLeft = Gas.fromFields([new Fr(randomInt(10000)), new Fr(randomInt(10000))]); - const transactionFee = Fr.random(); - const calldata = [Fr.random(), Fr.random(), Fr.random(), Fr.random()]; - const bytecode = randomBytes(100); - const returnValues = [Fr.random(), Fr.random()]; - - const avmEnvironment = initExecutionEnvironment({ - address, - calldata, - transactionFee, - }); - const reverted = false; - const avmCallResults = new AvmContractCallResult(reverted, returnValues, endGasLeft); - - let startCounter: number; - let startCounterFr: Fr; - let startCounterPlus1: number; - let trace: PublicSideEffectTrace; - - beforeEach(() => { - startCounter = randomInt(/*max=*/ 1000000); - startCounterFr = new Fr(startCounter); - startCounterPlus1 = startCounter + 1; - trace = new PublicSideEffectTrace(startCounter); - }); - - const toPxResult = (trc: PublicSideEffectTrace) => { - return trc.toPublicFunctionCallResult(avmEnvironment, startGasLeft, bytecode, avmCallResults.finalize()); - }; - - it('Should trace storage reads', () => { - const leafPreimage = new PublicDataTreeLeafPreimage(slot, value, Fr.ZERO, 0n); - trace.tracePublicStorageRead(address, slot, value, leafPreimage, Fr.ZERO, []); - expect(trace.getCounter()).toBe(startCounterPlus1); - - const pxResult = toPxResult(trace); - expect(pxResult.contractStorageReads).toEqual([ - { - storageSlot: slot, - currentValue: value, - counter: startCounter, - contractAddress: address, - //exists: exists, - //cached: cached, - }, - ]); - expect(pxResult.avmCircuitHints.storageValues.items).toEqual([{ key: startCounterFr, value: value }]); - }); - - it('Should trace storage writes', () => { - const lowLeafPreimage = new PublicDataTreeLeafPreimage(slot, value, Fr.ZERO, 0n); - const newLeafPreimage = new PublicDataTreeLeafPreimage(slot, value, Fr.ZERO, 0n); - - trace.tracePublicStorageWrite(address, slot, value, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); - expect(trace.getCounter()).toBe(startCounterPlus1); - - const pxResult = toPxResult(trace); - expect(pxResult.contractStorageUpdateRequests).toEqual([ - { - storageSlot: slot, - newValue: value, - counter: startCounter, - contractAddress: address, - }, - ]); - }); - - it('Should trace note hash checks', () => { - const exists = true; - trace.traceNoteHashCheck(address, utxo, leafIndex, exists, []); - - const pxResult = toPxResult(trace); - expect(pxResult.noteHashReadRequests).toEqual([ - { - // contractAddress, - value: utxo, - //exists: exists, - // counter: startCounter, - leafIndex, - }, - ]); - expect(pxResult.avmCircuitHints.noteHashExists.items).toEqual([{ key: leafIndex, value: new Fr(exists) }]); - }); - - it('Should trace note hashes', () => { - trace.traceNewNoteHash(address, utxo, Fr.ZERO, []); - expect(trace.getCounter()).toBe(startCounterPlus1); - - const pxResult = toPxResult(trace); - expect(pxResult.noteHashes).toEqual([ - { - // contractAddress, - value: utxo, - counter: startCounter, - }, - ]); - }); - - it('Should trace nullifier checks', () => { - const exists = true; - const lowLeafPreimage = new NullifierLeafPreimage(utxo, Fr.ZERO, 0n); - trace.traceNullifierCheck(utxo, exists, lowLeafPreimage, Fr.ZERO, []); - expect(trace.getCounter()).toBe(startCounterPlus1); - - const pxResult = toPxResult(trace); - expect(pxResult.nullifierReadRequests).toEqual([ - { - value: utxo, - counter: startCounter, - }, - ]); - expect(pxResult.nullifierNonExistentReadRequests).toEqual([]); - expect(pxResult.avmCircuitHints.nullifierExists.items).toEqual([{ key: startCounterFr, value: new Fr(exists) }]); - }); - - it('Should trace non-existent nullifier checks', () => { - const exists = false; - const lowLeafPreimage = new NullifierLeafPreimage(utxo, Fr.ZERO, 0n); - trace.traceNullifierCheck(utxo, exists, lowLeafPreimage, Fr.ZERO, []); - expect(trace.getCounter()).toBe(startCounterPlus1); - - const pxResult = toPxResult(trace); - expect(pxResult.nullifierReadRequests).toEqual([]); - expect(pxResult.nullifierNonExistentReadRequests).toEqual([ - { - value: utxo, - counter: startCounter, - }, - ]); - expect(pxResult.avmCircuitHints.nullifierExists.items).toEqual([{ key: startCounterFr, value: new Fr(exists) }]); - }); - - it('Should trace nullifiers', () => { - const lowLeafPreimage = new NullifierLeafPreimage(utxo, Fr.ZERO, 0n); - trace.traceNewNullifier(utxo, lowLeafPreimage, Fr.ZERO, [], []); - expect(trace.getCounter()).toBe(startCounterPlus1); - - const pxResult = toPxResult(trace); - expect(pxResult.nullifiers).toEqual([ - { - value: utxo, - counter: startCounter, - noteHash: Fr.ZERO, - }, - ]); - }); - - it('Should trace L1ToL2 Message checks', () => { - const exists = true; - trace.traceL1ToL2MessageCheck(address, utxo, leafIndex, exists, []); - - const pxResult = toPxResult(trace); - expect(pxResult.l1ToL2MsgReadRequests).toEqual([ - { - value: utxo, - leafIndex, - }, - ]); - expect(pxResult.avmCircuitHints.l1ToL2MessageExists.items).toEqual([ - { - key: leafIndex, - value: new Fr(exists), - }, - ]); - }); - - it('Should trace new L2ToL1 messages', () => { - trace.traceNewL2ToL1Message(address, recipient, content); - expect(trace.getCounter()).toBe(startCounterPlus1); - - const pxResult = toPxResult(trace); - expect(pxResult.l2ToL1Messages).toEqual([ - new L2ToL1Message(EthAddress.fromField(recipient), content, startCounter), - ]); - }); - - it('Should trace new unencrypted logs', () => { - trace.traceUnencryptedLog(address, log); - expect(trace.getCounter()).toBe(startCounterPlus1); - - const pxResult = toPxResult(trace); - const expectLog = new UnencryptedL2Log(address, Buffer.concat(log.map(f => f.toBuffer()))); - expect(pxResult.unencryptedLogs.logs).toEqual([expectLog]); - expect(pxResult.allUnencryptedLogs.logs).toEqual([expectLog]); - expect(pxResult.unencryptedLogsHashes).toEqual([ - expect.objectContaining({ - counter: startCounter, - }), - ]); - }); - - describe('Maximum accesses', () => { - it('Should enforce maximum number of public storage reads', () => { - for (let i = 0; i < MAX_PUBLIC_DATA_READS_PER_TX; i++) { - const leafPreimage = new PublicDataTreeLeafPreimage(new Fr(i), new Fr(i), Fr.ZERO, 0n); - trace.tracePublicStorageRead(address, slot, value, leafPreimage, Fr.ZERO, []); - } - const leafPreimage = new PublicDataTreeLeafPreimage(new Fr(42), new Fr(42), Fr.ZERO, 0n); - expect(() => trace.tracePublicStorageRead(address, new Fr(42), value, leafPreimage, Fr.ZERO, [])).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of public storage writes', () => { - for (let i = 0; i < MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX; i++) { - const lowLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i), new Fr(i), Fr.ZERO, 0n); - const newLeafPreimage = new PublicDataTreeLeafPreimage(new Fr(i + 1), new Fr(i + 1), Fr.ZERO, 0n); - trace.tracePublicStorageWrite(address, slot, value, lowLeafPreimage, Fr.ZERO, [], newLeafPreimage, []); - } - const leafPreimage = new PublicDataTreeLeafPreimage(new Fr(42), new Fr(42), Fr.ZERO, 0n); - expect(() => - trace.tracePublicStorageWrite( - AztecAddress.fromNumber(42), - new Fr(42), - value, - leafPreimage, - Fr.ZERO, - [], - leafPreimage, - [], - ), - ).toThrow(SideEffectLimitReachedError); - }); - - it('Should enforce maximum number of note hash checks', () => { - for (let i = 0; i < MAX_NOTE_HASH_READ_REQUESTS_PER_TX; i++) { - trace.traceNoteHashCheck(AztecAddress.fromNumber(i), new Fr(i), new Fr(i), true, []); - } - expect(() => trace.traceNoteHashCheck(AztecAddress.fromNumber(42), new Fr(42), new Fr(42), true, [])).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of new note hashes', () => { - for (let i = 0; i < MAX_NOTE_HASHES_PER_TX; i++) { - trace.traceNewNoteHash(AztecAddress.fromNumber(i), new Fr(i), Fr.ZERO, []); - } - expect(() => trace.traceNewNoteHash(AztecAddress.fromNumber(42), new Fr(42), Fr.ZERO, [])).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of nullifier checks', () => { - for (let i = 0; i < MAX_NULLIFIER_READ_REQUESTS_PER_TX; i++) { - const lowLeafPreimage = new NullifierLeafPreimage(new Fr(i), Fr.ZERO, 0n); - trace.traceNullifierCheck(new Fr(i + 1), true, lowLeafPreimage, Fr.ZERO, []); - } - const lowLeafPreimage = new NullifierLeafPreimage(new Fr(41), Fr.ZERO, 0n); - expect(() => trace.traceNullifierCheck(new Fr(42), true, lowLeafPreimage, Fr.ZERO, [])).toThrow( - SideEffectLimitReachedError, - ); - // NOTE: also cannot do a non-existent check once existent checks have filled up - expect(() => trace.traceNullifierCheck(new Fr(42), false, lowLeafPreimage, Fr.ZERO, [])).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of nullifier non-existent checks', () => { - for (let i = 0; i < MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX; i++) { - const lowLeafPreimage = new NullifierLeafPreimage(new Fr(i), Fr.ZERO, 0n); - trace.traceNullifierCheck(new Fr(i + 1), true, lowLeafPreimage, Fr.ZERO, []); - } - const lowLeafPreimage = new NullifierLeafPreimage(new Fr(41), Fr.ZERO, 0n); - expect(() => trace.traceNullifierCheck(new Fr(42), false, lowLeafPreimage, Fr.ZERO, [])).toThrow( - SideEffectLimitReachedError, - ); - // NOTE: also cannot do a existent check once non-existent checks have filled up - expect(() => trace.traceNullifierCheck(new Fr(42), true, lowLeafPreimage, Fr.ZERO, [])).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of new nullifiers', () => { - for (let i = 0; i < MAX_NULLIFIERS_PER_TX; i++) { - const lowLeafPreimage = new NullifierLeafPreimage(new Fr(i + 1), Fr.ZERO, 0n); - trace.traceNewNullifier(new Fr(i), lowLeafPreimage, Fr.ZERO, [], []); - } - const lowLeafPreimage = new NullifierLeafPreimage(new Fr(41), Fr.ZERO, 0n); - expect(() => trace.traceNewNullifier(new Fr(42), lowLeafPreimage, Fr.ZERO, [], [])).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of L1 to L2 message checks', () => { - for (let i = 0; i < MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX; i++) { - trace.traceL1ToL2MessageCheck(AztecAddress.fromNumber(i), new Fr(i), new Fr(i), true, []); - } - expect(() => - trace.traceL1ToL2MessageCheck(AztecAddress.fromNumber(42), new Fr(42), new Fr(42), true, []), - ).toThrow(SideEffectLimitReachedError); - }); - - it('Should enforce maximum number of new l2 to l1 messages', () => { - for (let i = 0; i < MAX_L2_TO_L1_MSGS_PER_TX; i++) { - trace.traceNewL2ToL1Message(AztecAddress.fromNumber(i), new Fr(i), new Fr(i)); - } - expect(() => trace.traceNewL2ToL1Message(AztecAddress.fromNumber(42), new Fr(42), new Fr(42))).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of new logs hashes', () => { - for (let i = 0; i < MAX_UNENCRYPTED_LOGS_PER_TX; i++) { - trace.traceUnencryptedLog(AztecAddress.fromNumber(i), [new Fr(i), new Fr(i)]); - } - expect(() => trace.traceUnencryptedLog(AztecAddress.fromNumber(42), [new Fr(42), new Fr(42)])).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of nullifier checks for GETCONTRACTINSTANCE', () => { - for (let i = 0; i < MAX_NULLIFIER_READ_REQUESTS_PER_TX; i++) { - const lowLeafPreimage = new NullifierLeafPreimage(new Fr(i), Fr.ZERO, 0n); - trace.traceNullifierCheck(new Fr(i + 1), true, lowLeafPreimage, Fr.ZERO, []); - } - expect(() => trace.traceGetContractInstance(address, /*exists=*/ true, contractInstance)).toThrow( - SideEffectLimitReachedError, - ); - // NOTE: also cannot do a existent check once non-existent checks have filled up - expect(() => trace.traceGetContractInstance(address, /*exists=*/ false, contractInstance)).toThrow( - SideEffectLimitReachedError, - ); - }); - - it('Should enforce maximum number of nullifier non-existent checks for GETCONTRACTINSTANCE', () => { - for (let i = 0; i < MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX; i++) { - const lowLeafPreimage = new NullifierLeafPreimage(new Fr(i), Fr.ZERO, 0n); - trace.traceNullifierCheck(new Fr(i + 1), true, lowLeafPreimage, Fr.ZERO, []); - } - expect(() => trace.traceGetContractInstance(address, /*exists=*/ false, contractInstance)).toThrow( - SideEffectLimitReachedError, - ); - // NOTE: also cannot do a existent check once non-existent checks have filled up - expect(() => trace.traceGetContractInstance(address, /*exists=*/ true, contractInstance)).toThrow( - SideEffectLimitReachedError, - ); - }); - }); - - it('Should trace nested calls', () => { - const existsDefault = true; - - const nestedTrace = new PublicSideEffectTrace(startCounter); - let testCounter = startCounter; - const leafPreimage = new PublicDataTreeLeafPreimage(slot, value, Fr.ZERO, 0n); - const lowLeafPreimage = new NullifierLeafPreimage(utxo, Fr.ZERO, 0n); - nestedTrace.tracePublicStorageRead(address, slot, value, leafPreimage, Fr.ZERO, []); - testCounter++; - nestedTrace.tracePublicStorageWrite(address, slot, value, leafPreimage, Fr.ZERO, [], leafPreimage, []); - testCounter++; - nestedTrace.traceNoteHashCheck(address, utxo, leafIndex, existsDefault, []); - // counter does not increment for note hash checks - nestedTrace.traceNewNoteHash(address, utxo, Fr.ZERO, []); - testCounter++; - nestedTrace.traceNullifierCheck(utxo, true, lowLeafPreimage, Fr.ZERO, []); - testCounter++; - nestedTrace.traceNullifierCheck(utxo, true, lowLeafPreimage, Fr.ZERO, []); - testCounter++; - nestedTrace.traceNewNullifier(utxo, lowLeafPreimage, Fr.ZERO, [], []); - testCounter++; - nestedTrace.traceL1ToL2MessageCheck(address, utxo, leafIndex, existsDefault, []); - // counter does not increment for l1tol2 message checks - nestedTrace.traceNewL2ToL1Message(address, recipient, content); - testCounter++; - nestedTrace.traceUnencryptedLog(address, log); - testCounter++; - nestedTrace.traceGetContractInstance(address, /*exists=*/ true, contractInstance); - testCounter++; - nestedTrace.traceGetContractInstance(address, /*exists=*/ false, contractInstance); - testCounter++; - - trace.traceNestedCall(nestedTrace, avmEnvironment, startGasLeft, bytecode, avmCallResults); - // parent trace adopts nested call's counter - expect(trace.getCounter()).toBe(testCounter); - - // get parent trace as result - const parentPxResult = toPxResult(trace); - const childPxResult = toPxResult(nestedTrace); - expect(parentPxResult.nestedExecutions).toEqual([childPxResult]); - - // parent absorb's child's unencryptedLogs into all* - expect(parentPxResult.allUnencryptedLogs).toEqual(childPxResult.allUnencryptedLogs); - }); -}); diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts deleted file mode 100644 index 47efe303a15..00000000000 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ /dev/null @@ -1,543 +0,0 @@ -import { PublicExecutionRequest, UnencryptedFunctionL2Logs, UnencryptedL2Log } from '@aztec/circuit-types'; -import { - AvmAppendTreeHint, - AvmContractBytecodeHints, - AvmContractInstanceHint, - AvmExecutionHints, - AvmExternalCallHint, - AvmKeyValueHint, - AvmNullifierReadTreeHint, - AvmNullifierWriteTreeHint, - AvmPublicDataReadTreeHint, - AvmPublicDataWriteTreeHint, - type AztecAddress, - CallContext, - type ContractClassIdPreimage, - type ContractInstanceWithAddress, - ContractStorageRead, - ContractStorageUpdateRequest, - EthAddress, - FunctionSelector, - Gas, - L1_TO_L2_MSG_TREE_HEIGHT, - L2ToL1Message, - LogHash, - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX, - MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_HASHES_PER_TX, - MAX_NOTE_HASH_READ_REQUESTS_PER_TX, - MAX_NULLIFIERS_PER_TX, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, - MAX_PUBLIC_DATA_READS_PER_TX, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_TX, - NOTE_HASH_TREE_HEIGHT, - NULLIFIER_TREE_HEIGHT, - NoteHash, - Nullifier, - NullifierLeafPreimage, - PUBLIC_DATA_TREE_HEIGHT, - type PublicCallRequest, - PublicDataTreeLeafPreimage, - type PublicInnerCallRequest, - ReadRequest, - SerializableContractInstance, - TreeLeafReadRequest, -} from '@aztec/circuits.js'; -import { Fr } from '@aztec/foundation/fields'; -import { jsonStringify } from '@aztec/foundation/json-rpc'; -import { createLogger } from '@aztec/foundation/log'; - -import { assert } from 'console'; - -import { type AvmContractCallResult, type AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js'; -import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; -import { - type EnqueuedPublicCallExecutionResultWithSideEffects, - type PublicFunctionCallResult, - resultToPublicCallRequest, -} from './execution.js'; -import { SideEffectLimitReachedError } from './side_effect_errors.js'; -import { type PublicSideEffectTraceInterface } from './side_effect_trace_interface.js'; - -export type TracedContractInstance = { exists: boolean } & ContractInstanceWithAddress; - -const emptyPublicDataPath = () => new Array(PUBLIC_DATA_TREE_HEIGHT).fill(Fr.zero()); -const emptyNoteHashPath = () => new Array(NOTE_HASH_TREE_HEIGHT).fill(Fr.zero()); -const emptyNullifierPath = () => new Array(NULLIFIER_TREE_HEIGHT).fill(Fr.zero()); -const emptyL1ToL2MessagePath = () => new Array(L1_TO_L2_MSG_TREE_HEIGHT).fill(Fr.zero()); - -export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { - public log = createLogger('public_side_effect_trace'); - - /** The side effect counter increments with every call to the trace. */ - private sideEffectCounter: number; // kept as number until finalized for efficiency - - private contractStorageReads: ContractStorageRead[] = []; - private contractStorageUpdateRequests: ContractStorageUpdateRequest[] = []; - - private noteHashReadRequests: TreeLeafReadRequest[] = []; - private noteHashes: NoteHash[] = []; - - private nullifierReadRequests: ReadRequest[] = []; - private nullifierNonExistentReadRequests: ReadRequest[] = []; - private nullifiers: Nullifier[] = []; - - private l1ToL2MsgReadRequests: TreeLeafReadRequest[] = []; - private newL2ToL1Messages: L2ToL1Message[] = []; - - private unencryptedLogs: UnencryptedL2Log[] = []; - private allUnencryptedLogs: UnencryptedL2Log[] = []; - private unencryptedLogsHashes: LogHash[] = []; - - private publicCallRequests: PublicInnerCallRequest[] = []; - - private nestedExecutions: PublicFunctionCallResult[] = []; - - private avmCircuitHints: AvmExecutionHints; - - constructor( - /** The counter of this trace's first side effect. */ - public readonly startSideEffectCounter: number = 0, - ) { - this.sideEffectCounter = startSideEffectCounter; - this.avmCircuitHints = AvmExecutionHints.empty(); - } - - public fork() { - return new PublicSideEffectTrace(this.sideEffectCounter); - } - - public getCounter() { - return this.sideEffectCounter; - } - - private incrementSideEffectCounter() { - this.sideEffectCounter++; - } - - public tracePublicStorageRead( - contractAddress: AztecAddress, - slot: Fr, - value: Fr, - leafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(), - leafIndex: Fr = Fr.zero(), - path: Fr[] = emptyPublicDataPath(), - ) { - if (!leafIndex.equals(Fr.zero())) { - // if we have real merkle hint content, make sure the value matches the the provided preimage - assert(leafPreimage.value.equals(value), 'Value mismatch when tracing in public data write'); - } - if (this.contractStorageReads.length >= MAX_PUBLIC_DATA_READS_PER_TX) { - throw new SideEffectLimitReachedError('contract storage read', MAX_PUBLIC_DATA_READS_PER_TX); - } - - this.contractStorageReads.push(new ContractStorageRead(slot, value, this.sideEffectCounter, contractAddress)); - this.avmCircuitHints.storageValues.items.push( - new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ value), - ); - - // New hinting - this.avmCircuitHints.publicDataReads.items.push(new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, path)); - - this.log.debug(`SLOAD cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`); - this.incrementSideEffectCounter(); - } - - public tracePublicStorageWrite( - contractAddress: AztecAddress, - slot: Fr, - value: Fr, - lowLeafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(), - lowLeafIndex: Fr = Fr.zero(), - lowLeafPath: Fr[] = emptyPublicDataPath(), - newLeafPreimage: PublicDataTreeLeafPreimage = PublicDataTreeLeafPreimage.empty(), - insertionPath: Fr[] = emptyPublicDataPath(), - ) { - if (!lowLeafIndex.equals(Fr.zero())) { - // if we have real merkle hint content, make sure the value matches the the provided preimage - assert(newLeafPreimage.value.equals(value), 'Value mismatch when tracing in public data read'); - } - if (this.contractStorageUpdateRequests.length >= MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) { - throw new SideEffectLimitReachedError('contract storage write', MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX); - } - - this.contractStorageUpdateRequests.push( - new ContractStorageUpdateRequest(slot, value, this.sideEffectCounter, contractAddress), - ); - - // New hinting - const readHint = new AvmPublicDataReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath); - this.avmCircuitHints.publicDataWrites.items.push( - new AvmPublicDataWriteTreeHint(readHint, newLeafPreimage, insertionPath), - ); - this.log.debug(`SSTORE cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`); - this.incrementSideEffectCounter(); - } - - // TODO(8287): _exists can be removed once we have the vm properly handling the equality check - public traceNoteHashCheck( - _contractAddress: AztecAddress, - noteHash: Fr, - leafIndex: Fr, - exists: boolean, - path: Fr[] = emptyNoteHashPath(), - ) { - // NOTE: contractAddress is unused but will be important when an AVM circuit processes an entire enqueued call - if (this.noteHashReadRequests.length >= MAX_NOTE_HASH_READ_REQUESTS_PER_TX) { - throw new SideEffectLimitReachedError('note hash read request', MAX_NOTE_HASH_READ_REQUESTS_PER_TX); - } - // Temp for backward compatibility - this.noteHashReadRequests.push(new TreeLeafReadRequest(noteHash, leafIndex)); - this.avmCircuitHints.noteHashExists.items.push( - new AvmKeyValueHint(/*key=*/ new Fr(leafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO), - ); - // New Hinting - this.avmCircuitHints.noteHashReads.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path)); - // NOTE: counter does not increment for note hash checks (because it doesn't rely on pending note hashes) - } - - public traceNewNoteHash( - _contractAddress: AztecAddress, - noteHash: Fr, - leafIndex: Fr = Fr.zero(), - path: Fr[] = emptyNoteHashPath(), - ) { - if (this.noteHashes.length >= MAX_NOTE_HASHES_PER_TX) { - throw new SideEffectLimitReachedError('note hash', MAX_NOTE_HASHES_PER_TX); - } - this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter)); - this.log.debug(`NEW_NOTE_HASH cnt: ${this.sideEffectCounter}`); - - // New Hinting - this.avmCircuitHints.noteHashWrites.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path)); - this.incrementSideEffectCounter(); - } - - public traceNullifierCheck( - siloedNullifier: Fr, - exists: boolean, - lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(), - lowLeafIndex: Fr = Fr.zero(), - lowLeafPath: Fr[] = emptyNullifierPath(), - ) { - // NOTE: contractAddress is unused but will be important when an AVM circuit processes an entire enqueued call - // NOTE: isPending and leafIndex are unused for now but may be used for optimizations or kernel hints later - - this.enforceLimitOnNullifierChecks(); - - const readRequest = new ReadRequest(siloedNullifier, this.sideEffectCounter); - if (exists) { - this.nullifierReadRequests.push(readRequest); - } else { - this.nullifierNonExistentReadRequests.push(readRequest); - } - this.avmCircuitHints.nullifierExists.items.push( - new AvmKeyValueHint(/*key=*/ new Fr(this.sideEffectCounter), /*value=*/ new Fr(exists ? 1 : 0)), - ); - - // New Hints - this.avmCircuitHints.nullifierReads.items.push( - new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath), - ); - this.log.debug(`NULLIFIER_EXISTS cnt: ${this.sideEffectCounter}`); - this.incrementSideEffectCounter(); - } - - public traceNewNullifier( - siloedNullifier: Fr, - lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(), - lowLeafIndex: Fr = Fr.zero(), - lowLeafPath: Fr[] = emptyNullifierPath(), - insertionPath: Fr[] = emptyNullifierPath(), - ) { - // NOTE: contractAddress is unused but will be important when an AVM circuit processes an entire enqueued call - if (this.nullifiers.length >= MAX_NULLIFIERS_PER_TX) { - throw new SideEffectLimitReachedError('nullifier', MAX_NULLIFIERS_PER_TX); - } - // this will be wrong for siloedNullifier - this.nullifiers.push(new Nullifier(siloedNullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO)); - // New hinting - const lowLeafReadHint = new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath); - this.avmCircuitHints.nullifierWrites.items.push(new AvmNullifierWriteTreeHint(lowLeafReadHint, insertionPath)); - this.log.debug(`NEW_NULLIFIER cnt: ${this.sideEffectCounter}`); - this.incrementSideEffectCounter(); - } - - // TODO(8287): _exists can be removed once we have the vm properly handling the equality check - public traceL1ToL2MessageCheck( - _contractAddress: AztecAddress, - msgHash: Fr, - msgLeafIndex: Fr, - exists: boolean, - path: Fr[] = emptyL1ToL2MessagePath(), - ) { - // NOTE: contractAddress is unused but will be important when an AVM circuit processes an entire enqueued call - if (this.l1ToL2MsgReadRequests.length >= MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX) { - throw new SideEffectLimitReachedError('l1 to l2 message read request', MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_TX); - } - this.l1ToL2MsgReadRequests.push(new TreeLeafReadRequest(msgHash, msgLeafIndex)); - this.avmCircuitHints.l1ToL2MessageExists.items.push( - new AvmKeyValueHint(/*key=*/ new Fr(msgLeafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO), - ); - - // New Hinting - this.avmCircuitHints.l1ToL2MessageReads.items.push(new AvmAppendTreeHint(msgLeafIndex, msgHash, path)); - // NOTE: counter does not increment for l1tol2 message checks (because it doesn't rely on pending messages) - } - - public traceNewL2ToL1Message(_contractAddress: AztecAddress, recipient: Fr, content: Fr) { - if (this.newL2ToL1Messages.length >= MAX_L2_TO_L1_MSGS_PER_TX) { - throw new SideEffectLimitReachedError('l2 to l1 message', MAX_L2_TO_L1_MSGS_PER_TX); - } - const recipientAddress = EthAddress.fromField(recipient); - this.newL2ToL1Messages.push(new L2ToL1Message(recipientAddress, content, this.sideEffectCounter)); - this.log.debug(`NEW_L2_TO_L1_MSG cnt: ${this.sideEffectCounter}`); - this.incrementSideEffectCounter(); - } - - public traceUnencryptedLog(contractAddress: AztecAddress, log: Fr[]) { - if (this.unencryptedLogs.length >= MAX_UNENCRYPTED_LOGS_PER_TX) { - throw new SideEffectLimitReachedError('unencrypted log', MAX_UNENCRYPTED_LOGS_PER_TX); - } - const ulog = new UnencryptedL2Log(contractAddress, Buffer.concat(log.map(f => f.toBuffer()))); - const basicLogHash = Fr.fromBuffer(ulog.hash()); - this.unencryptedLogs.push(ulog); - this.allUnencryptedLogs.push(ulog); - // This length is for charging DA and is checked on-chain - has to be length of log preimage + 4 bytes. - // The .length call also has a +4 but that is unrelated - this.unencryptedLogsHashes.push(new LogHash(basicLogHash, this.sideEffectCounter, new Fr(ulog.length + 4))); - this.log.debug(`NEW_UNENCRYPTED_LOG cnt: ${this.sideEffectCounter}`); - this.incrementSideEffectCounter(); - } - - public traceGetContractInstance( - contractAddress: AztecAddress, - exists: boolean, - instance: SerializableContractInstance = SerializableContractInstance.default(), - _lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(), - _lowLeafIndex: Fr = Fr.zero(), - _lowLeafPath: Fr[] = emptyNullifierPath(), - ) { - this.enforceLimitOnNullifierChecks('(contract address nullifier from GETCONTRACTINSTANCE)'); - - this.avmCircuitHints.contractInstances.items.push( - new AvmContractInstanceHint( - contractAddress, - exists, - instance.salt, - instance.deployer, - instance.contractClassId, - instance.initializationHash, - instance.publicKeys, - ), - ); - this.log.debug(`CONTRACT_INSTANCE cnt: ${this.sideEffectCounter}`); - this.incrementSideEffectCounter(); - } - - // This tracing function gets called everytime we start simulation/execution. - // This happens both when starting a new top-level trace and the start of every nested trace - // We use this to collect the AvmContractBytecodeHints - // We need to trace teh merkle tree as well here - public traceGetBytecode( - contractAddress: AztecAddress, - exists: boolean, - bytecode: Buffer = Buffer.alloc(0), - contractInstance: SerializableContractInstance = SerializableContractInstance.default(), - contractClass: ContractClassIdPreimage = { - artifactHash: Fr.zero(), - privateFunctionsRoot: Fr.zero(), - publicBytecodeCommitment: Fr.zero(), - }, - _lowLeafPreimage: NullifierLeafPreimage = NullifierLeafPreimage.empty(), - _lowLeafIndex: Fr = Fr.zero(), - _lowLeafPath: Fr[] = emptyNullifierPath(), - ) { - const instance = new AvmContractInstanceHint( - contractAddress, - exists, - contractInstance.salt, - contractInstance.deployer, - contractInstance.contractClassId, - contractInstance.initializationHash, - contractInstance.publicKeys, - ); - // We need to deduplicate the contract instances based on addresses - this.avmCircuitHints.contractBytecodeHints.items.push( - new AvmContractBytecodeHints(bytecode, instance, contractClass), - ); - this.log.debug( - `Bytecode retrieval for contract execution traced: exists=${exists}, instance=${jsonStringify(contractInstance)}`, - ); - } - - /** - * 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: PublicSideEffectTrace, - /** The execution environment of the nested call. */ - nestedEnvironment: AvmExecutionEnvironment, - /** How much gas was available for this public execution. */ - startGasLeft: Gas, - /** Bytecode used for this execution. */ - bytecode: Buffer, - /** The call's results */ - avmCallResults: AvmContractCallResult, - /** Function name for logging */ - functionName: string = 'unknown', - ) { - // TODO(4805): check if some threshold is reached for max nested calls (to unique contracts?) - // TODO(dbanks12): should emit a nullifier read request. There should be two thresholds. - // one for max unique contract calls, and another based on max nullifier reads. - // Since this trace function happens _after_ a nested call, such threshold limits must take - // place in another trace function that occurs _before_ a nested call. - const result = nestedCallTrace.toPublicFunctionCallResult( - nestedEnvironment, - startGasLeft, - bytecode, - avmCallResults.finalize(), - functionName, - ); - this.sideEffectCounter = result.endSideEffectCounter.toNumber(); - // when a nested call returns, caller accepts its updated counter - this.allUnencryptedLogs.push(...result.allUnencryptedLogs.logs); - // NOTE: eventually if the AVM circuit processes an entire enqueued call, - // this function will accept all of the nested's side effects into this instance - this.nestedExecutions.push(result); - - const gasUsed = new Gas( - result.startGasLeft.daGas - avmCallResults.gasLeft.daGas, - result.startGasLeft.l2Gas - avmCallResults.gasLeft.l2Gas, - ); - - this.publicCallRequests.push(resultToPublicCallRequest(result)); - - this.avmCircuitHints.externalCalls.items.push( - new AvmExternalCallHint( - /*success=*/ new Fr(result.reverted ? 0 : 1), - result.returnValues, - gasUsed, - result.endSideEffectCounter, - nestedEnvironment.address, - ), - ); - } - - public traceEnqueuedCall( - /** The call request from private that enqueued this call. */ - _publicCallRequest: PublicCallRequest, - /** The call's calldata */ - _calldata: Fr[], - /** Did the call revert? */ - _reverted: boolean, - ) { - throw new Error('Not implemented'); - } - - public merge(_nestedTrace: this, _reverted: boolean = false) { - throw new Error('Not implemented'); - } - - /** - * Convert this trace to a PublicExecutionResult for use externally to the simulator. - */ - public toPublicFunctionCallResult( - /** The execution environment of the nested call. */ - avmEnvironment: AvmExecutionEnvironment, - /** How much gas was available for this public execution. */ - startGasLeft: Gas, - /** Bytecode used for this execution. */ - bytecode: Buffer, - /** The call's results */ - avmCallResults: AvmFinalizedCallResult, - /** Function name for logging */ - functionName: string = 'unknown', - ): PublicFunctionCallResult { - return { - executionRequest: createPublicExecutionRequest(avmEnvironment), - - startSideEffectCounter: new Fr(this.startSideEffectCounter), - endSideEffectCounter: new Fr(this.sideEffectCounter), - startGasLeft, - endGasLeft: avmCallResults.gasLeft, - transactionFee: avmEnvironment.transactionFee, - - bytecode, - calldata: avmEnvironment.calldata, - returnValues: avmCallResults.output, - reverted: avmCallResults.reverted, - revertReason: avmCallResults.revertReason, - - contractStorageReads: this.contractStorageReads, - contractStorageUpdateRequests: this.contractStorageUpdateRequests, - noteHashReadRequests: this.noteHashReadRequests, - noteHashes: this.noteHashes, - nullifierReadRequests: this.nullifierReadRequests, - nullifierNonExistentReadRequests: this.nullifierNonExistentReadRequests, - nullifiers: this.nullifiers, - l1ToL2MsgReadRequests: this.l1ToL2MsgReadRequests, - l2ToL1Messages: this.newL2ToL1Messages, - // correct the type on these now that they are finalized (lists won't grow) - unencryptedLogs: new UnencryptedFunctionL2Logs(this.unencryptedLogs), - allUnencryptedLogs: new UnencryptedFunctionL2Logs(this.allUnencryptedLogs), - unencryptedLogsHashes: this.unencryptedLogsHashes, - - publicCallRequests: this.publicCallRequests, - nestedExecutions: this.nestedExecutions, - - avmCircuitHints: this.avmCircuitHints, - - functionName, - }; - } - - public toPublicEnqueuedCallExecutionResult( - /** The call's results */ - _avmCallResults: AvmFinalizedCallResult, - ): EnqueuedPublicCallExecutionResultWithSideEffects { - throw new Error('Not implemented'); - } - - private enforceLimitOnNullifierChecks(errorMsgOrigin: string = '') { - // NOTE: Why error if _either_ limit was reached? If user code emits either an existent or non-existent - // nullifier read request (NULLIFIEREXISTS, GETCONTRACTINSTANCE, *CALL), and one of the limits has been - // reached (MAX_NULLIFIER_NON_EXISTENT_RRS vs MAX_NULLIFIER_RRS), but not the other, we must prevent the - // sequencer from lying and saying "this nullifier exists, but MAX_NULLIFIER_RRS has been reached, so I'm - // going to skip the read request and just revert instead" when the nullifier actually doesn't exist - // (or vice versa). So, if either maximum has been reached, any nullifier-reading operation must error. - if (this.nullifierReadRequests.length >= MAX_NULLIFIER_READ_REQUESTS_PER_TX) { - throw new SideEffectLimitReachedError( - `nullifier read request ${errorMsgOrigin}`, - MAX_NULLIFIER_READ_REQUESTS_PER_TX, - ); - } - if (this.nullifierNonExistentReadRequests.length >= MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX) { - throw new SideEffectLimitReachedError( - `nullifier non-existent read request ${errorMsgOrigin}`, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_TX, - ); - } - } - - public getUnencryptedLogs(): UnencryptedL2Log[] { - throw new Error('Not implemented'); - } -} - -/** - * Helper function to create a public execution request from an AVM execution environment - */ -function createPublicExecutionRequest(avmEnvironment: AvmExecutionEnvironment): PublicExecutionRequest { - const callContext = CallContext.from({ - msgSender: avmEnvironment.sender, - contractAddress: avmEnvironment.address, - functionSelector: FunctionSelector.empty(), // TODO(#10563): Remove functionSelector in public call context - isStaticCall: avmEnvironment.isStaticCall, - }); - return new PublicExecutionRequest(callContext, avmEnvironment.calldata); -} diff --git a/yarn-project/simulator/src/public/side_effect_trace_interface.ts b/yarn-project/simulator/src/public/side_effect_trace_interface.ts index eaf2382cefd..de0c9d9aa01 100644 --- a/yarn-project/simulator/src/public/side_effect_trace_interface.ts +++ b/yarn-project/simulator/src/public/side_effect_trace_interface.ts @@ -10,7 +10,7 @@ import { import { type AztecAddress } from '@aztec/foundation/aztec-address'; import { type Fr } from '@aztec/foundation/fields'; -import { type AvmContractCallResult, type AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js'; +import { type AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js'; import { type AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; import { type EnqueuedPublicCallExecutionResultWithSideEffects, type PublicFunctionCallResult } from './execution.js'; @@ -80,20 +80,6 @@ export interface PublicSideEffectTraceInterface { lowLeafIndex?: Fr, lowLeafPath?: Fr[], ): void; - traceNestedCall( - /** The trace of the nested call. */ - nestedCallTrace: PublicSideEffectTraceInterface, - /** The execution environment of the nested call. */ - nestedEnvironment: AvmExecutionEnvironment, - /** How much gas was available for this public execution. */ - startGasLeft: Gas, - /** Bytecode used for this execution. */ - bytecode: Buffer, - /** The call's results */ - avmCallResults: AvmContractCallResult, - /** Function name */ - functionName: string, - ): void; traceEnqueuedCall( /** The call request from private that enqueued this call. */ publicCallRequest: PublicCallRequest,