From 91831351e63ff876d13ba5324211fc310e9c5f1f Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Fri, 29 Nov 2024 16:31:18 +0000 Subject: [PATCH 1/6] chore: witgen enforces limits on side effects --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 10 + .../src/barretenberg/vm/avm/trace/errors.hpp | 1 + .../vm/avm/trace/gadgets/merkle_tree.cpp | 1 + .../src/barretenberg/vm/avm/trace/helper.cpp | 4 + .../src/barretenberg/vm/avm/trace/trace.cpp | 183 ++++++++++++++++-- .../src/barretenberg/vm/avm/trace/trace.hpp | 2 + .../contracts/avm_test_contract/src/main.nr | 36 ++++ .../bb-prover/src/avm_proving.test.ts | 47 ++++- yarn-project/bb-prover/src/test/index.ts | 1 - yarn-project/bb-prover/src/test/test_avm.ts | 85 -------- .../circuits.js/src/structs/avm/avm.ts | 98 ++++++---- .../circuits.js/src/tests/factories.ts | 14 +- .../simulator/src/avm/journal/journal.ts | 9 + .../enqueued_call_side_effect_trace.test.ts | 28 +-- .../public/enqueued_call_side_effect_trace.ts | 36 ++-- .../simulator/src/public/fixtures/index.ts | 12 +- .../src/public/public_tx_simulator.ts | 4 +- .../simulator/src/public/side_effect_trace.ts | 20 +- .../src/public/transitional_adapters.ts | 15 +- 19 files changed, 395 insertions(+), 211 deletions(-) delete mode 100644 yarn-project/bb-prover/src/test/test_avm.ts diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 8f5a9809fdd..24d1f7a0da6 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -940,14 +940,24 @@ void avm_prove(const std::filesystem::path& calldata_path, // Using [0] is fine now for the top-level call, but we might need to index by address in future vinfo("bytecode size: ", avm_hints.all_contract_bytecode[0].bytecode.size()); vinfo("calldata size: ", calldata.size()); + vinfo("hints.storage_value_hints size: ", avm_hints.storage_value_hints.size()); vinfo("hints.note_hash_exists_hints size: ", avm_hints.note_hash_exists_hints.size()); vinfo("hints.nullifier_exists_hints size: ", avm_hints.nullifier_exists_hints.size()); vinfo("hints.l1_to_l2_message_exists_hints size: ", avm_hints.l1_to_l2_message_exists_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()); + vinfo("hints.storage_read_hints size: ", avm_hints.storage_read_hints.size()); + vinfo("hints.storage_write_hints size: ", avm_hints.storage_write_hints.size()); + vinfo("hints.nullifier_read_hints size: ", avm_hints.nullifier_read_hints.size()); + vinfo("hints.nullifier_write_hints size: ", avm_hints.nullifier_write_hints.size()); + 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("initializing crs with size: ", avm_trace::Execution::SRS_SIZE); init_bn254_crs(avm_trace::Execution::SRS_SIZE); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/errors.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/errors.hpp index e31d486e502..0e755eabe39 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/errors.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/errors.hpp @@ -18,6 +18,7 @@ enum class AvmError : uint32_t { CONTRACT_INST_MEM_UNKNOWN, RADIX_OUT_OF_BOUNDS, DUPLICATE_NULLIFIER, + SIDE_EFFECT_LIMIT_REACHED, }; } // namespace bb::avm_trace diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/merkle_tree.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/merkle_tree.cpp index 00171489efa..de1cad1ed37 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/merkle_tree.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/merkle_tree.cpp @@ -58,6 +58,7 @@ bool AvmMerkleTreeTraceBuilder::unconstrained_check_membership(const FF& leaf_va const FF& root) { FF computed_root = unconstrained_compute_root_from_path(leaf_value, leaf_index, path); + info("computed root: ", computed_root); // If the computed root is the same as the expected then the leaf is a member return computed_root == root; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp index e40a90129d5..d46220ea40e 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/helper.cpp @@ -127,6 +127,10 @@ std::string to_name(AvmError error) return "CONTRACT INSTANCE MEMBER UNKNOWN"; case AvmError::RADIX_OUT_OF_BOUNDS: return "RADIX OUT OF BOUNDS"; + case AvmError::DUPLICATE_NULLIFIER: + return "DUPLICATE NULLIFIER"; + case AvmError::SIDE_EFFECT_LIMIT_REACHED: + return "SIDE EFFECT LIMIT REACHED"; default: throw std::runtime_error("Invalid error type"); break; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index ecd740ca9ba..dbe2a07698a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -36,6 +36,7 @@ #include "barretenberg/vm/avm/trace/helper.hpp" #include "barretenberg/vm/avm/trace/opcode.hpp" #include "barretenberg/vm/avm/trace/trace.hpp" +#include "barretenberg/vm/aztec_constants.hpp" #include "barretenberg/vm/stats.hpp" namespace bb::avm_trace { @@ -2613,10 +2614,24 @@ AvmError AvmTraceBuilder::op_sload(uint8_t indirect, uint32_t slot_offset, uint3 AvmError AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint32_t slot_offset) { // We keep the first encountered error + AvmError error = AvmError::NO_ERROR; auto clk = static_cast(main_trace.size()) + 1; - // We keep the first encountered error - AvmError error = AvmError::NO_ERROR; + if (storage_write_counter >= MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX) { + error = AvmError::SIDE_EFFECT_LIMIT_REACHED; + auto row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(static_cast(!is_ok(error))), + .main_pc = pc, + .main_sel_op_sstore = FF(1), + }; + gas_trace_builder.constrain_gas(clk, OpCode::SSTORE); + main_trace.push_back(row); + pc += Deserialization::get_pc_increment(OpCode::SSTORE); + return error; + } + auto [resolved_addrs, res_error] = Addressing<2>::fromWire(indirect, call_ptr).resolve({ src_offset, slot_offset }, mem_trace_builder); auto [resolved_src, resolved_slot] = resolved_addrs; @@ -2662,6 +2677,7 @@ AvmError AvmTraceBuilder::op_sstore(uint8_t indirect, uint32_t src_offset, uint3 .main_ind_addr_a = read_a.indirect_address, .main_internal_return_ptr = internal_return_ptr, .main_mem_addr_a = read_a.direct_address, // direct address incremented at end of the loop + .main_op_err = FF(static_cast(!is_ok(error))), .main_pc = pc, .main_r_in_tag = static_cast(AvmMemoryTag::FF), .main_sel_mem_op_a = 1, @@ -2780,8 +2796,25 @@ AvmError AvmTraceBuilder::op_note_hash_exists(uint8_t indirect, AvmError AvmTraceBuilder::op_emit_note_hash(uint8_t indirect, uint32_t note_hash_offset) { + // We keep the first encountered error + AvmError error = AvmError::NO_ERROR; auto const clk = static_cast(main_trace.size()) + 1; + if (note_hash_write_counter >= MAX_NOTE_HASHES_PER_TX) { + error = AvmError::SIDE_EFFECT_LIMIT_REACHED; + auto row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(static_cast(!is_ok(error))), + .main_pc = pc, + .main_sel_op_emit_note_hash = FF(1), + }; + gas_trace_builder.constrain_gas(clk, OpCode::EMITNOTEHASH); + main_trace.push_back(row); + pc += Deserialization::get_pc_increment(OpCode::EMITNOTEHASH); + return error; + } + AppendTreeHint note_hash_write_hint = execution_hints.note_hash_write_hints.at(note_hash_write_counter++); // We first check that the index is currently empty auto insertion_index = static_cast(intermediate_tree_snapshots.note_hash_tree.size); @@ -2797,8 +2830,12 @@ AvmError AvmTraceBuilder::op_emit_note_hash(uint8_t indirect, uint32_t note_hash intermediate_tree_snapshots.note_hash_tree.root = new_root; intermediate_tree_snapshots.note_hash_tree.size++; - auto [row, error] = create_kernel_output_opcode(indirect, clk, note_hash_offset); + auto [row, output_error] = create_kernel_output_opcode(indirect, clk, note_hash_offset); + if (is_ok(error)) { + error = output_error; + } row.main_sel_op_emit_note_hash = FF(1); + row.main_op_err = FF(static_cast(!is_ok(error))); // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::EMITNOTEHASH); @@ -2921,34 +2958,100 @@ AvmError AvmTraceBuilder::op_nullifier_exists(uint8_t indirect, AvmError AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier_offset) { + // We keep the first encountered error + AvmError error = AvmError::NO_ERROR; auto const clk = static_cast(main_trace.size()) + 1; - auto [row, error] = create_kernel_output_opcode(indirect, clk, nullifier_offset); + if (nullifier_write_counter >= MAX_NULLIFIERS_PER_TX) { + error = AvmError::SIDE_EFFECT_LIMIT_REACHED; + auto row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(static_cast(!is_ok(error))), + .main_pc = pc, + .main_sel_op_emit_nullifier = FF(1), + }; + gas_trace_builder.constrain_gas(clk, OpCode::EMITNULLIFIER); + main_trace.push_back(row); + pc += Deserialization::get_pc_increment(OpCode::EMITNULLIFIER); + return error; + } + + auto [row, output_error] = create_kernel_output_opcode(indirect, clk, nullifier_offset); row.main_sel_op_emit_nullifier = FF(1); + if (is_ok(error)) { + error = output_error; + } + info("before merkles"); // Do merkle check FF nullifier_value = row.main_ia; FF siloed_nullifier = AvmMerkleTreeTraceBuilder::unconstrained_silo_nullifier( current_public_call_request.contract_address, nullifier_value); + info("siloed, getting read hint ", nullifier_read_counter); // This is a little bit fragile - but we use the fact that if we traced a nullifier that already exists (which is // invalid), we would have stored it under a read hint. - NullifierReadTreeHint nullifier_read_hint = execution_hints.nullifier_read_hints.at(nullifier_read_counter); - bool is_update = merkle_tree_trace_builder.perform_nullifier_read(clk, - nullifier_read_hint.low_leaf_preimage, - nullifier_read_hint.low_leaf_index, - nullifier_read_hint.low_leaf_sibling_path, - intermediate_tree_snapshots.nullifier_tree.root); + // NullifierReadTreeHint nullifier_read_hint = execution_hints.nullifier_read_hints.at(nullifier_read_counter); + // info("got hint, performing read"); + // bool is_update = merkle_tree_trace_builder.perform_nullifier_read(clk, + // nullifier_read_hint.low_leaf_preimage, + // nullifier_read_hint.low_leaf_index, + // nullifier_read_hint.low_leaf_sibling_path, + // intermediate_tree_snapshots.nullifier_tree.root); + info("0writing... getting write hint ", nullifier_write_counter); + // This is a non-membership proof which means our insertion is valid + NullifierWriteTreeHint nullifier_write_hint = execution_hints.nullifier_write_hints.at(nullifier_write_counter++); + // bool is_update = merkle_tree_trace_builder.perform_nullifier_read(clk, + // nullifier_write_hint.low_leaf_membership.low_leaf_preimage, + // nullifier_write_hint.low_leaf_membership.low_leaf_index, + // nullifier_write_hint.low_leaf_membership.low_leaf_sibling_path, + // intermediate_tree_snapshots.nullifier_tree.root); + // if the hinted low-leaf skips the target nullifier, it does not exist + // if the hinted low-leaf points to the target nullifier, it already exists which means this would be an "update" + // which is disallowed, so we need to prove the hinted leaf's membership which serves as a proof of the + // target nullifier's non-membership + bool is_update = siloed_nullifier == nullifier_write_hint.low_leaf_membership.low_leaf_preimage.next_nullifier; if (is_update) { - // If we are in this branch, then the nullifier already exists in the tree - // WE NEED TO RAISE AN ERROR FLAG HERE - for now we do nothing, except increment the counter - + // hinted nullifier skips target nullifier + // prove non membership of the target nullifier by proving membership of the hinted low-leaf + info("is update"); + bool exists = merkle_tree_trace_builder.perform_nullifier_read( + clk, + nullifier_write_hint.low_leaf_membership.low_leaf_preimage, + nullifier_write_hint.low_leaf_membership.low_leaf_index, + nullifier_write_hint.low_leaf_membership.low_leaf_sibling_path, + intermediate_tree_snapshots.nullifier_tree.root); + // if hinted low-leaf that skips the nullifier fails membership check, bad hint! + ASSERT(exists); nullifier_read_counter++; - error = AvmError::DUPLICATE_NULLIFIER; + if (is_ok(error)) { + error = AvmError::DUPLICATE_NULLIFIER; + } } else { - // This is a non-membership proof which means our insertion is valid - NullifierWriteTreeHint nullifier_write_hint = - execution_hints.nullifier_write_hints.at(nullifier_write_counter++); + info("low leaf preimage nullifier: ", nullifier_write_hint.low_leaf_membership.low_leaf_preimage.nullifier); + info("low leaf preimage next_nullifier: ", + nullifier_write_hint.low_leaf_membership.low_leaf_preimage.next_nullifier); + info("low leaf preimage next_index: ", nullifier_write_hint.low_leaf_membership.low_leaf_preimage.next_index); + info("low leaf index: ", nullifier_write_hint.low_leaf_membership.low_leaf_index); + info("low leaf sibling path: ["); + for (auto node : nullifier_write_hint.low_leaf_membership.low_leaf_sibling_path) { + info("\t", node); + } + info("]"); + info("insertion path: ["); + for (auto node : nullifier_write_hint.insertion_path) { + info("\t", node); + } + info("]"); + info("siloed nullifier: ", siloed_nullifier); + info("intermediate_tree_snapshots.nullifier_tree.size: ", intermediate_tree_snapshots.nullifier_tree.size); + info("intermediate_tree_snapshots.nullifier_tree.root: ", intermediate_tree_snapshots.nullifier_tree.root); + // info("writing... getting write hint ", nullifier_write_counter); + //// This is a non-membership proof which means our insertion is valid + // NullifierWriteTreeHint nullifier_write_hint = + // execution_hints.nullifier_write_hints.at(nullifier_write_counter++); + info("not update. performing nullifier append"); FF new_root = merkle_tree_trace_builder.perform_nullifier_append( clk, nullifier_write_hint.low_leaf_membership.low_leaf_preimage, @@ -2958,11 +3061,15 @@ AvmError AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier intermediate_tree_snapshots.nullifier_tree.size, nullifier_write_hint.insertion_path, intermediate_tree_snapshots.nullifier_tree.root); + info("new_root: ", new_root); intermediate_tree_snapshots.nullifier_tree.root = new_root; intermediate_tree_snapshots.nullifier_tree.size++; + info("done with append"); } + row.main_op_err = FF(static_cast(!is_ok(error))); + // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::EMITNULLIFIER); @@ -2972,6 +3079,7 @@ AvmError AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier side_effect_counter++; pc += Deserialization::get_pc_increment(OpCode::EMITNULLIFIER); + info("done opcode"); return error; } @@ -3192,6 +3300,21 @@ AvmError AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log AvmError error = AvmError::NO_ERROR; auto const clk = static_cast(main_trace.size()) + 1; + if (unencrypted_log_write_counter >= MAX_UNENCRYPTED_LOGS_PER_TX) { + error = AvmError::SIDE_EFFECT_LIMIT_REACHED; + auto row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(static_cast(!is_ok(error))), + .main_pc = pc, + .main_sel_op_emit_unencrypted_log = FF(1), + }; + gas_trace_builder.constrain_gas(clk, OpCode::EMITUNENCRYPTEDLOG); + main_trace.push_back(row); + pc += Deserialization::get_pc_increment(OpCode::EMITUNENCRYPTEDLOG); + return error; + } + // FIXME: read (and constrain) log_size_offset auto [resolved_addrs, res_error] = Addressing<2>::fromWire(indirect, call_ptr).resolve({ log_offset, log_size_offset }, mem_trace_builder); @@ -3289,14 +3412,38 @@ AvmError AvmTraceBuilder::op_emit_unencrypted_log(uint8_t indirect, uint32_t log AvmError AvmTraceBuilder::op_emit_l2_to_l1_msg(uint8_t indirect, uint32_t recipient_offset, uint32_t content_offset) { + // We keep the first encountered error + AvmError error = AvmError::NO_ERROR; auto const clk = static_cast(main_trace.size()) + 1; + if (l2_to_l1_msg_write_counter >= MAX_L2_TO_L1_MSGS_PER_TX) { + error = AvmError::SIDE_EFFECT_LIMIT_REACHED; + auto row = Row{ + .main_clk = clk, + .main_internal_return_ptr = internal_return_ptr, + .main_op_err = FF(static_cast(!is_ok(error))), + .main_pc = pc, + .main_sel_op_emit_l2_to_l1_msg = FF(1), + }; + gas_trace_builder.constrain_gas(clk, OpCode::SENDL2TOL1MSG); + main_trace.push_back(row); + pc += Deserialization::get_pc_increment(OpCode::SENDL2TOL1MSG); + return error; + } + l2_to_l1_msg_write_counter++; + // Note: unorthodox order - as seen in L2ToL1Message struct in TS - auto [row, error] = create_kernel_output_opcode_with_metadata( + auto [row, output_error] = create_kernel_output_opcode_with_metadata( indirect, clk, content_offset, AvmMemoryTag::FF, recipient_offset, AvmMemoryTag::FF); + + if (is_ok(error)) { + error = output_error; + } + // Wtite to output // kernel_trace_builder.op_emit_l2_to_l1_msg(clk, side_effect_counter, row.main_ia, row.main_ib); row.main_sel_op_emit_l2_to_l1_msg = FF(1); + row.main_op_err = FF(static_cast(!is_ok(error))); // Constrain gas cost gas_trace_builder.constrain_gas(clk, OpCode::SENDL2TOL1MSG); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index aed311ee443..fd257ac772b 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -269,8 +269,10 @@ class AvmTraceBuilder { uint32_t nullifier_read_counter = 0; uint32_t nullifier_write_counter = 0; uint32_t l1_to_l2_msg_read_counter = 0; + uint32_t l2_to_l1_msg_write_counter = 0; uint32_t storage_read_counter = 0; uint32_t storage_write_counter = 0; + uint32_t unencrypted_log_write_counter = 0; // These exist due to testing only. bool range_check_required = true; diff --git a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr index 93c07de02a2..78edfb1d6f4 100644 --- a/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/avm_test_contract/src/main.nr @@ -473,6 +473,42 @@ contract AvmTest { context.push_nullifier(nullifier); } + #[public] + fn n_storage_writes(num: u32) { + for i in 0..num { + context.push_nullifier(i as Field); + storage.map.at(AztecAddress::from_field(i as Field)).write(i); + } + } + + #[public] + fn n_new_note_hashes(num: u32) { + for i in 0..num { + context.push_note_hash(i as Field); + } + } + + #[public] + fn n_new_nullifiers(num: u32) { + for i in 0..num { + context.push_nullifier(i as Field); + } + } + + #[public] + fn n_new_l2_to_l1_msgs(num: u32) { + for i in 0..num { + context.message_portal(EthAddress::from_field(i as Field), i as Field) + } + } + + #[public] + fn n_new_unencrypted_logs(num: u32) { + for i in 0..num { + context.emit_unencrypted_log(/*message=*/ [i as Field]); + } + } + // Use the standard context interface to check for a nullifier #[public] fn nullifier_exists(nullifier: Field) -> bool { diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index 3e0ae84cf22..7840d5707ba 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -1,4 +1,4 @@ -import { VerificationKeyData } from '@aztec/circuits.js'; +import { MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, VerificationKeyData } from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { simulateAvmTestContractGenerateCircuitInputs } from '@aztec/simulator/public/fixtures'; @@ -10,17 +10,54 @@ import path from 'path'; import { type BBSuccess, BB_RESULT, generateAvmProof, verifyAvmProof } from './bb/execute.js'; import { extractAvmVkData } from './verification_key/verification_key_data.js'; +const TIMEOUT = 180_000; + describe('AVM WitGen, proof generation and verification', () => { it('Should prove and verify bulk_testing', async () => { await proveAndVerifyAvmTestContract( 'bulk_testing', - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x)), + /*calldata=*/ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x)), + ); + }, TIMEOUT); + it('Should prove and verify test that performs too many storage writes and reverts', async () => { + await proveAndVerifyAvmTestContract( + 'n_storage_writes', + /*calldata=*/ [new Fr(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX+1)], + /*expectRevert=*/ true, + ); + }, TIMEOUT); + it('Should prove and verify test that creates too many note hashes and reverts', async () => { + await proveAndVerifyAvmTestContract( + 'n_new_note_hashes', + /*calldata=*/ [new Fr(MAX_NOTE_HASHES_PER_TX+1)], + /*expectRevert=*/ true, + ); + }, TIMEOUT); + it('Should prove and verify test that creates too many nullifiers and reverts', async () => { + await proveAndVerifyAvmTestContract( + 'n_new_nullifiers', + /*calldata=*/ [new Fr(MAX_NULLIFIERS_PER_TX+1)], + /*expectRevert=*/ true, + ); + }, TIMEOUT); + it('Should prove and verify test that creates too many l2tol1 messages and reverts', async () => { + await proveAndVerifyAvmTestContract( + 'n_new_l2_to_l1_msgs', + /*calldata=*/ [new Fr(MAX_L2_TO_L1_MSGS_PER_TX+1)], + /*expectRevert=*/ true, + ); + }, TIMEOUT); + it('Should prove and verify test that creates too many unencrypted logs and reverts', async () => { + await proveAndVerifyAvmTestContract( + 'n_new_unencrypted_logs', + /*calldata=*/ [new Fr(MAX_UNENCRYPTED_LOGS_PER_TX+1)], + /*expectRevert=*/ true, ); - }, 180_000); + }, TIMEOUT); }); -async function proveAndVerifyAvmTestContract(functionName: string, calldata: Fr[] = []) { - const avmCircuitInputs = await simulateAvmTestContractGenerateCircuitInputs(functionName, calldata); +async function proveAndVerifyAvmTestContract(functionName: string, calldata: Fr[] = [], expectRevert = false) { + const avmCircuitInputs = await simulateAvmTestContractGenerateCircuitInputs(functionName, calldata, expectRevert); const internalLogger = createDebugLogger('aztec:avm-proving-test'); const logger = (msg: string, _data?: any) => internalLogger.verbose(msg); diff --git a/yarn-project/bb-prover/src/test/index.ts b/yarn-project/bb-prover/src/test/index.ts index 555536e8cb7..3f84ad27da1 100644 --- a/yarn-project/bb-prover/src/test/index.ts +++ b/yarn-project/bb-prover/src/test/index.ts @@ -1,3 +1,2 @@ export * from './test_circuit_prover.js'; export * from './test_verifier.js'; -export * from './test_avm.js'; diff --git a/yarn-project/bb-prover/src/test/test_avm.ts b/yarn-project/bb-prover/src/test/test_avm.ts deleted file mode 100644 index 4cbac8bb1c4..00000000000 --- a/yarn-project/bb-prover/src/test/test_avm.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { - AztecAddress, - ContractStorageRead, - ContractStorageUpdateRequest, - Gas, - GlobalVariables, - Header, - L2ToL1Message, - LogHash, - MAX_ENQUEUED_CALLS_PER_CALL, - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, - MAX_L2_TO_L1_MSGS_PER_CALL, - MAX_NOTE_HASHES_PER_CALL, - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NULLIFIERS_PER_CALL, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - MAX_UNENCRYPTED_LOGS_PER_CALL, - NoteHash, - Nullifier, - PublicCircuitPublicInputs, - PublicInnerCallRequest, - ReadRequest, - RevertCode, - TreeLeafReadRequest, -} from '@aztec/circuits.js'; -import { computeVarArgsHash } from '@aztec/circuits.js/hash'; -import { padArrayEnd } from '@aztec/foundation/collection'; -import { type PublicFunctionCallResult } from '@aztec/simulator'; - -// TODO: pub somewhere more usable - copied from abstract phase manager -export function getPublicInputs(result: PublicFunctionCallResult): PublicCircuitPublicInputs { - return PublicCircuitPublicInputs.from({ - callContext: result.executionRequest.callContext, - proverAddress: AztecAddress.ZERO, - argsHash: computeVarArgsHash(result.executionRequest.args), - noteHashes: padArrayEnd(result.noteHashes, NoteHash.empty(), MAX_NOTE_HASHES_PER_CALL), - nullifiers: padArrayEnd(result.nullifiers, Nullifier.empty(), MAX_NULLIFIERS_PER_CALL), - l2ToL1Msgs: padArrayEnd(result.l2ToL1Messages, L2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_CALL), - startSideEffectCounter: result.startSideEffectCounter, - endSideEffectCounter: result.endSideEffectCounter, - returnsHash: computeVarArgsHash(result.returnValues), - noteHashReadRequests: padArrayEnd( - result.noteHashReadRequests, - TreeLeafReadRequest.empty(), - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - ), - nullifierReadRequests: padArrayEnd( - result.nullifierReadRequests, - ReadRequest.empty(), - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - ), - nullifierNonExistentReadRequests: padArrayEnd( - result.nullifierNonExistentReadRequests, - ReadRequest.empty(), - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, - ), - l1ToL2MsgReadRequests: padArrayEnd( - result.l1ToL2MsgReadRequests, - TreeLeafReadRequest.empty(), - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, - ), - contractStorageReads: padArrayEnd( - result.contractStorageReads, - ContractStorageRead.empty(), - MAX_PUBLIC_DATA_READS_PER_CALL, - ), - contractStorageUpdateRequests: padArrayEnd( - result.contractStorageUpdateRequests, - ContractStorageUpdateRequest.empty(), - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - ), - publicCallRequests: padArrayEnd([], PublicInnerCallRequest.empty(), MAX_ENQUEUED_CALLS_PER_CALL), - unencryptedLogsHashes: padArrayEnd(result.unencryptedLogsHashes, LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL), - historicalHeader: Header.empty(), - globalVariables: GlobalVariables.empty(), - startGasLeft: Gas.from(result.startGasLeft), - endGasLeft: Gas.from(result.endGasLeft), - transactionFee: result.transactionFee, - // TODO(@just-mitch): need better mapping from simulator to revert code. - revertCode: result.reverted ? RevertCode.APP_LOGIC_REVERTED : RevertCode.OK, - }); -} diff --git a/yarn-project/circuits.js/src/structs/avm/avm.ts b/yarn-project/circuits.js/src/structs/avm/avm.ts index 30c37a7b132..f31d3b16f71 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.ts @@ -13,6 +13,7 @@ import { PublicCircuitPublicInputs } from '../public_circuit_public_inputs.js'; import { Vector } from '../shared.js'; import { NullifierLeafPreimage } from '../trees/nullifier_leaf.js'; import { AvmCircuitPublicInputs } from './avm_circuit_public_inputs.js'; +import { createDebugLogger } from '@aztec/foundation/log'; export class AvmEnqueuedCallHint { public readonly contractAddress: AztecAddress; @@ -520,6 +521,12 @@ export class AvmNullifierWriteTreeHint { * */ constructor(public lowLeafRead: AvmNullifierReadTreeHint, public _insertionPath: Fr[]) { this.insertionPath = new Vector(_insertionPath); + console.log(`constr:david:lowLeafPreimage.nullifier: ${this.lowLeafRead.lowLeafPreimage.nullifier}`); + console.log(`constr:david:lowLeafPreimage.nextNullifier: ${this.lowLeafRead.lowLeafPreimage.nextNullifier}`); + console.log(`constr:david:lowLeafPreimage.nextIndex: ${this.lowLeafRead.lowLeafPreimage.nextIndex}`); + console.log(`constr:david:lowLeafIndex: ${this.lowLeafRead.lowLeafIndex}`); + console.log(`constr:david:lowLeafPath: ${JSON.stringify(this.lowLeafRead.lowLeafSiblingPath.items)}}`); + console.log(`constr:david:insertionPath: ${JSON.stringify(this.insertionPath)}}`); } /** @@ -561,6 +568,12 @@ export class AvmNullifierWriteTreeHint { * @returns An array of fields. */ static getFields(fields: FieldsOf) { + console.log(`david:lowLeafPreimage.nullifier: ${fields.lowLeafRead.lowLeafPreimage.nullifier}`); + console.log(`david:lowLeafPreimage.nextNullifier: ${fields.lowLeafRead.lowLeafPreimage.nextNullifier}`); + console.log(`david:lowLeafPreimage.nextIndex: ${fields.lowLeafRead.lowLeafPreimage.nextIndex}`); + console.log(`david:lowLeafIndex: ${fields.lowLeafRead.lowLeafIndex}`); + console.log(`david:lowLeafPath: ${JSON.stringify(fields.lowLeafRead.lowLeafSiblingPath.items)}}`); + console.log(`david:insertionPath: ${JSON.stringify(fields.insertionPath)}}`); return [...AvmNullifierReadTreeHint.getFields(fields.lowLeafRead), fields.insertionPath] as const; } @@ -851,13 +864,13 @@ export class AvmExecutionHints { public readonly contractInstances: Vector; public readonly contractBytecodeHints: Vector; - public readonly storageReadRequest: Vector; - public readonly storageUpdateRequest: Vector; - public readonly nullifierReadRequest: Vector; - public readonly nullifierWriteHints: Vector; - public readonly noteHashReadRequest: Vector; - public readonly noteHashWriteRequest: Vector; - public readonly l1ToL2MessageReadRequest: Vector; + public readonly publicDataReads: Vector; + public readonly publicDataWrites: Vector; + public readonly nullifierReads: Vector; + public readonly nullifierWrites: Vector; + public readonly noteHashReads: Vector; + public readonly noteHashWrites: Vector; + public readonly l1ToL2MessageReads: Vector; constructor( enqueuedCalls: AvmEnqueuedCallHint[], @@ -868,13 +881,13 @@ export class AvmExecutionHints { externalCalls: AvmExternalCallHint[], contractInstances: AvmContractInstanceHint[], contractBytecodeHints: AvmContractBytecodeHints[], - storageReadRequest: AvmPublicDataReadTreeHint[], - storageUpdateRequest: AvmPublicDataWriteTreeHint[], - nullifierReadRequest: AvmNullifierReadTreeHint[], - nullifierWriteHints: AvmNullifierWriteTreeHint[], - noteHashReadRequest: AvmAppendTreeHint[], - noteHashWriteRequest: AvmAppendTreeHint[], - l1ToL2MessageReadRequest: AvmAppendTreeHint[], + publicDataReads: AvmPublicDataReadTreeHint[], + publicDataWrites: AvmPublicDataWriteTreeHint[], + nullifierReads: AvmNullifierReadTreeHint[], + nullifierWrites: AvmNullifierWriteTreeHint[], + noteHashReads: AvmAppendTreeHint[], + noteHashWrites: AvmAppendTreeHint[], + l1ToL2MessageReads: AvmAppendTreeHint[], ) { this.enqueuedCalls = new Vector(enqueuedCalls); this.storageValues = new Vector(storageValues); @@ -884,14 +897,13 @@ export class AvmExecutionHints { this.externalCalls = new Vector(externalCalls); this.contractInstances = new Vector(contractInstances); this.contractBytecodeHints = new Vector(contractBytecodeHints); - this.storageReadRequest = new Vector(storageReadRequest); - this.storageUpdateRequest = new Vector(storageUpdateRequest); - this.noteHashReadRequest = new Vector(noteHashReadRequest); - this.nullifierReadRequest = new Vector(nullifierReadRequest); - this.nullifierWriteHints = new Vector(nullifierWriteHints); - this.noteHashReadRequest = new Vector(noteHashReadRequest); - this.noteHashWriteRequest = new Vector(noteHashWriteRequest); - this.l1ToL2MessageReadRequest = new Vector(l1ToL2MessageReadRequest); + this.publicDataReads = new Vector(publicDataReads); + this.publicDataWrites = new Vector(publicDataWrites); + this.nullifierReads = new Vector(nullifierReads); + this.nullifierWrites = new Vector(nullifierWrites); + this.noteHashReads = new Vector(noteHashReads); + this.noteHashWrites = new Vector(noteHashWrites); + this.l1ToL2MessageReads = new Vector(l1ToL2MessageReads); } /** @@ -932,13 +944,13 @@ export class AvmExecutionHints { this.externalCalls.items.length == 0 && this.contractInstances.items.length == 0 && this.contractBytecodeHints.items.length == 0 && - this.storageReadRequest.items.length == 0 && - this.storageUpdateRequest.items.length == 0 && - this.nullifierReadRequest.items.length == 0 && - this.nullifierWriteHints.items.length == 0 && - this.noteHashReadRequest.items.length == 0 && - this.noteHashWriteRequest.items.length == 0 && - this.l1ToL2MessageReadRequest.items.length == 0 + this.publicDataReads.items.length == 0 && + this.publicDataWrites.items.length == 0 && + this.nullifierReads.items.length == 0 && + this.nullifierWrites.items.length == 0 && + this.noteHashReads.items.length == 0 && + this.noteHashWrites.items.length == 0 && + this.l1ToL2MessageReads.items.length == 0 ); } @@ -958,13 +970,13 @@ export class AvmExecutionHints { fields.externalCalls.items, fields.contractInstances.items, fields.contractBytecodeHints.items, - fields.storageReadRequest.items, - fields.storageUpdateRequest.items, - fields.nullifierReadRequest.items, - fields.nullifierWriteHints.items, - fields.noteHashReadRequest.items, - fields.noteHashWriteRequest.items, - fields.l1ToL2MessageReadRequest.items, + fields.publicDataReads.items, + fields.publicDataWrites.items, + fields.nullifierReads.items, + fields.nullifierWrites.items, + fields.noteHashReads.items, + fields.noteHashWrites.items, + fields.l1ToL2MessageReads.items, ); } @@ -984,13 +996,13 @@ export class AvmExecutionHints { fields.externalCalls, fields.contractInstances, fields.contractBytecodeHints, - fields.storageReadRequest, - fields.storageUpdateRequest, - fields.nullifierReadRequest, - fields.nullifierWriteHints, - fields.noteHashReadRequest, - fields.noteHashWriteRequest, - fields.l1ToL2MessageReadRequest, + fields.publicDataReads, + fields.publicDataWrites, + fields.nullifierReads, + fields.nullifierWrites, + fields.noteHashReads, + fields.noteHashWrites, + fields.l1ToL2MessageReads, ] as const; } diff --git a/yarn-project/circuits.js/src/tests/factories.ts b/yarn-project/circuits.js/src/tests/factories.ts index 1fce585ae3b..7e5806736db 100644 --- a/yarn-project/circuits.js/src/tests/factories.ts +++ b/yarn-project/circuits.js/src/tests/factories.ts @@ -1404,13 +1404,13 @@ export function makeAvmExecutionHints( externalCalls: makeVector(baseLength + 4, makeAvmExternalCallHint, seed + 0x4600), contractInstances: makeVector(baseLength + 5, makeAvmContractInstanceHint, seed + 0x4700), contractBytecodeHints: makeVector(baseLength + 6, makeAvmBytecodeHints, seed + 0x4800), - storageReadRequest: makeVector(baseLength + 7, makeAvmStorageReadTreeHints, seed + 0x4900), - storageUpdateRequest: makeVector(baseLength + 8, makeAvmStorageUpdateTreeHints, seed + 0x4a00), - nullifierReadRequest: makeVector(baseLength + 9, makeAvmNullifierReadTreeHints, seed + 0x4b00), - nullifierWriteHints: makeVector(baseLength + 10, makeAvmNullifierInsertionTreeHints, seed + 0x4c00), - noteHashReadRequest: makeVector(baseLength + 11, makeAvmTreeHints, seed + 0x4d00), - noteHashWriteRequest: makeVector(baseLength + 12, makeAvmTreeHints, seed + 0x4e00), - l1ToL2MessageReadRequest: makeVector(baseLength + 13, makeAvmTreeHints, seed + 0x4f00), + publicDataReads: makeVector(baseLength + 7, makeAvmStorageReadTreeHints, seed + 0x4900), + publicDataWrites: makeVector(baseLength + 8, makeAvmStorageUpdateTreeHints, seed + 0x4a00), + nullifierReads: makeVector(baseLength + 9, makeAvmNullifierReadTreeHints, seed + 0x4b00), + nullifierWrites: makeVector(baseLength + 10, makeAvmNullifierInsertionTreeHints, seed + 0x4c00), + noteHashReads: makeVector(baseLength + 11, makeAvmTreeHints, seed + 0x4d00), + noteHashWrites: makeVector(baseLength + 12, makeAvmTreeHints, seed + 0x4e00), + l1ToL2MessageReads: makeVector(baseLength + 13, makeAvmTreeHints, seed + 0x4f00), ...overrides, }); } diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 9a3ffa5273a..d588f67201c 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -379,6 +379,9 @@ export class AvmPersistableStateManager { // Cache pending nullifiers for later access await this.nullifiers.append(siloedNullifier); // We append the new nullifier + this.log.debug( + `Nullifier tree root before insertion ${this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE)!.getRoot()}`, + ); const appendResult = await this.merkleTrees.appendNullifier(siloedNullifier); this.log.debug( `Nullifier tree root after insertion ${this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE)!.getRoot()}`, @@ -387,6 +390,12 @@ export class AvmPersistableStateManager { const lowLeafIndex = appendResult.lowWitness.index; const lowLeafPath = appendResult.lowWitness.siblingPath; const insertionPath = appendResult.insertionPath; + this.log.debug(`J:lowLeafPreimage.nullifier: ${lowLeafPreimage.nullifier}`); + this.log.debug(`J:lowLeafPreimage.nextNullifier: ${lowLeafPreimage.nextNullifier}`); + this.log.debug(`J:lowLeafPreimage.nextIndex: ${lowLeafPreimage.nextIndex}`); + this.log.debug(`J:lowLeafIndex: ${lowLeafIndex}`); + this.log.debug(`J:lowLeafPath: ${JSON.stringify(lowLeafPath)}}`); + this.log.debug(`J:insertionPath: ${JSON.stringify(insertionPath)}}`); this.trace.traceNewNullifier( siloedNullifier, lowLeafPreimage, 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 6f84f4de2ad..d21f38dee71 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 @@ -59,7 +59,7 @@ describe('Enqueued-call Side Effect Trace', () => { expect(trace.getCounter()).toBe(startCounterPlus1); const expected = new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, siblingPath); - expect(trace.getAvmCircuitHints().storageReadRequest.items).toEqual([expected]); + expect(trace.getAvmCircuitHints().publicDataReads.items).toEqual([expected]); }); it('Should trace storage writes', () => { @@ -84,14 +84,14 @@ describe('Enqueued-call Side Effect Trace', () => { const readHint = new AvmPublicDataReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafSiblingPath); const expectedHint = new AvmPublicDataWriteTreeHint(readHint, newLeafPreimage, siblingPath); - expect(trace.getAvmCircuitHints().storageUpdateRequest.items).toEqual([expectedHint]); + expect(trace.getAvmCircuitHints().publicDataWrites.items).toEqual([expectedHint]); }); it('Should trace note hash checks', () => { const exists = true; trace.traceNoteHashCheck(address, utxo, leafIndex, exists, siblingPath); const expected = new AvmAppendTreeHint(leafIndex, utxo, siblingPath); - expect(trace.getAvmCircuitHints().noteHashReadRequest.items).toEqual([expected]); + expect(trace.getAvmCircuitHints().noteHashReads.items).toEqual([expected]); }); it('Should trace note hashes', () => { @@ -102,7 +102,7 @@ describe('Enqueued-call Side Effect Trace', () => { expect(trace.getSideEffects().noteHashes).toEqual(expected); const expectedHint = new AvmAppendTreeHint(leafIndex, utxo, siblingPath); - expect(trace.getAvmCircuitHints().noteHashWriteRequest.items).toEqual([expectedHint]); + expect(trace.getAvmCircuitHints().noteHashWrites.items).toEqual([expectedHint]); }); it('Should trace nullifier checks', () => { @@ -112,7 +112,7 @@ describe('Enqueued-call Side Effect Trace', () => { expect(trace.getCounter()).toBe(startCounterPlus1); const expected = new AvmNullifierReadTreeHint(lowLeafPreimage, leafIndex, siblingPath); - expect(trace.getAvmCircuitHints().nullifierReadRequest.items).toEqual([expected]); + expect(trace.getAvmCircuitHints().nullifierReads.items).toEqual([expected]); }); it('Should trace nullifiers', () => { @@ -125,14 +125,14 @@ describe('Enqueued-call Side Effect Trace', () => { const readHint = new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafSiblingPath); const expectedHint = new AvmNullifierWriteTreeHint(readHint, siblingPath); - expect(trace.getAvmCircuitHints().nullifierWriteHints.items).toEqual([expectedHint]); + expect(trace.getAvmCircuitHints().nullifierWrites.items).toEqual([expectedHint]); }); it('Should trace L1ToL2 Message checks', () => { const exists = true; trace.traceL1ToL2MessageCheck(address, utxo, leafIndex, exists, siblingPath); const expected = new AvmAppendTreeHint(leafIndex, utxo, siblingPath); - expect(trace.getAvmCircuitHints().l1ToL2MessageReadRequest.items).toEqual([expected]); + expect(trace.getAvmCircuitHints().l1ToL2MessageReads.items).toEqual([expected]); }); it('Should trace new L2ToL1 messages', () => { @@ -321,13 +321,13 @@ describe('Enqueued-call Side Effect Trace', () => { 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.storageReadRequest.items).toEqual(childHints.storageReadRequest.items); - expect(parentHints.storageUpdateRequest.items).toEqual(childHints.storageUpdateRequest.items); - expect(parentHints.nullifierReadRequest.items).toEqual(childHints.nullifierReadRequest.items); - expect(parentHints.nullifierWriteHints.items).toEqual(childHints.nullifierWriteHints.items); - expect(parentHints.noteHashReadRequest.items).toEqual(childHints.noteHashReadRequest.items); - expect(parentHints.noteHashWriteRequest.items).toEqual(childHints.noteHashWriteRequest.items); - expect(parentHints.l1ToL2MessageReadRequest.items).toEqual(childHints.l1ToL2MessageReadRequest.items); + expect(parentHints.publicDataReads.items).toEqual(childHints.publicDataReads.items); + expect(parentHints.publicDataWrites.items).toEqual(childHints.publicDataWrites.items); + expect(parentHints.nullifierReads.items).toEqual(childHints.nullifierReads.items); + expect(parentHints.nullifierWrites.items).toEqual(childHints.nullifierWrites.items); + expect(parentHints.noteHashReads.items).toEqual(childHints.noteHashReads.items); + expect(parentHints.noteHashWrites.items).toEqual(childHints.noteHashWrites.items); + expect(parentHints.l1ToL2MessageReads.items).toEqual(childHints.l1ToL2MessageReads.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 84e85adcd64..5729cc5898c 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 @@ -179,14 +179,14 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.avmCircuitHints.contractInstances.items.push(...forkedTrace.avmCircuitHints.contractInstances.items); this.avmCircuitHints.contractBytecodeHints.items.push(...forkedTrace.avmCircuitHints.contractBytecodeHints.items); - this.avmCircuitHints.storageReadRequest.items.push(...forkedTrace.avmCircuitHints.storageReadRequest.items); - this.avmCircuitHints.storageUpdateRequest.items.push(...forkedTrace.avmCircuitHints.storageUpdateRequest.items); - this.avmCircuitHints.nullifierReadRequest.items.push(...forkedTrace.avmCircuitHints.nullifierReadRequest.items); - this.avmCircuitHints.nullifierWriteHints.items.push(...forkedTrace.avmCircuitHints.nullifierWriteHints.items); - this.avmCircuitHints.noteHashReadRequest.items.push(...forkedTrace.avmCircuitHints.noteHashReadRequest.items); - this.avmCircuitHints.noteHashWriteRequest.items.push(...forkedTrace.avmCircuitHints.noteHashWriteRequest.items); - this.avmCircuitHints.l1ToL2MessageReadRequest.items.push( - ...forkedTrace.avmCircuitHints.l1ToL2MessageReadRequest.items, + this.avmCircuitHints.publicDataReads.items.push(...forkedTrace.avmCircuitHints.publicDataReads.items); + this.avmCircuitHints.publicDataWrites.items.push(...forkedTrace.avmCircuitHints.publicDataWrites.items); + this.avmCircuitHints.nullifierReads.items.push(...forkedTrace.avmCircuitHints.nullifierReads.items); + this.avmCircuitHints.nullifierWrites.items.push(...forkedTrace.avmCircuitHints.nullifierWrites.items); + this.avmCircuitHints.noteHashReads.items.push(...forkedTrace.avmCircuitHints.noteHashReads.items); + this.avmCircuitHints.noteHashWrites.items.push(...forkedTrace.avmCircuitHints.noteHashWrites.items); + this.avmCircuitHints.l1ToL2MessageReads.items.push( + ...forkedTrace.avmCircuitHints.l1ToL2MessageReads.items, ); } @@ -211,7 +211,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI assert(leafPreimage.value.equals(value), 'Value mismatch when tracing in public data write'); } - this.avmCircuitHints.storageReadRequest.items.push(new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, path)); + this.avmCircuitHints.publicDataReads.items.push(new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, path)); this.log.debug(`SLOAD cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`); this.incrementSideEffectCounter(); } @@ -245,7 +245,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI // New hinting const readHint = new AvmPublicDataReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath); - this.avmCircuitHints.storageUpdateRequest.items.push( + this.avmCircuitHints.publicDataWrites.items.push( new AvmPublicDataWriteTreeHint(readHint, newLeafPreimage, insertionPath), ); @@ -264,7 +264,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI path: Fr[] = emptyNoteHashPath(), ) { // New Hinting - this.avmCircuitHints.noteHashReadRequest.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path)); + 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) } @@ -282,7 +282,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI //const siloedNoteHash = siloNoteHash(contractAddress, noteHash); this.noteHashes.push(new NoteHash(noteHash, this.sideEffectCounter).scope(contractAddress)); this.log.debug(`NEW_NOTE_HASH cnt: ${this.sideEffectCounter}`); - this.avmCircuitHints.noteHashWriteRequest.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path)); + this.avmCircuitHints.noteHashWrites.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path)); this.incrementSideEffectCounter(); } @@ -293,7 +293,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI lowLeafIndex: Fr = Fr.zero(), lowLeafPath: Fr[] = emptyNullifierPath(), ) { - this.avmCircuitHints.nullifierReadRequest.items.push( + this.avmCircuitHints.nullifierReads.items.push( new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath), ); this.log.debug(`NULLIFIER_EXISTS cnt: ${this.sideEffectCounter}`); @@ -314,8 +314,14 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.nullifiers.push(new Nullifier(siloedNullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO)); const lowLeafReadHint = new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath); - this.avmCircuitHints.nullifierWriteHints.items.push(new AvmNullifierWriteTreeHint(lowLeafReadHint, insertionPath)); + this.avmCircuitHints.nullifierWrites.items.push(new AvmNullifierWriteTreeHint(lowLeafReadHint, insertionPath)); this.log.debug(`NEW_NULLIFIER cnt: ${this.sideEffectCounter}`); + this.log.debug(`ET:lowLeafPreimage.nullifier: ${lowLeafPreimage.nullifier}`); + this.log.debug(`ET:lowLeafPreimage.nextNullifier: ${lowLeafPreimage.nextNullifier}`); + this.log.debug(`ET:lowLeafPreimage.nextIndex: ${lowLeafPreimage.nextIndex}`); + this.log.debug(`ET:lowLeafIndex: ${lowLeafIndex}`); + this.log.debug(`ET:lowLeafPath: ${JSON.stringify(lowLeafPath)}}`); + this.log.debug(`ET:insertionPath: ${JSON.stringify(insertionPath)}}`); this.incrementSideEffectCounter(); } @@ -327,7 +333,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI _exists: boolean, path: Fr[] = emptyL1ToL2MessagePath(), ) { - this.avmCircuitHints.l1ToL2MessageReadRequest.items.push(new AvmAppendTreeHint(msgLeafIndex, msgHash, path)); + this.avmCircuitHints.l1ToL2MessageReads.items.push(new AvmAppendTreeHint(msgLeafIndex, msgHash, path)); } public traceNewL2ToL1Message(contractAddress: AztecAddress, recipient: Fr, content: Fr) { diff --git a/yarn-project/simulator/src/public/fixtures/index.ts b/yarn-project/simulator/src/public/fixtures/index.ts index d4c69bfd9ae..be511c9a358 100644 --- a/yarn-project/simulator/src/public/fixtures/index.ts +++ b/yarn-project/simulator/src/public/fixtures/index.ts @@ -33,14 +33,10 @@ import { MerkleTrees } from '@aztec/world-state'; import { getAvmTestContractBytecode, getAvmTestContractFunctionSelector } from '../../avm/fixtures/index.js'; -/** - * If assertionErrString is set, we expect a (non exceptional halting) revert due to a failing assertion and - * we check that the revert reason error contains this string. However, the circuit must correctly prove the - * execution. - */ export async function simulateAvmTestContractGenerateCircuitInputs( functionName: string, calldata: Fr[] = [], + expectRevert: boolean = false, assertionErrString?: string, ): Promise { const sender = AztecAddress.random(); @@ -79,13 +75,15 @@ export async function simulateAvmTestContractGenerateCircuitInputs( const avmResult = await simulator.simulate(tx); - if (assertionErrString == undefined) { + if (!expectRevert) { expect(avmResult.revertCode.isOK()).toBe(true); } else { // Explicit revert when an assertion failed. expect(avmResult.revertCode.isOK()).toBe(false); expect(avmResult.revertReason).toBeDefined(); - expect(avmResult.revertReason?.getMessage()).toContain(assertionErrString); + if (assertionErrString !== undefined) { + expect(avmResult.revertReason?.getMessage()).toContain(assertionErrString); + } } const avmCircuitInputs: AvmCircuitInputs = avmResult.avmProvingRequest.inputs; diff --git a/yarn-project/simulator/src/public/public_tx_simulator.ts b/yarn-project/simulator/src/public/public_tx_simulator.ts index 7cf250cc1d5..78ef5a54bb4 100644 --- a/yarn-project/simulator/src/public/public_tx_simulator.ts +++ b/yarn-project/simulator/src/public/public_tx_simulator.ts @@ -387,7 +387,7 @@ export class PublicTxSimulator { public async insertNonRevertiblesFromPrivate(context: PublicTxContext) { const stateManager = context.state.getActiveStateManager(); try { - await stateManager.writeSiloedNullifiersFromPrivate(context.nonRevertibleAccumulatedDataFromPrivate.nullifiers); + //await stateManager.writeSiloedNullifiersFromPrivate(context.nonRevertibleAccumulatedDataFromPrivate.nullifiers); } catch (e) { if (e instanceof NullifierCollisionError) { throw new NullifierCollisionError( @@ -406,7 +406,7 @@ export class PublicTxSimulator { context.state.fork(); const stateManager = context.state.getActiveStateManager(); try { - await stateManager.writeSiloedNullifiersFromPrivate(context.revertibleAccumulatedDataFromPrivate.nullifiers); + //await stateManager.writeSiloedNullifiersFromPrivate(context.revertibleAccumulatedDataFromPrivate.nullifiers); } catch (e) { if (e instanceof NullifierCollisionError) { throw new NullifierCollisionError( diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts index 474e3ff155d..e96fa274336 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -138,7 +138,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { ); // New hinting - this.avmCircuitHints.storageReadRequest.items.push(new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, path)); + this.avmCircuitHints.publicDataReads.items.push(new AvmPublicDataReadTreeHint(leafPreimage, leafIndex, path)); this.log.debug(`SLOAD cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`); this.incrementSideEffectCounter(); @@ -168,7 +168,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { // New hinting const readHint = new AvmPublicDataReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath); - this.avmCircuitHints.storageUpdateRequest.items.push( + this.avmCircuitHints.publicDataWrites.items.push( new AvmPublicDataWriteTreeHint(readHint, newLeafPreimage, insertionPath), ); this.log.debug(`SSTORE cnt: ${this.sideEffectCounter} val: ${value} slot: ${slot}`); @@ -193,7 +193,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { new AvmKeyValueHint(/*key=*/ new Fr(leafIndex), /*value=*/ exists ? Fr.ONE : Fr.ZERO), ); // New Hinting - this.avmCircuitHints.noteHashReadRequest.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path)); + 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) } @@ -210,7 +210,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.log.debug(`NEW_NOTE_HASH cnt: ${this.sideEffectCounter}`); // New Hinting - this.avmCircuitHints.noteHashWriteRequest.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path)); + this.avmCircuitHints.noteHashWrites.items.push(new AvmAppendTreeHint(leafIndex, noteHash, path)); this.incrementSideEffectCounter(); } @@ -237,7 +237,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { ); // New Hints - this.avmCircuitHints.nullifierReadRequest.items.push( + this.avmCircuitHints.nullifierReads.items.push( new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath), ); this.log.debug(`NULLIFIER_EXISTS cnt: ${this.sideEffectCounter}`); @@ -259,8 +259,14 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { this.nullifiers.push(new Nullifier(siloedNullifier, this.sideEffectCounter, /*noteHash=*/ Fr.ZERO)); // New hinting const lowLeafReadHint = new AvmNullifierReadTreeHint(lowLeafPreimage, lowLeafIndex, lowLeafPath); - this.avmCircuitHints.nullifierWriteHints.items.push(new AvmNullifierWriteTreeHint(lowLeafReadHint, insertionPath)); + this.avmCircuitHints.nullifierWrites.items.push(new AvmNullifierWriteTreeHint(lowLeafReadHint, insertionPath)); this.log.debug(`NEW_NULLIFIER cnt: ${this.sideEffectCounter}`); + this.log.debug(`ST:lowLeafPreimage.nullifier: ${lowLeafPreimage.nullifier}`); + this.log.debug(`ST:lowLeafPreimage.nextNullifier: ${lowLeafPreimage.nextNullifier}`); + this.log.debug(`ST:lowLeafPreimage.nextIndex: ${lowLeafPreimage.nextIndex}`); + this.log.debug(`ST:lowLeafIndex: ${lowLeafIndex}`); + this.log.debug(`ST:lowLeafPath: ${JSON.stringify(lowLeafPath)}}`); + this.log.debug(`ST:insertionPath: ${JSON.stringify(insertionPath)}}`); this.incrementSideEffectCounter(); } @@ -282,7 +288,7 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { ); // New Hinting - this.avmCircuitHints.l1ToL2MessageReadRequest.items.push(new AvmAppendTreeHint(msgLeafIndex, msgHash, path)); + 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) } diff --git a/yarn-project/simulator/src/public/transitional_adapters.ts b/yarn-project/simulator/src/public/transitional_adapters.ts index 63470f6fc18..08ea83c92b2 100644 --- a/yarn-project/simulator/src/public/transitional_adapters.ts +++ b/yarn-project/simulator/src/public/transitional_adapters.ts @@ -19,7 +19,6 @@ import { MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASHES_PER_TX, MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NULLIFIERS_PER_CALL, MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, MAX_NULLIFIER_READ_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_READS_PER_CALL, @@ -42,6 +41,8 @@ import { TreeSnapshots, countAccumulatedItems, mergeAccumulatedData, + MAX_NULLIFIERS_PER_TX, + MAX_NULLIFIERS_PER_CALL, } from '@aztec/circuits.js'; import { computeNoteHashNonce, computeUniqueNoteHash, computeVarArgsHash, siloNoteHash } from '@aztec/circuits.js/hash'; import { padArrayEnd } from '@aztec/foundation/collection'; @@ -257,19 +258,19 @@ function getPublicCircuitPublicInputs( proverAddress: AztecAddress.ZERO, argsHash: computeVarArgsHash(result.executionRequest.args), noteHashes: padArrayEnd( - result.noteHashes, + [], NoteHash.empty(), MAX_NOTE_HASHES_PER_CALL, `Too many note hashes. Got ${result.noteHashes.length} with max being ${MAX_NOTE_HASHES_PER_CALL}`, ), nullifiers: padArrayEnd( - result.nullifiers, + [], Nullifier.empty(), MAX_NULLIFIERS_PER_CALL, - `Too many nullifiers. Got ${result.nullifiers.length} with max being ${MAX_NULLIFIERS_PER_CALL}`, + `Too many nullifiers. Got ${result.nullifiers.length} with max being ${MAX_NULLIFIERS_PER_TX}`, ), l2ToL1Msgs: padArrayEnd( - result.l2ToL1Messages, + [], L2ToL1Message.empty(), MAX_L2_TO_L1_MSGS_PER_CALL, `Too many L2 to L1 messages. Got ${result.l2ToL1Messages.length} with max being ${MAX_L2_TO_L1_MSGS_PER_CALL}`, @@ -308,7 +309,7 @@ function getPublicCircuitPublicInputs( `Too many public data reads. Got ${result.contractStorageReads.length} with max being ${MAX_PUBLIC_DATA_READS_PER_CALL}`, ), contractStorageUpdateRequests: padArrayEnd( - result.contractStorageUpdateRequests, + [], ContractStorageUpdateRequest.empty(), MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, `Too many public data update requests. Got ${result.contractStorageUpdateRequests.length} with max being ${MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL}`, @@ -320,7 +321,7 @@ function getPublicCircuitPublicInputs( `Too many public call requests. Got ${result.publicCallRequests.length} with max being ${MAX_ENQUEUED_CALLS_PER_CALL}`, ), unencryptedLogsHashes: padArrayEnd( - result.unencryptedLogsHashes, + [], LogHash.empty(), MAX_UNENCRYPTED_LOGS_PER_CALL, `Too many unencrypted logs. Got ${result.unencryptedLogsHashes.length} with max being ${MAX_UNENCRYPTED_LOGS_PER_CALL}`, From 036fd925d97d5cc1a7eac62268854fa3b9b2f715 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Sat, 30 Nov 2024 19:52:57 +0000 Subject: [PATCH 2/6] cleanup --- barretenberg/cpp/src/barretenberg/bb/main.cpp | 8 --- .../barretenberg/vm/avm/trace/execution.cpp | 18 ----- .../vm/avm/trace/gadgets/merkle_tree.cpp | 5 -- .../src/barretenberg/vm/avm/trace/trace.cpp | 71 ++----------------- .../circuits.js/src/structs/avm/avm.ts | 12 ---- .../simulator/src/avm/journal/journal.ts | 6 -- .../public/enqueued_call_side_effect_trace.ts | 6 -- .../simulator/src/public/public_tx_context.ts | 6 +- .../simulator/src/public/side_effect_trace.ts | 6 -- 9 files changed, 6 insertions(+), 132 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index 944be9bb8f1..1d544434a28 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -948,14 +948,6 @@ void avm_prove(const std::filesystem::path& public_inputs_path, vinfo("hints.contract_instance_hints size: ", avm_hints.contract_instance_hints.size()); vinfo("hints.contract_bytecode_hints size: ", avm_hints.all_contract_bytecode.size()); - vinfo("hints.storage_read_hints size: ", avm_hints.storage_read_hints.size()); - vinfo("hints.storage_write_hints size: ", avm_hints.storage_write_hints.size()); - vinfo("hints.nullifier_read_hints size: ", avm_hints.nullifier_read_hints.size()); - vinfo("hints.nullifier_write_hints size: ", avm_hints.nullifier_write_hints.size()); - 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("initializing crs with size: ", avm_trace::Execution::SRS_SIZE); init_bn254_crs(avm_trace::Execution::SRS_SIZE); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index da7fa1f6c95..39e826814bf 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -281,24 +281,6 @@ std::vector Execution::gen_trace(AvmPublicInputs const& public_inputs, AvmTraceBuilder trace_builder = Execution::trace_builder_constructor(public_inputs, execution_hints, start_side_effect_counter, calldata); - // std::vector public_call_requests; - // for (const auto& setup_requests : public_inputs.public_setup_call_requests) { - // if (setup_requests.contract_address != 0) { - // public_call_requests.push_back(setup_requests); - // } - // } - // size_t setup_counter = public_call_requests.size(); - - // for (const auto& app_requests : public_inputs.public_app_logic_call_requests) { - // if (app_requests.contract_address != 0) { - // public_call_requests.push_back(app_requests); - // } - // } - //// We should not need to guard teardown, but while we are testing with handcrafted txs we do - // if (public_inputs.public_teardown_call_request.contract_address != 0) { - // public_call_requests.push_back(public_inputs.public_teardown_call_request); - // } - // Temporary spot for private non-revertible insertion std::vector siloed_nullifiers; siloed_nullifiers.insert(siloed_nullifiers.end(), diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/merkle_tree.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/merkle_tree.cpp index 4cb80ab543f..4c549157fc7 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/merkle_tree.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/gadgets/merkle_tree.cpp @@ -67,7 +67,6 @@ bool AvmMerkleTreeTraceBuilder::unconstrained_check_membership(const FF& leaf_va const FF& root) { FF computed_root = unconstrained_compute_root_from_path(leaf_value, leaf_index, path); - info("computed root: ", computed_root); // If the computed root is the same as the expected then the leaf is a member return computed_root == root; } @@ -172,8 +171,6 @@ FF AvmMerkleTreeTraceBuilder::perform_nullifier_append([[maybe_unused]] uint32_t ASSERT(is_member); return tree_snapshots.nullifier_tree.root; } - info("BEFORE tree_snapshots.nullifier_tree.root: ", tree_snapshots.nullifier_tree.root); - info("BEFORE tree_snapshots.nullifier_tree.size: ", tree_snapshots.nullifier_tree.size); // Check membership of the low leaf bool low_leaf_member = unconstrained_check_membership( low_preimage_hash, static_cast(low_index), low_path, tree_snapshots.nullifier_tree.root); @@ -198,8 +195,6 @@ FF AvmMerkleTreeTraceBuilder::perform_nullifier_append([[maybe_unused]] uint32_t // Insert the new leaf into the tree tree_snapshots.nullifier_tree.root = unconstrained_update_leaf_index(leaf_preimage_hash, index, insertion_path); tree_snapshots.nullifier_tree.size++; - info("AFTER tree_snapshots.nullifier_tree.root: ", tree_snapshots.nullifier_tree.root); - info("AFTER tree_snapshots.nullifier_tree.size: ", tree_snapshots.nullifier_tree.size); return tree_snapshots.nullifier_tree.root; } diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index 45195459f13..721cbaa8b81 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -2829,25 +2829,6 @@ AvmError AvmTraceBuilder::op_emit_note_hash(uint8_t indirect, uint32_t note_hash return error; } - // AppendTreeHint note_hash_write_hint = execution_hints.note_hash_write_hints.at(note_hash_write_counter++); - //// We first check that the index is currently empty - // auto insertion_index = static_cast(intermediate_tree_snapshots.note_hash_tree.size); - // bool insert_index_is_empty = - // AvmMerkleTreeTraceBuilder::unconstrained_check_membership(FF::zero(), - // insertion_index, - // note_hash_write_hint.sibling_path, - // intermediate_tree_snapshots.note_hash_tree.root); - // ASSERT(insert_index_is_empty); - //// Update the root with the new leaf that is appended - // FF new_root = AvmMerkleTreeTraceBuilder::unconstrained_update_leaf_index( - // note_hash_write_hint.leaf_value, insertion_index, note_hash_write_hint.sibling_path); - // intermediate_tree_snapshots.note_hash_tree.root = new_root; - // intermediate_tree_snapshots.note_hash_tree.size++; - - // auto [row, output_error] = create_kernel_output_opcode(indirect, clk, note_hash_offset); - // if (is_ok(error)) { - // error = output_error; - // } auto [row, error] = create_kernel_output_opcode(indirect, clk, note_hash_offset); row.main_sel_op_emit_note_hash = FF(1); row.main_op_err = FF(static_cast(!is_ok(error))); @@ -3008,32 +2989,16 @@ AvmError AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier error = output_error; } - info("before merkles"); // Do merkle check FF nullifier_value = row.main_ia; FF siloed_nullifier = AvmMerkleTreeTraceBuilder::unconstrained_silo_nullifier( current_public_call_request.contract_address, nullifier_value); - info("siloed, getting write hint ", nullifier_write_counter); - // This is a little bit fragile - but we use the fact that if we traced a nullifier that already exists (which is - // invalid), we would have stored it under a read hint. - // - // This is a non-membership proof which means our insertion is valid NullifierWriteTreeHint nullifier_write_hint = execution_hints.nullifier_write_hints.at(nullifier_write_counter++); - // NullifierReadTreeHint nullifier_read_hint = execution_hints.nullifier_read_hints.at(nullifier_read_counter); - // bool is_update = merkle_tree_trace_builder.perform_nullifier_read(clk, - // nullifier_read_hint.low_leaf_preimage, - // nullifier_read_hint.low_leaf_index, - // nullifier_read_hint.low_leaf_sibling_path); - // if the hinted low-leaf skips the target nullifier, it does not exist - // if the hinted low-leaf points to the target nullifier, it already exists which means this would be an "update" - // which is disallowed, so we need to prove the hinted leaf's membership which serves as a proof of the - // target nullifier's non-membership bool is_update = siloed_nullifier == nullifier_write_hint.low_leaf_membership.low_leaf_preimage.next_nullifier; if (is_update) { - // hinted nullifier skips target nullifier - // prove non membership of the target nullifier by proving membership of the hinted low-leaf - info("is update"); + // hinted low-leaf points to the target nullifier, so it already exists + // prove membership of that low-leaf, which also proves membership of the target nullifier bool exists = merkle_tree_trace_builder.perform_nullifier_read( clk, nullifier_write_hint.low_leaf_membership.low_leaf_preimage, @@ -3042,30 +3007,13 @@ AvmError AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier // if hinted low-leaf that skips the nullifier fails membership check, bad hint! ASSERT(exists); nullifier_read_counter++; + // Cannot update an existing nullifier, and cannot emit a duplicate. Error! if (is_ok(error)) { error = AvmError::DUPLICATE_NULLIFIER; } } else { - info("low leaf preimage nullifier: ", nullifier_write_hint.low_leaf_membership.low_leaf_preimage.nullifier); - info("low leaf preimage next_nullifier: ", - nullifier_write_hint.low_leaf_membership.low_leaf_preimage.next_nullifier); - info("low leaf preimage next_index: ", nullifier_write_hint.low_leaf_membership.low_leaf_preimage.next_index); - info("low leaf index: ", nullifier_write_hint.low_leaf_membership.low_leaf_index); - info("low leaf sibling path: ["); - for (auto node : nullifier_write_hint.low_leaf_membership.low_leaf_sibling_path) { - info("\t", node); - } - info("]"); - info("insertion path: ["); - for (auto node : nullifier_write_hint.insertion_path) { - info("\t", node); - } - info("]"); - info("siloed nullifier: ", siloed_nullifier); - // info("intermediate_tree_snapshots.nullifier_tree.size: ", intermediate_tree_snapshots.nullifier_tree.size); - // info("intermediate_tree_snapshots.nullifier_tree.root: ", intermediate_tree_snapshots.nullifier_tree.root); - info("writing... getting write hint ", nullifier_write_counter); - info("not update. performing nullifier append"); + // hinted low-leaf SKIPS the target nullifier, so it does NOT exist + // prove membership of the low leaf which also proves non-membership of the target nullifier merkle_tree_trace_builder.perform_nullifier_append( clk, nullifier_write_hint.low_leaf_membership.low_leaf_preimage, @@ -3086,7 +3034,6 @@ AvmError AvmTraceBuilder::op_emit_nullifier(uint8_t indirect, uint32_t nullifier side_effect_counter++; pc += Deserialization::get_pc_increment(OpCode::EMITNULLIFIER); - info("done opcode"); return error; } @@ -4499,10 +4446,6 @@ std::vector AvmTraceBuilder::finalize() // Some sanity checks // Check that the final merkle tree lines up with the public inputs TreeSnapshots tree_snapshots = merkle_tree_trace_builder.get_tree_snapshots(); - info("tree_snapshots ?= public_inputs.end.tree_snapshots"); - info(tree_snapshots.nullifier_tree.root, " == ", public_inputs.end_tree_snapshots.nullifier_tree.root); - // info("tree_snapshot: ", tree_snapshots.nullifier_tree.root); - // info(" == ", public_inputs.end_tree_snapshots); ASSERT(tree_snapshots == public_inputs.end_tree_snapshots); vinfo("range_check_required: ", range_check_required); @@ -4770,10 +4713,6 @@ std::vector AvmTraceBuilder::finalize() // Sanity check that the amount of gas consumed matches what we expect from the public inputs auto last_l2_gas_remaining = main_trace.back().main_l2_gas_remaining; auto expected_end_gas_l2 = public_inputs.gas_settings.gas_limits.l2_gas - public_inputs.end_gas_used.l2_gas; - info("gas limit l2: ", public_inputs.gas_settings.gas_limits.l2_gas); - info("public inputs end gas used: ", public_inputs.end_gas_used.l2_gas); - info("last l2 gas remaining: ", last_l2_gas_remaining); - info("expected end l2 gas: ", expected_end_gas_l2); ASSERT(last_l2_gas_remaining == expected_end_gas_l2); auto last_da_gas_remaining = main_trace.back().main_da_gas_remaining; auto expected_end_gas_da = public_inputs.gas_settings.gas_limits.da_gas - public_inputs.end_gas_used.da_gas; diff --git a/yarn-project/circuits.js/src/structs/avm/avm.ts b/yarn-project/circuits.js/src/structs/avm/avm.ts index 021af30b6e5..cafaf9c0721 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.ts @@ -521,12 +521,6 @@ export class AvmNullifierWriteTreeHint { * */ constructor(public lowLeafRead: AvmNullifierReadTreeHint, public _insertionPath: Fr[]) { this.insertionPath = new Vector(_insertionPath); - console.log(`constr:david:lowLeafPreimage.nullifier: ${this.lowLeafRead.lowLeafPreimage.nullifier}`); - console.log(`constr:david:lowLeafPreimage.nextNullifier: ${this.lowLeafRead.lowLeafPreimage.nextNullifier}`); - console.log(`constr:david:lowLeafPreimage.nextIndex: ${this.lowLeafRead.lowLeafPreimage.nextIndex}`); - console.log(`constr:david:lowLeafIndex: ${this.lowLeafRead.lowLeafIndex}`); - console.log(`constr:david:lowLeafPath: ${JSON.stringify(this.lowLeafRead.lowLeafSiblingPath.items)}}`); - console.log(`constr:david:insertionPath: ${JSON.stringify(this.insertionPath)}}`); } /** @@ -568,12 +562,6 @@ export class AvmNullifierWriteTreeHint { * @returns An array of fields. */ static getFields(fields: FieldsOf) { - console.log(`david:lowLeafPreimage.nullifier: ${fields.lowLeafRead.lowLeafPreimage.nullifier}`); - console.log(`david:lowLeafPreimage.nextNullifier: ${fields.lowLeafRead.lowLeafPreimage.nextNullifier}`); - console.log(`david:lowLeafPreimage.nextIndex: ${fields.lowLeafRead.lowLeafPreimage.nextIndex}`); - console.log(`david:lowLeafIndex: ${fields.lowLeafRead.lowLeafIndex}`); - console.log(`david:lowLeafPath: ${JSON.stringify(fields.lowLeafRead.lowLeafSiblingPath.items)}}`); - console.log(`david:insertionPath: ${JSON.stringify(fields.insertionPath)}}`); return [...AvmNullifierReadTreeHint.getFields(fields.lowLeafRead), fields.insertionPath] as const; } diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index d588f67201c..6156af3d36a 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -390,12 +390,6 @@ export class AvmPersistableStateManager { const lowLeafIndex = appendResult.lowWitness.index; const lowLeafPath = appendResult.lowWitness.siblingPath; const insertionPath = appendResult.insertionPath; - this.log.debug(`J:lowLeafPreimage.nullifier: ${lowLeafPreimage.nullifier}`); - this.log.debug(`J:lowLeafPreimage.nextNullifier: ${lowLeafPreimage.nextNullifier}`); - this.log.debug(`J:lowLeafPreimage.nextIndex: ${lowLeafPreimage.nextIndex}`); - this.log.debug(`J:lowLeafIndex: ${lowLeafIndex}`); - this.log.debug(`J:lowLeafPath: ${JSON.stringify(lowLeafPath)}}`); - this.log.debug(`J:insertionPath: ${JSON.stringify(insertionPath)}}`); this.trace.traceNewNullifier( siloedNullifier, lowLeafPreimage, 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 5729cc5898c..cc9aa1fc8a6 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 @@ -316,12 +316,6 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI 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.log.debug(`ET:lowLeafPreimage.nullifier: ${lowLeafPreimage.nullifier}`); - this.log.debug(`ET:lowLeafPreimage.nextNullifier: ${lowLeafPreimage.nextNullifier}`); - this.log.debug(`ET:lowLeafPreimage.nextIndex: ${lowLeafPreimage.nextIndex}`); - this.log.debug(`ET:lowLeafIndex: ${lowLeafIndex}`); - this.log.debug(`ET:lowLeafPath: ${JSON.stringify(lowLeafPath)}}`); - this.log.debug(`ET:insertionPath: ${JSON.stringify(insertionPath)}}`); this.incrementSideEffectCounter(); } diff --git a/yarn-project/simulator/src/public/public_tx_context.ts b/yarn-project/simulator/src/public/public_tx_context.ts index e2af976fdf3..94057597a18 100644 --- a/yarn-project/simulator/src/public/public_tx_context.ts +++ b/yarn-project/simulator/src/public/public_tx_context.ts @@ -91,7 +91,7 @@ export class PublicTxContext { const previousAccumulatedDataArrayLengths = new SideEffectArrayLengths( /*publicDataWrites*/ 0, countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.noteHashes), - 0, //countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.nullifiers), + /*nullifiers=*/ 0, countAccumulatedItems(nonRevertibleAccumulatedDataFromPrivate.l2ToL1Msgs), /*unencryptedLogsHashes*/ 0, ); @@ -313,8 +313,6 @@ export class PublicTxContext { const nullifierTree = getAppendSnaphot(MerkleTreeId.NULLIFIER_TREE); const publicDataTree = getAppendSnaphot(MerkleTreeId.PUBLIC_DATA_TREE); - this.log.debug(`CONTEXT: nullifier tree root: ${nullifierTree.root.toString()}`); - const endTreeSnapshots = new TreeSnapshots( endStateReference.l1ToL2MessageTree, noteHashTree, @@ -322,8 +320,6 @@ export class PublicTxContext { publicDataTree, ); - this.log.debug(`CONTEXT: end gas used: ${this.gasUsed.l2Gas}`); - return generateAvmCircuitPublicInputs( this.trace, this.globalVariables, diff --git a/yarn-project/simulator/src/public/side_effect_trace.ts b/yarn-project/simulator/src/public/side_effect_trace.ts index e96fa274336..8e9f93256d0 100644 --- a/yarn-project/simulator/src/public/side_effect_trace.ts +++ b/yarn-project/simulator/src/public/side_effect_trace.ts @@ -261,12 +261,6 @@ export class PublicSideEffectTrace implements PublicSideEffectTraceInterface { 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.log.debug(`ST:lowLeafPreimage.nullifier: ${lowLeafPreimage.nullifier}`); - this.log.debug(`ST:lowLeafPreimage.nextNullifier: ${lowLeafPreimage.nextNullifier}`); - this.log.debug(`ST:lowLeafPreimage.nextIndex: ${lowLeafPreimage.nextIndex}`); - this.log.debug(`ST:lowLeafIndex: ${lowLeafIndex}`); - this.log.debug(`ST:lowLeafPath: ${JSON.stringify(lowLeafPath)}}`); - this.log.debug(`ST:insertionPath: ${JSON.stringify(insertionPath)}}`); this.incrementSideEffectCounter(); } From cd3f8e6ef1daee62c5f3d8befe84326191a1bb5b Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Sat, 30 Nov 2024 20:41:18 +0000 Subject: [PATCH 3/6] fmt --- .../bb-prover/src/avm_proving.test.ts | 115 +++++++---- .../circuits.js/src/structs/avm/avm.ts | 1 - .../simulator/src/avm/journal/journal.ts | 4 +- .../public/enqueued_call_side_effect_trace.ts | 4 +- .../src/public/transitional_adapters.ts | 192 +----------------- 5 files changed, 82 insertions(+), 234 deletions(-) diff --git a/yarn-project/bb-prover/src/avm_proving.test.ts b/yarn-project/bb-prover/src/avm_proving.test.ts index 7840d5707ba..07024d57608 100644 --- a/yarn-project/bb-prover/src/avm_proving.test.ts +++ b/yarn-project/bb-prover/src/avm_proving.test.ts @@ -1,4 +1,11 @@ -import { MAX_L2_TO_L1_MSGS_PER_TX, MAX_NOTE_HASHES_PER_TX, MAX_NULLIFIERS_PER_TX, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, MAX_UNENCRYPTED_LOGS_PER_TX, VerificationKeyData } from '@aztec/circuits.js'; +import { + MAX_L2_TO_L1_MSGS_PER_TX, + MAX_NOTE_HASHES_PER_TX, + MAX_NULLIFIERS_PER_TX, + MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, + MAX_UNENCRYPTED_LOGS_PER_TX, + VerificationKeyData, +} from '@aztec/circuits.js'; import { Fr } from '@aztec/foundation/fields'; import { createDebugLogger } from '@aztec/foundation/log'; import { simulateAvmTestContractGenerateCircuitInputs } from '@aztec/simulator/public/fixtures'; @@ -13,47 +20,71 @@ import { extractAvmVkData } from './verification_key/verification_key_data.js'; const TIMEOUT = 180_000; describe('AVM WitGen, proof generation and verification', () => { - it('Should prove and verify bulk_testing', async () => { - await proveAndVerifyAvmTestContract( - 'bulk_testing', - /*calldata=*/ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x)), - ); - }, TIMEOUT); - it('Should prove and verify test that performs too many storage writes and reverts', async () => { - await proveAndVerifyAvmTestContract( - 'n_storage_writes', - /*calldata=*/ [new Fr(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX+1)], - /*expectRevert=*/ true, - ); - }, TIMEOUT); - it('Should prove and verify test that creates too many note hashes and reverts', async () => { - await proveAndVerifyAvmTestContract( - 'n_new_note_hashes', - /*calldata=*/ [new Fr(MAX_NOTE_HASHES_PER_TX+1)], - /*expectRevert=*/ true, - ); - }, TIMEOUT); - it('Should prove and verify test that creates too many nullifiers and reverts', async () => { - await proveAndVerifyAvmTestContract( - 'n_new_nullifiers', - /*calldata=*/ [new Fr(MAX_NULLIFIERS_PER_TX+1)], - /*expectRevert=*/ true, - ); - }, TIMEOUT); - it('Should prove and verify test that creates too many l2tol1 messages and reverts', async () => { - await proveAndVerifyAvmTestContract( - 'n_new_l2_to_l1_msgs', - /*calldata=*/ [new Fr(MAX_L2_TO_L1_MSGS_PER_TX+1)], - /*expectRevert=*/ true, - ); - }, TIMEOUT); - it('Should prove and verify test that creates too many unencrypted logs and reverts', async () => { - await proveAndVerifyAvmTestContract( - 'n_new_unencrypted_logs', - /*calldata=*/ [new Fr(MAX_UNENCRYPTED_LOGS_PER_TX+1)], - /*expectRevert=*/ true, - ); - }, TIMEOUT); + it( + 'Should prove and verify bulk_testing', + async () => { + await proveAndVerifyAvmTestContract( + 'bulk_testing', + /*calldata=*/ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(x => new Fr(x)), + ); + }, + TIMEOUT, + ); + it( + 'Should prove and verify test that performs too many storage writes and reverts', + async () => { + await proveAndVerifyAvmTestContract( + 'n_storage_writes', + /*calldata=*/ [new Fr(MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX + 1)], + /*expectRevert=*/ true, + ); + }, + TIMEOUT, + ); + it( + 'Should prove and verify test that creates too many note hashes and reverts', + async () => { + await proveAndVerifyAvmTestContract( + 'n_new_note_hashes', + /*calldata=*/ [new Fr(MAX_NOTE_HASHES_PER_TX + 1)], + /*expectRevert=*/ true, + ); + }, + TIMEOUT, + ); + it( + 'Should prove and verify test that creates too many nullifiers and reverts', + async () => { + await proveAndVerifyAvmTestContract( + 'n_new_nullifiers', + /*calldata=*/ [new Fr(MAX_NULLIFIERS_PER_TX + 1)], + /*expectRevert=*/ true, + ); + }, + TIMEOUT, + ); + it( + 'Should prove and verify test that creates too many l2tol1 messages and reverts', + async () => { + await proveAndVerifyAvmTestContract( + 'n_new_l2_to_l1_msgs', + /*calldata=*/ [new Fr(MAX_L2_TO_L1_MSGS_PER_TX + 1)], + /*expectRevert=*/ true, + ); + }, + TIMEOUT, + ); + it( + 'Should prove and verify test that creates too many unencrypted logs and reverts', + async () => { + await proveAndVerifyAvmTestContract( + 'n_new_unencrypted_logs', + /*calldata=*/ [new Fr(MAX_UNENCRYPTED_LOGS_PER_TX + 1)], + /*expectRevert=*/ true, + ); + }, + TIMEOUT, + ); }); async function proveAndVerifyAvmTestContract(functionName: string, calldata: Fr[] = [], expectRevert = false) { diff --git a/yarn-project/circuits.js/src/structs/avm/avm.ts b/yarn-project/circuits.js/src/structs/avm/avm.ts index cafaf9c0721..e50308e2b73 100644 --- a/yarn-project/circuits.js/src/structs/avm/avm.ts +++ b/yarn-project/circuits.js/src/structs/avm/avm.ts @@ -13,7 +13,6 @@ import { PublicCircuitPublicInputs } from '../public_circuit_public_inputs.js'; import { Vector } from '../shared.js'; import { NullifierLeafPreimage } from '../trees/nullifier_leaf.js'; import { AvmCircuitPublicInputs } from './avm_circuit_public_inputs.js'; -import { createDebugLogger } from '@aztec/foundation/log'; export class AvmEnqueuedCallHint { public readonly contractAddress: AztecAddress; diff --git a/yarn-project/simulator/src/avm/journal/journal.ts b/yarn-project/simulator/src/avm/journal/journal.ts index 6156af3d36a..15ad24709d5 100644 --- a/yarn-project/simulator/src/avm/journal/journal.ts +++ b/yarn-project/simulator/src/avm/journal/journal.ts @@ -380,7 +380,9 @@ export class AvmPersistableStateManager { await this.nullifiers.append(siloedNullifier); // We append the new nullifier this.log.debug( - `Nullifier tree root before insertion ${this.merkleTrees.treeMap.get(MerkleTreeId.NULLIFIER_TREE)!.getRoot()}`, + `Nullifier tree root before insertion ${this.merkleTrees.treeMap + .get(MerkleTreeId.NULLIFIER_TREE)! + .getRoot()}`, ); const appendResult = await this.merkleTrees.appendNullifier(siloedNullifier); this.log.debug( 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 cc9aa1fc8a6..a7e24ac5520 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 @@ -185,9 +185,7 @@ export class PublicEnqueuedCallSideEffectTrace implements PublicSideEffectTraceI this.avmCircuitHints.nullifierWrites.items.push(...forkedTrace.avmCircuitHints.nullifierWrites.items); this.avmCircuitHints.noteHashReads.items.push(...forkedTrace.avmCircuitHints.noteHashReads.items); this.avmCircuitHints.noteHashWrites.items.push(...forkedTrace.avmCircuitHints.noteHashWrites.items); - this.avmCircuitHints.l1ToL2MessageReads.items.push( - ...forkedTrace.avmCircuitHints.l1ToL2MessageReads.items, - ); + this.avmCircuitHints.l1ToL2MessageReads.items.push(...forkedTrace.avmCircuitHints.l1ToL2MessageReads.items); } public getCounter() { diff --git a/yarn-project/simulator/src/public/transitional_adapters.ts b/yarn-project/simulator/src/public/transitional_adapters.ts index a28f1f22939..09ec0094110 100644 --- a/yarn-project/simulator/src/public/transitional_adapters.ts +++ b/yarn-project/simulator/src/public/transitional_adapters.ts @@ -1,58 +1,28 @@ -import { type AvmProvingRequest, ProvingRequestType, type PublicExecutionRequest } from '@aztec/circuit-types'; import { - AvmCircuitInputs, - AvmCircuitPublicInputs, - AztecAddress, - ContractStorageRead, - ContractStorageUpdateRequest, - Fr, - Gas, + type AvmCircuitPublicInputs, + type Fr, + type Gas, type GasSettings, type GlobalVariables, - type Header, - L2ToL1Message, - LogHash, - MAX_ENQUEUED_CALLS_PER_CALL, - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, - MAX_L2_TO_L1_MSGS_PER_CALL, MAX_L2_TO_L1_MSGS_PER_TX, - MAX_NOTE_HASHES_PER_CALL, MAX_NOTE_HASHES_PER_TX, - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - MAX_PUBLIC_DATA_READS_PER_CALL, - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX, - MAX_UNENCRYPTED_LOGS_PER_CALL, - NoteHash, - Nullifier, PrivateToAvmAccumulatedData, PrivateToAvmAccumulatedDataArrayLengths, type PrivateToPublicAccumulatedData, PublicCallRequest, - PublicCircuitPublicInputs, PublicDataWrite, - PublicInnerCallRequest, - ReadRequest, - RevertCode, + type RevertCode, type StateReference, - TreeLeafReadRequest, TreeSnapshots, countAccumulatedItems, mergeAccumulatedData, - MAX_NULLIFIERS_PER_TX, - MAX_NULLIFIERS_PER_CALL, } from '@aztec/circuits.js'; -import { computeNoteHashNonce, computeUniqueNoteHash, computeVarArgsHash, siloNoteHash } from '@aztec/circuits.js/hash'; +import { computeNoteHashNonce, computeUniqueNoteHash, siloNoteHash } from '@aztec/circuits.js/hash'; import { padArrayEnd } from '@aztec/foundation/collection'; import { assertLength } from '@aztec/foundation/serialize'; -import { AvmFinalizedCallResult } from '../avm/avm_contract_call_result.js'; -import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js'; -import { type AvmPersistableStateManager } from '../avm/journal/journal.js'; import { type PublicEnqueuedCallSideEffectTrace } from './enqueued_call_side_effect_trace.js'; -import { type EnqueuedPublicCallExecutionResult, type PublicFunctionCallResult } from './execution.js'; export function generateAvmCircuitPublicInputs( trace: PublicEnqueuedCallSideEffectTrace, @@ -177,155 +147,3 @@ export function generateAvmCircuitPublicInputs( //console.log(`AvmCircuitPublicInputs:\n${inspect(avmCircuitPublicInputs)}`); return avmCircuitPublicInputs; } - -export function generateAvmProvingRequest( - real: boolean, - fnName: string, - stateManager: AvmPersistableStateManager, - historicalHeader: Header, - globalVariables: GlobalVariables, - executionRequest: PublicExecutionRequest, - result: EnqueuedPublicCallExecutionResult, - allocatedGas: Gas, - transactionFee: Fr, -): AvmProvingRequest { - const avmExecutionEnv = new AvmExecutionEnvironment( - executionRequest.callContext.contractAddress, - executionRequest.callContext.msgSender, - executionRequest.callContext.functionSelector, - /*contractCallDepth=*/ Fr.zero(), - transactionFee, - globalVariables, - executionRequest.callContext.isStaticCall, - executionRequest.args, - ); - - const avmCallResult = new AvmFinalizedCallResult(result.reverted, result.returnValues, result.endGasLeft); - - // Generate an AVM proving request - let avmProvingRequest: AvmProvingRequest; - if (real) { - const deprecatedFunctionCallResult = stateManager.trace.toPublicFunctionCallResult( - avmExecutionEnv, - /*startGasLeft=*/ allocatedGas, - Buffer.alloc(0), - avmCallResult, - fnName, - ); - const publicInputs = getPublicCircuitPublicInputs(historicalHeader, globalVariables, deprecatedFunctionCallResult); - avmProvingRequest = makeAvmProvingRequest(publicInputs, deprecatedFunctionCallResult); - } else { - avmProvingRequest = emptyAvmProvingRequest(); - } - return avmProvingRequest; -} - -function emptyAvmProvingRequest(): AvmProvingRequest { - return { - type: ProvingRequestType.PUBLIC_VM, - inputs: AvmCircuitInputs.empty(), - }; -} -function makeAvmProvingRequest(inputs: PublicCircuitPublicInputs, result: PublicFunctionCallResult): AvmProvingRequest { - return { - type: ProvingRequestType.PUBLIC_VM, - inputs: new AvmCircuitInputs( - result.functionName, - result.calldata, - inputs, - result.avmCircuitHints, - AvmCircuitPublicInputs.empty(), - ), - }; -} - -function getPublicCircuitPublicInputs( - historicalHeader: Header, - globalVariables: GlobalVariables, - result: PublicFunctionCallResult, -) { - const header = historicalHeader.clone(); // don't modify the original - header.state.partial.publicDataTree.root = Fr.zero(); // AVM doesn't check this yet - - return PublicCircuitPublicInputs.from({ - callContext: result.executionRequest.callContext, - proverAddress: AztecAddress.ZERO, - argsHash: computeVarArgsHash(result.executionRequest.args), - noteHashes: padArrayEnd( - [], - NoteHash.empty(), - MAX_NOTE_HASHES_PER_CALL, - `Too many note hashes. Got ${result.noteHashes.length} with max being ${MAX_NOTE_HASHES_PER_CALL}`, - ), - nullifiers: padArrayEnd( - [], - Nullifier.empty(), - MAX_NULLIFIERS_PER_CALL, - `Too many nullifiers. Got ${result.nullifiers.length} with max being ${MAX_NULLIFIERS_PER_TX}`, - ), - l2ToL1Msgs: padArrayEnd( - [], - L2ToL1Message.empty(), - MAX_L2_TO_L1_MSGS_PER_CALL, - `Too many L2 to L1 messages. Got ${result.l2ToL1Messages.length} with max being ${MAX_L2_TO_L1_MSGS_PER_CALL}`, - ), - startSideEffectCounter: result.startSideEffectCounter, - endSideEffectCounter: result.endSideEffectCounter, - returnsHash: computeVarArgsHash(result.returnValues), - noteHashReadRequests: padArrayEnd( - result.noteHashReadRequests, - TreeLeafReadRequest.empty(), - MAX_NOTE_HASH_READ_REQUESTS_PER_CALL, - `Too many note hash read requests. Got ${result.noteHashReadRequests.length} with max being ${MAX_NOTE_HASH_READ_REQUESTS_PER_CALL}`, - ), - nullifierReadRequests: padArrayEnd( - result.nullifierReadRequests, - ReadRequest.empty(), - MAX_NULLIFIER_READ_REQUESTS_PER_CALL, - `Too many nullifier read requests. Got ${result.nullifierReadRequests.length} with max being ${MAX_NULLIFIER_READ_REQUESTS_PER_CALL}`, - ), - nullifierNonExistentReadRequests: padArrayEnd( - result.nullifierNonExistentReadRequests, - ReadRequest.empty(), - MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL, - `Too many nullifier non-existent read requests. Got ${result.nullifierNonExistentReadRequests.length} with max being ${MAX_NULLIFIER_NON_EXISTENT_READ_REQUESTS_PER_CALL}`, - ), - l1ToL2MsgReadRequests: padArrayEnd( - result.l1ToL2MsgReadRequests, - TreeLeafReadRequest.empty(), - MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL, - `Too many L1 to L2 message read requests. Got ${result.l1ToL2MsgReadRequests.length} with max being ${MAX_L1_TO_L2_MSG_READ_REQUESTS_PER_CALL}`, - ), - contractStorageReads: padArrayEnd( - result.contractStorageReads, - ContractStorageRead.empty(), - MAX_PUBLIC_DATA_READS_PER_CALL, - `Too many public data reads. Got ${result.contractStorageReads.length} with max being ${MAX_PUBLIC_DATA_READS_PER_CALL}`, - ), - contractStorageUpdateRequests: padArrayEnd( - [], - ContractStorageUpdateRequest.empty(), - MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL, - `Too many public data update requests. Got ${result.contractStorageUpdateRequests.length} with max being ${MAX_PUBLIC_DATA_UPDATE_REQUESTS_PER_CALL}`, - ), - publicCallRequests: padArrayEnd( - result.publicCallRequests, - PublicInnerCallRequest.empty(), - MAX_ENQUEUED_CALLS_PER_CALL, - `Too many public call requests. Got ${result.publicCallRequests.length} with max being ${MAX_ENQUEUED_CALLS_PER_CALL}`, - ), - unencryptedLogsHashes: padArrayEnd( - [], - LogHash.empty(), - MAX_UNENCRYPTED_LOGS_PER_CALL, - `Too many unencrypted logs. Got ${result.unencryptedLogsHashes.length} with max being ${MAX_UNENCRYPTED_LOGS_PER_CALL}`, - ), - historicalHeader: header, - globalVariables: globalVariables, - startGasLeft: Gas.from(result.startGasLeft), - endGasLeft: Gas.from(result.endGasLeft), - transactionFee: result.transactionFee, - // TODO(@just-mitch): need better mapping from simulator to revert code. - revertCode: result.reverted ? RevertCode.APP_LOGIC_REVERTED : RevertCode.OK, - }); -} From b9580d8c80decfc5889dcc18bcc6a647462b01e2 Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Sun, 1 Dec 2024 17:14:48 +0000 Subject: [PATCH 4/6] option to disable gas assertions in avm cpp tests --- .../src/barretenberg/vm/avm/trace/trace.cpp | 18 ++++++++++-------- .../src/barretenberg/vm/avm/trace/trace.hpp | 4 ++-- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index 721cbaa8b81..eceb12456bb 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -4441,7 +4441,7 @@ AvmError AvmTraceBuilder::op_to_radix_be(uint8_t indirect, * * @return The main trace */ -std::vector AvmTraceBuilder::finalize() +std::vector AvmTraceBuilder::finalize(bool apply_public_inputs_assertions) { // Some sanity checks // Check that the final merkle tree lines up with the public inputs @@ -4710,13 +4710,15 @@ std::vector AvmTraceBuilder::finalize() gas_trace_builder.finalize(main_trace); - // Sanity check that the amount of gas consumed matches what we expect from the public inputs - auto last_l2_gas_remaining = main_trace.back().main_l2_gas_remaining; - auto expected_end_gas_l2 = public_inputs.gas_settings.gas_limits.l2_gas - public_inputs.end_gas_used.l2_gas; - ASSERT(last_l2_gas_remaining == expected_end_gas_l2); - auto last_da_gas_remaining = main_trace.back().main_da_gas_remaining; - auto expected_end_gas_da = public_inputs.gas_settings.gas_limits.da_gas - public_inputs.end_gas_used.da_gas; - ASSERT(last_da_gas_remaining == expected_end_gas_da); + if (apply_public_inputs_assertions) { + // Sanity check that the amount of gas consumed matches what we expect from the public inputs + auto last_l2_gas_remaining = main_trace.back().main_l2_gas_remaining; + auto expected_end_gas_l2 = public_inputs.gas_settings.gas_limits.l2_gas - public_inputs.end_gas_used.l2_gas; + ASSERT(last_l2_gas_remaining == expected_end_gas_l2); + auto last_da_gas_remaining = main_trace.back().main_da_gas_remaining; + auto expected_end_gas_da = public_inputs.gas_settings.gas_limits.da_gas - public_inputs.end_gas_used.da_gas; + ASSERT(last_da_gas_remaining == expected_end_gas_da); + } /********************************************************************************************** * KERNEL TRACE INCLUSION diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index 0f33377a92c..e81375144b1 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -41,7 +41,7 @@ struct RowWithError { class AvmTraceBuilder { public: - AvmTraceBuilder(AvmPublicInputs public_inputs = {}, + AvmTraceBuilder(AvmPublicInputs public_inputs, ExecutionHints execution_hints = {}, uint32_t side_effect_counter = 0, std::vector calldata = {}); @@ -221,7 +221,7 @@ class AvmTraceBuilder { uint32_t num_limbs, uint8_t output_bits); - std::vector finalize(); + std::vector finalize(bool apply_public_inputs_assertions = false); void reset(); void checkpoint_non_revertible_state(); From 22338507e0531be30cf33564c8e515322a0004ac Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Sun, 1 Dec 2024 17:16:53 +0000 Subject: [PATCH 5/6] fix --- barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index 39e826814bf..229979cabe4 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -304,8 +304,8 @@ std::vector Execution::gen_trace(AvmPublicInputs const& public_inputs, if (call_request.contract_address != 0) { public_call_requests.push_back(call_request); } + info("Beginning execution of phase ", phase, " (", public_call_requests.size(), " enqueued calls)."); } - info("Beginning execution of phase ", phase, " (", public_call_requests.size(), " enqueued calls)."); AvmError error = AvmError::NO_ERROR; for (size_t i = 0; i < public_call_requests.size(); i++) { @@ -868,7 +868,7 @@ std::vector Execution::gen_trace(AvmPublicInputs const& public_inputs, } } } - auto trace = trace_builder.finalize(); + auto trace = trace_builder.finalize(/*apply_public_inputs_assertions=*/true); show_trace_info(trace); return trace; From 9dbaef4a15049bbc2b51fc081cab959f13b3781d Mon Sep 17 00:00:00 2001 From: dbanks12 Date: Sun, 1 Dec 2024 19:44:17 +0000 Subject: [PATCH 6/6] phase enum, fix gas assertions --- .../barretenberg/vm/avm/trace/execution.cpp | 41 ++++++++++++++----- .../barretenberg/vm/avm/trace/execution.hpp | 11 ++++- .../src/barretenberg/vm/avm/trace/trace.cpp | 4 +- .../src/barretenberg/vm/avm/trace/trace.hpp | 2 +- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp index 229979cabe4..bd8e2e91186 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.cpp @@ -38,6 +38,22 @@ using namespace bb; std::filesystem::path avm_dump_trace_path; namespace bb::avm_trace { + +std::string to_name(TxExecutionPhase phase) +{ + switch (phase) { + case TxExecutionPhase::SETUP: + return "SETUP"; + case TxExecutionPhase::APP_LOGIC: + return "APP_LOGIC"; + case TxExecutionPhase::TEARDOWN: + return "TEARDOWN"; + default: + throw std::runtime_error("Invalid tx phase"); + break; + } +} + namespace { // The SRS needs to be able to accommodate the circuit subgroup size. @@ -183,7 +199,8 @@ std::tuple Execution::prove(AvmPublicInpu for (const auto& enqueued_call_hints : execution_hints.enqueued_call_hints) { calldata.insert(calldata.end(), enqueued_call_hints.calldata.begin(), enqueued_call_hints.calldata.end()); } - std::vector trace = AVM_TRACK_TIME_V("prove/gen_trace", gen_trace(public_inputs, returndata, execution_hints)); + std::vector trace = AVM_TRACK_TIME_V( + "prove/gen_trace", gen_trace(public_inputs, returndata, execution_hints, /*apply_end_gas_assertions=*/true)); if (!avm_dump_trace_path.empty()) { info("Dumping trace as CSV to: " + avm_dump_trace_path.string()); dump_trace_as_csv(trace, avm_dump_trace_path); @@ -265,7 +282,8 @@ bool Execution::verify(AvmFlavor::VerificationKey vk, HonkProof const& proof) */ std::vector Execution::gen_trace(AvmPublicInputs const& public_inputs, std::vector& returndata, - ExecutionHints const& execution_hints) + ExecutionHints const& execution_hints, + bool apply_end_gas_assertions) { vinfo("------- GENERATING TRACE -------"); @@ -295,22 +313,23 @@ std::vector Execution::gen_trace(AvmPublicInputs const& public_inputs, // Loop over all the public call requests uint8_t call_ctx = 0; - for (size_t phase = 0; phase < 3; phase++) { - auto call_requests_array = phase == 0 ? public_inputs.public_setup_call_requests - : phase == 1 ? public_inputs.public_app_logic_call_requests - : public_teardown_call_requests; + auto const phases = { TxExecutionPhase::SETUP, TxExecutionPhase::APP_LOGIC, TxExecutionPhase::TEARDOWN }; + for (auto phase : phases) { + auto call_requests_array = phase == TxExecutionPhase::SETUP ? public_inputs.public_setup_call_requests + : phase == TxExecutionPhase::APP_LOGIC ? public_inputs.public_app_logic_call_requests + : public_teardown_call_requests; std::vector public_call_requests; for (const auto& call_request : call_requests_array) { if (call_request.contract_address != 0) { public_call_requests.push_back(call_request); } - info("Beginning execution of phase ", phase, " (", public_call_requests.size(), " enqueued calls)."); } + info("Beginning execution of phase ", to_name(phase), " (", public_call_requests.size(), " enqueued calls)."); AvmError error = AvmError::NO_ERROR; for (size_t i = 0; i < public_call_requests.size(); i++) { // When we get this, it means we have done our non-revertible setup phase - if (phase == 0) { + if (phase == TxExecutionPhase::SETUP) { // Temporary spot for private revertible insertion std::vector siloed_nullifiers; siloed_nullifiers.insert( @@ -858,8 +877,8 @@ std::vector Execution::gen_trace(AvmPublicInputs const& public_inputs, } } if (!is_ok(error)) { - info("Phase ", phase, " reverted."); - if (phase == 0) { + info("Phase ", to_name(phase), " reverted."); + if (phase == TxExecutionPhase::SETUP) { info("A revert during SETUP phase halts the entire TX"); break; } else { @@ -868,7 +887,7 @@ std::vector Execution::gen_trace(AvmPublicInputs const& public_inputs, } } } - auto trace = trace_builder.finalize(/*apply_public_inputs_assertions=*/true); + auto trace = trace_builder.finalize(apply_end_gas_assertions); show_trace_info(trace); return trace; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.hpp index 840b5a690df..6573e63ab29 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/execution.hpp @@ -13,6 +13,14 @@ namespace bb::avm_trace { +enum class TxExecutionPhase : uint32_t { + SETUP, + APP_LOGIC, + TEARDOWN, +}; + +std::string to_name(TxExecutionPhase phase); + class Execution { public: static constexpr size_t SRS_SIZE = 1 << 22; @@ -31,7 +39,8 @@ class Execution { // Eventually this will be the bytecode of the dispatch function of top-level contract static std::vector gen_trace(AvmPublicInputs const& public_inputs, std::vector& returndata, - ExecutionHints const& execution_hints); + ExecutionHints const& execution_hints, + bool apply_end_gas_assertions = false); // For testing purposes only. static void set_trace_builder_constructor(TraceBuilderConstructor constructor) diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp index eceb12456bb..8181ffc2b7a 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.cpp @@ -4441,7 +4441,7 @@ AvmError AvmTraceBuilder::op_to_radix_be(uint8_t indirect, * * @return The main trace */ -std::vector AvmTraceBuilder::finalize(bool apply_public_inputs_assertions) +std::vector AvmTraceBuilder::finalize(bool apply_end_gas_assertions) { // Some sanity checks // Check that the final merkle tree lines up with the public inputs @@ -4710,7 +4710,7 @@ std::vector AvmTraceBuilder::finalize(bool apply_public_inputs_assertions) gas_trace_builder.finalize(main_trace); - if (apply_public_inputs_assertions) { + if (apply_end_gas_assertions) { // Sanity check that the amount of gas consumed matches what we expect from the public inputs auto last_l2_gas_remaining = main_trace.back().main_l2_gas_remaining; auto expected_end_gas_l2 = public_inputs.gas_settings.gas_limits.l2_gas - public_inputs.end_gas_used.l2_gas; diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp index e81375144b1..2be1f528073 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/trace/trace.hpp @@ -221,7 +221,7 @@ class AvmTraceBuilder { uint32_t num_limbs, uint8_t output_bits); - std::vector finalize(bool apply_public_inputs_assertions = false); + std::vector finalize(bool apply_end_gas_assertions = false); void reset(); void checkpoint_non_revertible_state();