diff --git a/barretenberg/cpp/src/barretenberg/api/api_avm.hpp b/barretenberg/cpp/src/barretenberg/api/api_avm.hpp index ccd4a34def90..e21e383c203e 100644 --- a/barretenberg/cpp/src/barretenberg/api/api_avm.hpp +++ b/barretenberg/cpp/src/barretenberg/api/api_avm.hpp @@ -7,13 +7,13 @@ namespace bb { extern const bool avm_enabled; /** - * @brief Writes an avm proof and corresponding (incomplete) verification key to files. + * @brief Writes an avm proof to a file. * * Communication: - * - Filesystem: The proof and vk are written to the paths output_path/proof and output_path/vk + * - Filesystem: The proof is written to the path output_path/proof * * @param inputs_path Path to the file containing the serialised avm public inputs and hints - * @param output_path Path (directory) to write the output proof and verification keys + * @param output_path Path (directory) to write the output proof */ void avm_prove(const std::filesystem::path& inputs_path, const std::filesystem::path& output_path); @@ -27,14 +27,12 @@ void avm_check_circuit(const std::filesystem::path& inputs_path); * an exit code of 0 will be returned for success and 1 for failure. * * @param proof_path Path to the file containing the serialized proof - * @param vk_path Path to the file containing the serialized verification key + * @param public_inputs_path Path to the file containing the serialized public inputs * @return true If the proof is valid * @return false If the proof is invalid */ // NOTE: The proof should NOT include the public inputs. -bool avm_verify(const std::filesystem::path& proof_path, - const std::filesystem::path& public_inputs_path, - const std::filesystem::path& vk_path); +bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::path& public_inputs_path); /** * @brief Simulates an public transaction diff --git a/barretenberg/cpp/src/barretenberg/bb/cli.cpp b/barretenberg/cpp/src/barretenberg/bb/cli.cpp index 57c30213b4a3..c9d7a6f1d070 100644 --- a/barretenberg/cpp/src/barretenberg/bb/cli.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/cli.cpp @@ -585,7 +585,6 @@ int parse_and_run_cli_command(int argc, char* argv[]) add_crs_path_option(avm_verify_command); add_avm_public_inputs_option(avm_verify_command); add_proof_path_option(avm_verify_command); - add_vk_path_option(avm_verify_command); /*************************************************************************************************************** * Subcommand: aztec_process_artifact @@ -894,7 +893,7 @@ int parse_and_run_cli_command(int argc, char* argv[]) } else if (avm_check_circuit_command->parsed()) { avm_check_circuit(avm_inputs_path); } else if (avm_verify_command->parsed()) { - return avm_verify(proof_path, avm_public_inputs_path, vk_path) ? 0 : 1; + return avm_verify(proof_path, avm_public_inputs_path) ? 0 : 1; } else if (avm_simulate_command->parsed()) { avm_simulate(avm_inputs_path); } else if (avm_write_vk_command->parsed()) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/api_avm.cpp b/barretenberg/cpp/src/barretenberg/vm2/api_avm.cpp index 294b706eb748..2252ee3731ba 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/api_avm.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/api_avm.cpp @@ -31,11 +31,10 @@ void avm_prove(const std::filesystem::path& inputs_path, const std::filesystem:: { avm2::AvmAPI avm; auto inputs = avm2::AvmAPI::ProvingInputs::from(read_file(inputs_path)); - auto [proof, vk] = avm.prove(inputs); + auto proof = avm.prove(inputs); - // NOTE: As opposed to Avm1 and other proof systems, the public inputs are NOT part of the proof. + // NOTE: As opposed to other proof systems, the public inputs are NOT part of the proof. write_file(output_path / "proof", to_buffer(proof)); - write_file(output_path / "vk", vk); print_avm_stats(); @@ -43,7 +42,7 @@ void avm_prove(const std::filesystem::path& inputs_path, const std::filesystem:: // The reasoning is that proving will always pass unless it crashes. // We want to return an exit code != 0 if the proof is invalid so that the prover client saves the inputs. info("verifying..."); - bool res = avm.verify(proof, inputs.public_inputs, vk); + bool res = avm.verify(proof, inputs.public_inputs); info("verification: ", res ? "success" : "failure"); if (!res) { throw std::runtime_error("Generated proof is invalid!!!!!"); @@ -62,16 +61,13 @@ void avm_check_circuit(const std::filesystem::path& inputs_path) } // NOTE: The proof should NOT include the public inputs. -bool avm_verify(const std::filesystem::path& proof_path, - const std::filesystem::path& public_inputs_path, - const std::filesystem::path& vk_path) +bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::path& public_inputs_path) { const auto proof = many_from_buffer(read_file(proof_path)); - std::vector vk_bytes = read_file(vk_path); auto public_inputs = avm2::PublicInputs::from(read_file(public_inputs_path)); avm2::AvmAPI avm; - bool res = avm.verify(proof, public_inputs, vk_bytes); + bool res = avm.verify(proof, public_inputs); info("verification: ", res ? "success" : "failure"); print_avm_stats(); diff --git a/barretenberg/cpp/src/barretenberg/vm2/api_avm.hpp b/barretenberg/cpp/src/barretenberg/vm2/api_avm.hpp index ccd4a34def90..e21e383c203e 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/api_avm.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/api_avm.hpp @@ -7,13 +7,13 @@ namespace bb { extern const bool avm_enabled; /** - * @brief Writes an avm proof and corresponding (incomplete) verification key to files. + * @brief Writes an avm proof to a file. * * Communication: - * - Filesystem: The proof and vk are written to the paths output_path/proof and output_path/vk + * - Filesystem: The proof is written to the path output_path/proof * * @param inputs_path Path to the file containing the serialised avm public inputs and hints - * @param output_path Path (directory) to write the output proof and verification keys + * @param output_path Path (directory) to write the output proof */ void avm_prove(const std::filesystem::path& inputs_path, const std::filesystem::path& output_path); @@ -27,14 +27,12 @@ void avm_check_circuit(const std::filesystem::path& inputs_path); * an exit code of 0 will be returned for success and 1 for failure. * * @param proof_path Path to the file containing the serialized proof - * @param vk_path Path to the file containing the serialized verification key + * @param public_inputs_path Path to the file containing the serialized public inputs * @return true If the proof is valid * @return false If the proof is invalid */ // NOTE: The proof should NOT include the public inputs. -bool avm_verify(const std::filesystem::path& proof_path, - const std::filesystem::path& public_inputs_path, - const std::filesystem::path& vk_path); +bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::path& public_inputs_path); /** * @brief Simulates an public transaction diff --git a/barretenberg/cpp/src/barretenberg/vm2/avm_api.cpp b/barretenberg/cpp/src/barretenberg/vm2/avm_api.cpp index 68b5ff218d51..30f3bc0b9851 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/avm_api.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/avm_api.cpp @@ -10,7 +10,7 @@ namespace bb::avm2 { using namespace bb::avm2::simulation; -std::pair AvmAPI::prove(const AvmAPI::ProvingInputs& inputs) +AvmAPI::AvmProof AvmAPI::prove(const AvmAPI::ProvingInputs& inputs) { // Simulate. vinfo("Simulating..."); @@ -27,10 +27,10 @@ std::pair AvmAPI::prove(const AvmA // Prove. vinfo("Proving..."); AvmProvingHelper proving_helper; - auto [proof, vk] = AVM_TRACK_TIME_V("proving/all", proving_helper.prove(std::move(trace))); + auto proof = AVM_TRACK_TIME_V("proving/all", proving_helper.prove(std::move(trace))); vinfo("Done!"); - return { std::move(proof), std::move(vk) }; + return proof; } bool AvmAPI::check_circuit(const AvmAPI::ProvingInputs& inputs) @@ -63,11 +63,11 @@ bool AvmAPI::check_circuit(const AvmAPI::ProvingInputs& inputs) return proving_helper.check_circuit(std::move(trace)); } -bool AvmAPI::verify(const AvmProof& proof, const PublicInputs& pi, const AvmVerificationKey& vk_data) +bool AvmAPI::verify(const AvmProof& proof, const PublicInputs& pi) { vinfo("Verifying..."); AvmProvingHelper proving_helper; - return AVM_TRACK_TIME_V("verifing/all", proving_helper.verify(proof, pi, vk_data)); + return AVM_TRACK_TIME_V("verifing/all", proving_helper.verify(proof, pi)); } AvmAPI::AvmVerificationKey AvmAPI::get_verification_key() diff --git a/barretenberg/cpp/src/barretenberg/vm2/avm_api.hpp b/barretenberg/cpp/src/barretenberg/vm2/avm_api.hpp index 9d178c60aac3..5372e1924e65 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/avm_api.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/avm_api.hpp @@ -15,9 +15,9 @@ class AvmAPI : public AvmSimAPI { AvmAPI() = default; // NOTE: The public inputs are NOT part of the proof. - std::pair prove(const ProvingInputs& inputs); + AvmProof prove(const ProvingInputs& inputs); bool check_circuit(const ProvingInputs& inputs); - bool verify(const AvmProof& proof, const PublicInputs& pi, const AvmVerificationKey& vk_data); + bool verify(const AvmProof& proof, const PublicInputs& pi); AvmVerificationKey get_verification_key(); }; diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.test.cpp index 4338aeb5c8a6..61322f88a3f2 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/recursive_verifier.test.cpp @@ -44,8 +44,8 @@ class AvmRecursiveTests : public ::testing::Test { const auto public_inputs_cols = public_inputs.to_columns(); InnerProver prover; - const auto [proof, vk_data] = prover.prove(std::move(trace)); - const auto verification_key = InnerProver::create_verification_key(vk_data); + const auto proof = prover.prove(std::move(trace)); + const auto verification_key = InnerProver::create_verification_key(InnerProver().get_verification_key()); InnerVerifier verifier(verification_key); const bool verified = verifier.verify_proof(proof, public_inputs_cols); diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.test.cpp index 7ae671ab52cf..fe3f4cb98225 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/verifier.test.cpp @@ -24,16 +24,16 @@ class AvmVerifierTests : public ::testing::Test { }; // Helper function to create proof. - static NativeProofResult create_proof_and_vk() + static NativeProofResult create_proof() { auto [trace, public_inputs] = testing::get_minimal_trace_with_pi(); Prover prover; auto public_inputs_cols = public_inputs.to_columns(); - const auto [proof, vk_data] = prover.prove(std::move(trace)); - const auto verification_key = prover.create_verification_key(vk_data); + const auto proof = prover.prove(std::move(trace)); + auto vk = AvmProvingHelper::create_verification_key(AvmProvingHelper().get_verification_key()); - return { proof, verification_key, public_inputs_cols }; + return { proof, vk, public_inputs_cols }; } }; @@ -43,11 +43,9 @@ TEST_F(AvmVerifierTests, GoodPublicInputs) GTEST_SKIP() << "Skipping slow test"; } - NativeProofResult proof_result = create_proof_and_vk(); - auto [proof, verification_key, public_inputs_cols] = proof_result; - - Verifier verifier(verification_key); + auto [proof, vk, public_inputs_cols] = create_proof(); + Verifier verifier(vk); const bool verified = verifier.verify_proof(proof, public_inputs_cols); ASSERT_TRUE(verified) << "native proof verification failed"; @@ -59,11 +57,10 @@ TEST_F(AvmVerifierTests, NegativeBadPublicInputs) GTEST_SKIP() << "Skipping slow test"; } - NativeProofResult proof_result = create_proof_and_vk(); - auto [proof, verification_key, public_inputs_cols] = proof_result; + auto [proof, vk, public_inputs_cols] = create_proof(); auto verify_with_corrupt_pi_col = [&](size_t col_idx) { public_inputs_cols[col_idx][5] += FF::one(); - Verifier verifier(verification_key); + Verifier verifier(vk); const bool verified = verifier.verify_proof(proof, public_inputs_cols); ASSERT_FALSE(verified) << "native proof verification succeeded, but should have failed due to corruption of public inputs col " @@ -73,7 +70,7 @@ TEST_F(AvmVerifierTests, NegativeBadPublicInputs) for (size_t col_idx = 0; col_idx < 4; col_idx++) { verify_with_corrupt_pi_col(col_idx); } - Verifier verifier(verification_key); + Verifier verifier(vk); const bool verified = verifier.verify_proof(proof, public_inputs_cols); ASSERT_TRUE(verified) << "native proof verification failed, but should have succeeded"; } @@ -81,9 +78,9 @@ TEST_F(AvmVerifierTests, NegativeBadPublicInputs) // Verify that the actual proof size matches COMPUTED_AVM_PROOF_LENGTH_IN_FIELDS TEST_F(AvmVerifierTests, ProofSizeMatchesComputedConstant) { - NativeProofResult proof_result = create_proof_and_vk(); + auto [proof, vk, public_inputs_cols] = create_proof(); - const size_t actual_proof_size = proof_result.proof.size(); + const size_t actual_proof_size = proof.size(); const size_t computed_proof_size = AvmFlavor::COMPUTED_AVM_PROOF_LENGTH_IN_FIELDS; EXPECT_EQ(actual_proof_size, computed_proof_size) diff --git a/barretenberg/cpp/src/barretenberg/vm2/dsl/avm2_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/vm2/dsl/avm2_recursion_constraint.test.cpp index 56f42dd46acb..c59dff4e3466 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/dsl/avm2_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/dsl/avm2_recursion_constraint.test.cpp @@ -52,10 +52,10 @@ class AvmRecursionConstraintTestingFunctions { auto [trace, public_inputs] = avm2::testing::get_minimal_trace_with_pi(); AvmProver prover; - auto [proof, vk_data] = prover.prove(std::move(trace)); + auto proof = prover.prove(std::move(trace)); proof.resize(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, FF::zero()); // Pad proof - const bool verified = prover.verify(proof, public_inputs, vk_data); + const bool verified = prover.verify(proof, public_inputs); EXPECT_TRUE(verified) << "native proof verification failed"; auto public_inputs_flat = PublicInputs::columns_to_flat(public_inputs.to_columns()); diff --git a/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp b/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp index d9a216762e96..ce2749023db2 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/proving_helper.cpp @@ -51,7 +51,7 @@ AvmProvingHelper::VkData AvmProvingHelper::get_verification_key() return serialized_vk; } -std::pair AvmProvingHelper::prove(tracegen::TraceContainer&& trace) +AvmProvingHelper::Proof AvmProvingHelper::prove(tracegen::TraceContainer&& trace) { auto polynomials = AVM_TRACK_TIME_V("proving/prove:compute_polynomials", constraining::compute_polynomials(trace)); auto proving_key = @@ -66,7 +66,7 @@ std::pair AvmProvingHelper::p auto proof = AVM_TRACK_TIME_V("proving/construct_proof", prover.construct_proof()); auto serialized_vk = to_buffer(verification_key->to_field_elements()); - return { std::move(proof), std::move(serialized_vk) }; + return proof; } bool AvmProvingHelper::check_circuit(tracegen::TraceContainer&& trace) @@ -97,8 +97,9 @@ bool AvmProvingHelper::check_circuit(tracegen::TraceContainer&& trace) return true; } -bool AvmProvingHelper::verify(const AvmProvingHelper::Proof& proof, const PublicInputs& pi, const VkData& vk_data) +bool AvmProvingHelper::verify(const AvmProvingHelper::Proof& proof, const PublicInputs& pi) { + auto vk_data = AVM_TRACK_TIME_V("proving/verify:get_verification_key", get_verification_key()); auto vk = AVM_TRACK_TIME_V("proving/verify:create_verification_key", create_verification_key(vk_data)); auto verifier = AVM_TRACK_TIME_V("proving/verify:construct_verifier", AvmVerifier(std::move(vk))); return AVM_TRACK_TIME_V("proving/verify_proof", verifier.verify_proof(proof, pi.to_columns())); diff --git a/barretenberg/cpp/src/barretenberg/vm2/proving_helper.hpp b/barretenberg/cpp/src/barretenberg/vm2/proving_helper.hpp index 5140e809a642..d879c79888f7 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/proving_helper.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/proving_helper.hpp @@ -16,9 +16,9 @@ class AvmProvingHelper { static std::shared_ptr create_verification_key(const VkData& vk_data); VkData get_verification_key(); - std::pair prove(tracegen::TraceContainer&& trace); + Proof prove(tracegen::TraceContainer&& trace); bool check_circuit(tracegen::TraceContainer&& trace); - bool verify(const Proof& proof, const PublicInputs& pi, const VkData& vk_data); + bool verify(const Proof& proof, const PublicInputs& pi); }; } // namespace bb::avm2 diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/bytecode_manager.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/bytecode_manager.cpp index c23b95550a01..80ee05a504b5 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/bytecode_manager.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/bytecode_manager.cpp @@ -155,7 +155,9 @@ Instruction TxBytecodeManager::read_instruction(const BytecodeId& bytecode_id, std::shared_ptr> TxBytecodeManager::get_bytecode_data(const BytecodeId& bytecode_id) { - return bytecodes.at(bytecode_id); + auto it = bytecodes.find(bytecode_id); + BB_ASSERT(it != bytecodes.end(), "Bytecode not found for the given bytecode_id"); + return it->second; } } // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/concrete_dbs.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/concrete_dbs.cpp index da800d186eb4..c55559064544 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/concrete_dbs.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/concrete_dbs.cpp @@ -17,11 +17,15 @@ std::optional ContractDB::get_contract_instance(const AztecAdd } // If we did get a contract instance, we need to prove that the address is derived from the instance. // For protocol contracts the input address is the canonical address, we need to retrieve the derived address. - AztecAddress derived_address = is_protocol_contract_address(address) - ? get_derived_address(protocol_contracts, address) - .value() /* We can assume that get_derived_address will not return a - nullopt, since we have succesfully fetched the instance.*/ - : address; + AztecAddress derived_address; + if (is_protocol_contract_address(address)) { + auto maybe_derived = get_derived_address(protocol_contracts, address); + BB_ASSERT(maybe_derived.has_value(), + "Derived address should be found for protocol contract whose instance is found"); + derived_address = maybe_derived.value(); + } else { + derived_address = address; + } address_derivation.assert_derivation(derived_address, instance.value()); return instance; } diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/context_provider.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/context_provider.cpp index bc567a5fc6ed..f4f3dc7e9d7e 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/context_provider.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/context_provider.cpp @@ -5,14 +5,14 @@ namespace bb::avm2::simulation { -std::unique_ptr ContextProvider::make_nested_context(AztecAddress address, - AztecAddress msg_sender, - FF transaction_fee, +std::unique_ptr ContextProvider::make_nested_context(const AztecAddress& address, + const AztecAddress& msg_sender, + const FF& transaction_fee, ContextInterface& parent_context, MemoryAddress cd_offset_address, uint32_t cd_size, bool is_static, - Gas gas_limit, + const Gas& gas_limit, TransactionPhase phase) { merkle_db.create_checkpoint(); // Fork DB just like in TS. @@ -41,14 +41,14 @@ std::unique_ptr ContextProvider::make_nested_context(AztecAddr cd_size); } -std::unique_ptr ContextProvider::make_enqueued_context(AztecAddress address, - AztecAddress msg_sender, - FF transaction_fee, +std::unique_ptr ContextProvider::make_enqueued_context(const AztecAddress& address, + const AztecAddress& msg_sender, + const FF& transaction_fee, std::span calldata, const FF& calldata_hash, bool is_static, - Gas gas_limit, - Gas gas_used, + const Gas& gas_limit, + const Gas& gas_used, TransactionPhase phase) { diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/context_provider.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/context_provider.hpp index d471322c1a38..f4c1f11edebd 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/context_provider.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/gadgets/context_provider.hpp @@ -35,23 +35,23 @@ class ContextProvider : public ContextProviderInterface { , side_effect_tracker(side_effect_tracker) , global_variables(global_variables) {} - std::unique_ptr make_nested_context(AztecAddress address, - AztecAddress msg_sender, - FF transaction_fee, + std::unique_ptr make_nested_context(const AztecAddress& address, + const AztecAddress& msg_sender, + const FF& transaction_fee, ContextInterface& parent_context, MemoryAddress cd_offset_address, - MemoryAddress cd_size_address, + uint32_t cd_size, bool is_static, - Gas gas_limit, + const Gas& gas_limit, TransactionPhase phase) override; - std::unique_ptr make_enqueued_context(AztecAddress address, - AztecAddress msg_sender, - FF transaction_fee, + std::unique_ptr make_enqueued_context(const AztecAddress& address, + const AztecAddress& msg_sender, + const FF& transaction_fee, std::span calldata, const FF& calldata_hash, bool is_static, - Gas gas_limit, - Gas gas_used, + const Gas& gas_limit, + const Gas& gas_used, TransactionPhase phase) override; uint32_t get_next_context_id() const override; diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/interfaces/context_provider.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/interfaces/context_provider.hpp index 0464425f4567..a1adc76d2609 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/interfaces/context_provider.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/interfaces/context_provider.hpp @@ -16,24 +16,24 @@ class ContextProviderInterface { public: virtual ~ContextProviderInterface() = default; - virtual std::unique_ptr make_nested_context(AztecAddress address, - AztecAddress msg_sender, - FF transaction_fee, + virtual std::unique_ptr make_nested_context(const AztecAddress& address, + const AztecAddress& msg_sender, + const FF& transaction_fee, ContextInterface& parent_context, MemoryAddress cd_offset_address, uint32_t cd_size, bool is_static, - Gas gas_limit, + const Gas& gas_limit, TransactionPhase phase) = 0; - virtual std::unique_ptr make_enqueued_context(AztecAddress address, - AztecAddress msg_sender, - FF transaction_fee, + virtual std::unique_ptr make_enqueued_context(const AztecAddress& address, + const AztecAddress& msg_sender, + const FF& transaction_fee, std::span calldata, const FF& calldata_hash, bool is_static, - Gas gas_limit, - Gas gas_used, + const Gas& gas_limit, + const Gas& gas_used, TransactionPhase phase) = 0; // This can be removed if we use clk for the context id diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/hinting_dbs.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/hinting_dbs.cpp index bcce6453bcad..71f55503510f 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/hinting_dbs.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/hinting_dbs.cpp @@ -264,6 +264,8 @@ SequentialInsertionResult HintingRawDB::insert_indexed_leav AppendOnlyTreeSnapshot state_after = db.get_tree_roots().public_data_tree; SequentialInsertHintPublicDataTreeKey key = { tree_info, world_state::MerkleTreeId::PUBLIC_DATA_TREE, leaf_value }; + BB_ASSERT(!result.low_leaf_witness_data.empty(), "Expected non-empty low_leaf_witness_data after insertion"); + BB_ASSERT(!result.insertion_witness_data.empty(), "Expected non-empty insertion_witness_data after insertion"); SequentialInsertHint sequential_insert_hint = { .hint_key = tree_info, .tree_id = world_state::MerkleTreeId::PUBLIC_DATA_TREE, @@ -286,6 +288,8 @@ SequentialInsertionResult HintingRawDB::insert_indexed_leave auto state_after = db.get_tree_roots().nullifier_tree; SequentialInsertHintNullifierTreeKey key = { tree_info, world_state::MerkleTreeId::NULLIFIER_TREE, leaf_value }; + BB_ASSERT(!result.low_leaf_witness_data.empty(), "Expected non-empty low_leaf_witness_data after insertion"); + BB_ASSERT(!result.insertion_witness_data.empty(), "Expected non-empty insertion_witness_data after insertion"); SequentialInsertHint sequential_insert_hint = { .hint_key = tree_info, .tree_id = world_state::MerkleTreeId::NULLIFIER_TREE, diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/indexed_memory_tree.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/indexed_memory_tree.hpp index b4b42f3956c2..a82f4dbc33ff 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/indexed_memory_tree.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/lib/indexed_memory_tree.hpp @@ -117,6 +117,7 @@ GetLowIndexedLeafResponse IndexedMemoryTree::get_low_in template IndexedLeaf IndexedMemoryTree::get_leaf_preimage(size_t leaf_index) const { + BB_ASSERT_DEBUG(leaf_index < leaves.size(), "Leaf index out of bounds"); return leaves.at(leaf_index); } diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/standalone/pure_bytecode_manager.cpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/standalone/pure_bytecode_manager.cpp index c8f8c67f97a1..514145741977 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/standalone/pure_bytecode_manager.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/standalone/pure_bytecode_manager.cpp @@ -133,7 +133,9 @@ Instruction PureTxBytecodeManager::read_instruction(const BytecodeId&, std::shared_ptr> PureTxBytecodeManager::get_bytecode_data(const BytecodeId& bytecode_id) { - return bytecodes.at(bytecode_id); + auto it = bytecodes.find(bytecode_id); + BB_ASSERT_DEBUG(it != bytecodes.end(), "Bytecode not found for the given bytecode_id"); + return it->second; } } // namespace bb::avm2::simulation diff --git a/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_context_provider.hpp b/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_context_provider.hpp index 31b4204ec1d9..fcc5e02a229f 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_context_provider.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/simulation/testing/mock_context_provider.hpp @@ -20,27 +20,27 @@ class MockContextProvider : public ContextProviderInterface { MOCK_METHOD(std::unique_ptr, make_nested_context, - (AztecAddress address, - AztecAddress msg_sender, - FF transaction_fee, + (const AztecAddress& address, + const AztecAddress& msg_sender, + const FF& transaction_fee, ContextInterface& parent_context, - MemoryAddress cd_offset_addr, - MemoryAddress cd_size_addr, + MemoryAddress cd_offset_address, + uint32_t cd_size, bool is_static, - Gas gas_limit, + const Gas& gas_limit, TransactionPhase phase), (override)); MOCK_METHOD(std::unique_ptr, make_enqueued_context, - (AztecAddress address, - AztecAddress msg_sender, - FF transaction_fee, + (const AztecAddress& address, + const AztecAddress& msg_sender, + const FF& transaction_fee, std::span calldata, const FF& calldata_hash, bool is_static, - Gas gas_limit, - Gas gas_used, + const Gas& gas_limit, + const Gas& gas_used, TransactionPhase phase), (override)); diff --git a/barretenberg/cpp/src/barretenberg/vm2/tracegen/sha256_trace.cpp b/barretenberg/cpp/src/barretenberg/vm2/tracegen/sha256_trace.cpp index dc3d317c22a1..93227ff96ce6 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/tracegen/sha256_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2/tracegen/sha256_trace.cpp @@ -434,6 +434,7 @@ void Sha256TraceBuilder::process( // If during simulation we encounter an invalid tag, it will have been the last element we retrieved // before we threw an error - so it will be the last element in the input vector. // Therefore, it is just sufficient to check the tag of the last element + BB_ASSERT(!event.input.empty(), "SHA256 input cannot be empty"); bool invalid_tag_err = event.input.back().get_tag() != MemoryTag::U32; // Note that if we encountered an invalid tag error, the row that loaded the invalid tag needs to contain diff --git a/barretenberg/cpp/src/barretenberg/vm2_stub/api_avm.cpp b/barretenberg/cpp/src/barretenberg/vm2_stub/api_avm.cpp index 6aef757923e1..5a3469d4ab5e 100644 --- a/barretenberg/cpp/src/barretenberg/vm2_stub/api_avm.cpp +++ b/barretenberg/cpp/src/barretenberg/vm2_stub/api_avm.cpp @@ -19,8 +19,7 @@ void avm_check_circuit([[maybe_unused]] const std::filesystem::path& inputs_path } bool avm_verify([[maybe_unused]] const std::filesystem::path& proof_path, - [[maybe_unused]] const std::filesystem::path& public_inputs_path, - [[maybe_unused]] const std::filesystem::path& vk_path) + [[maybe_unused]] const std::filesystem::path& public_inputs_path) { throw_or_abort("AVM is not supported in this build. Use the 'bb-avm' binary with full AVM support."); } diff --git a/barretenberg/cpp/src/barretenberg/vm2_stub/api_avm.hpp b/barretenberg/cpp/src/barretenberg/vm2_stub/api_avm.hpp index 78bf62e34462..00af7d8222f9 100644 --- a/barretenberg/cpp/src/barretenberg/vm2_stub/api_avm.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2_stub/api_avm.hpp @@ -19,9 +19,7 @@ void avm_check_circuit(const std::filesystem::path& inputs_path); /** * @brief Stub - throws runtime error if called */ -bool avm_verify(const std::filesystem::path& proof_path, - const std::filesystem::path& public_inputs_path, - const std::filesystem::path& vk_path); +bool avm_verify(const std::filesystem::path& proof_path, const std::filesystem::path& public_inputs_path); /** * @brief Stub - throws runtime error if called diff --git a/yarn-project/bb-prover/src/avm_proving_tests/avm_proving_tester.ts b/yarn-project/bb-prover/src/avm_proving_tests/avm_proving_tester.ts index cefc4a46bf94..d261b71695a5 100644 --- a/yarn-project/bb-prover/src/avm_proving_tests/avm_proving_tester.ts +++ b/yarn-project/bb-prover/src/avm_proving_tests/avm_proving_tester.ts @@ -18,14 +18,7 @@ import fs from 'node:fs/promises'; import { tmpdir } from 'node:os'; import path from 'path'; -import { - type BBResult, - type BBSuccess, - BB_RESULT, - VK_FILENAME, - generateAvmProof, - verifyAvmProof, -} from '../bb/execute.js'; +import { type BBResult, type BBSuccess, BB_RESULT, generateAvmProof, verifyAvmProof } from '../bb/execute.js'; const BB_PATH = path.resolve('../../barretenberg/cpp/build/bin/bb-avm'); @@ -193,14 +186,7 @@ export class AvmProvingTester extends PublicTxSimulationTester { return proofRes; } - return await verifyAvmProof( - BB_PATH, - this.bbWorkingDirectory, - proofRes.proofPath!, - publicInputs, - path.join(proofRes.vkDirectoryPath!, VK_FILENAME), - this.logger, - ); + return await verifyAvmProof(BB_PATH, this.bbWorkingDirectory, proofRes.proofPath!, publicInputs, this.logger); } public async proveVerify(avmCircuitInputs: AvmCircuitInputs, txLabel: string = 'unlabeledTx') { diff --git a/yarn-project/bb-prover/src/bb/execute.ts b/yarn-project/bb-prover/src/bb/execute.ts index 1f398d64ac0f..06af043b4737 100644 --- a/yarn-project/bb-prover/src/bb/execute.ts +++ b/yarn-project/bb-prover/src/bb/execute.ts @@ -353,7 +353,7 @@ export async function generateAvmProof( durationMs: duration, proofPath: join(outputPath, PROOF_FILENAME), pkPath: undefined, - vkDirectoryPath: outputPath, + vkDirectoryPath: undefined, // AVM VK is fixed in the binary. }; } // Not a great error message here but it is difficult to decipher what comes from bb @@ -372,7 +372,7 @@ export async function generateAvmProof( * @param pathToBB - The full path to the bb binary * @param proofFullPath - The full path to the proof to be verified * @param verificationKeyPath - The full path to the circuit verification key - * @param log - A logging function + * @param logger - A logger * @returns An object containing a result indication and duration taken */ export async function verifyProof( @@ -380,16 +380,25 @@ export async function verifyProof( proofFullPath: string, verificationKeyPath: string, ultraHonkFlavor: UltraHonkFlavor, - log: Logger, + logger: Logger, ): Promise { - return await verifyProofInternal( - pathToBB, + // Specify the public inputs path in the case of UH verification. + // Take proofFullPath and remove the suffix past the / to get the directory. + const proofDir = proofFullPath.substring(0, proofFullPath.lastIndexOf('/')); + const publicInputsFullPath = join(proofDir, '/public_inputs'); + logger.debug(`public inputs path: ${publicInputsFullPath}`); + + const args = [ + '-p', proofFullPath, + '-k', verificationKeyPath, - `verify`, - log, - getArgs(ultraHonkFlavor), - ); + '-i', + publicInputsFullPath, + '--disable_zk', + ...getArgs(ultraHonkFlavor), + ]; + return await verifyProofInternal(pathToBB, `verify`, args, logger); } export async function verifyAvmProof( @@ -397,7 +406,6 @@ export async function verifyAvmProof( workingDirectory: string, proofFullPath: string, publicInputs: AvmCircuitPublicInputs, - verificationKeyPath: string, logger: Logger, ): Promise { const inputsBuffer = publicInputs.serializeWithMessagePack(); @@ -414,10 +422,8 @@ export async function verifyAvmProof( return { status: BB_RESULT.FAILURE, reason: `Could not write avm inputs to ${avmInputsPath}` }; } - return await verifyProofInternal(pathToBB, proofFullPath, verificationKeyPath, 'avm_verify', logger, [ - '--avm-public-inputs', - avmInputsPath, - ]); + const args = ['-p', proofFullPath, '--avm-public-inputs', avmInputsPath]; + return await verifyProofInternal(pathToBB, 'avm_verify', args, logger); } /** @@ -425,7 +431,7 @@ export async function verifyAvmProof( * TODO(#7370) The verification keys should be supplied separately * @param pathToBB - The full path to the bb binary * @param targetPath - The path to the folder with the proof, accumulator, and verification keys - * @param log - A logging function + * @param logger - A logger * @param concurrency - The number of threads to use for the verification * @returns An object containing a result indication and duration taken */ @@ -433,7 +439,7 @@ export async function verifyChonkProof( pathToBB: string, proofPath: string, keyPath: string, - log: LogFn, + logger: Logger, concurrency = 1, ): Promise { const binaryPresent = await fs @@ -444,43 +450,25 @@ export async function verifyChonkProof( return { status: BB_RESULT.FAILURE, reason: `Failed to find bb binary at ${pathToBB}` }; } - try { - const args = ['--scheme', 'chonk', '-p', proofPath, '-k', keyPath, '-v']; - const timer = new Timer(); - const command = 'verify'; - - const result = await executeBB(pathToBB, command, args, log, concurrency); - const duration = timer.ms(); - if (result.status == BB_RESULT.SUCCESS) { - return { status: BB_RESULT.SUCCESS, durationMs: duration }; - } - // Not a great error message here but it is difficult to decipher what comes from bb - return { - status: BB_RESULT.FAILURE, - reason: `Failed to verify proof. Exit code ${result.exitCode}. Signal ${result.signal}.`, - retry: !!result.signal, - }; - } catch (error) { - return { status: BB_RESULT.FAILURE, reason: `${error}` }; - } + const args = ['--scheme', 'chonk', '-p', proofPath, '-k', keyPath, '-v']; + return await verifyProofInternal(pathToBB, 'verify', args, logger, concurrency); } /** * Used for verifying proofs with BB * @param pathToBB - The full path to the bb binary - * @param proofFullPath - The full path to the proof to be verified - * @param verificationKeyPath - The full path to the circuit verification key * @param command - The BB command to execute (verify/avm_verify) - * @param log - A logging function + * @param args - The arguments to pass to the command + * @param logger - A logger + * @param concurrency - The number of threads to use for the verification * @returns An object containing a result indication and duration taken */ async function verifyProofInternal( pathToBB: string, - proofFullPath: string, - verificationKeyPath: string, command: 'verify' | 'avm_verify', + args: string[], logger: Logger, - extraArgs: string[] = [], + concurrency?: number, ): Promise { const binaryPresent = await fs .access(pathToBB, fs.constants.R_OK) @@ -495,28 +483,12 @@ async function verifyProofInternal( }; try { - let args; - - if (command == 'verify') { - // Specify the public inputs path in the case of UH verification. - // Take proofFullPath and remove the suffix past the / to get the directory. - const proofDir = proofFullPath.substring(0, proofFullPath.lastIndexOf('/')); - const publicInputsFullPath = join(proofDir, '/public_inputs'); - logger.debug(`public inputs path: ${publicInputsFullPath}`); - - args = ['-p', proofFullPath, '-k', verificationKeyPath, '-i', publicInputsFullPath, '--disable_zk', ...extraArgs]; - } else { - args = ['-p', proofFullPath, '-k', verificationKeyPath, ...extraArgs]; - } - const loggingArg = logger.level === 'debug' || logger.level === 'trace' ? '-d' : logger.level === 'verbose' ? '-v' : ''; - if (loggingArg !== '') { - args.push(loggingArg); - } + const finalArgs = loggingArg !== '' ? [...args, loggingArg] : args; const timer = new Timer(); - const result = await executeBB(pathToBB, command, args, logFunction); + const result = await executeBB(pathToBB, command, finalArgs, logFunction, concurrency); const duration = timer.ms(); if (result.status == BB_RESULT.SUCCESS) { return { status: BB_RESULT.SUCCESS, durationMs: duration }; diff --git a/yarn-project/bb-prover/src/prover/server/bb_prover.ts b/yarn-project/bb-prover/src/prover/server/bb_prover.ts index 1c9969fe7d18..b9917ae4a0b2 100644 --- a/yarn-project/bb-prover/src/prover/server/bb_prover.ts +++ b/yarn-project/bb-prover/src/prover/server/bb_prover.ts @@ -55,10 +55,8 @@ import { NativeACVMSimulator } from '@aztec/simulator/server'; import type { AvmCircuitInputs, AvmCircuitPublicInputs } from '@aztec/stdlib/avm'; import { ProvingError } from '@aztec/stdlib/errors'; import { - type ProofAndVerificationKey, type PublicInputsAndRecursiveProof, type ServerCircuitProver, - makeProofAndVerificationKey, makePublicInputsAndRecursiveProof, } from '@aztec/stdlib/interfaces/server'; import type { ParityBasePrivateInputs, ParityPublicInputs, ParityRootPrivateInputs } from '@aztec/stdlib/parity'; @@ -86,7 +84,7 @@ import { type TxRollupPublicInputs, } from '@aztec/stdlib/rollup'; import type { CircuitProvingStats, CircuitWitnessGenerationStats } from '@aztec/stdlib/stats'; -import type { VerificationKeyData } from '@aztec/stdlib/vks'; +import { VerificationKeyData } from '@aztec/stdlib/vks'; import { Attributes, type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client'; import { promises as fs } from 'fs'; @@ -105,9 +103,8 @@ import { verifyProof, } from '../../bb/execute.js'; import type { ACVMConfig, BBConfig } from '../../config.js'; -import { type UltraHonkFlavor, getUltraHonkFlavorForCircuit } from '../../honk.js'; +import { getUltraHonkFlavorForCircuit } from '../../honk.js'; import { ProverInstrumentation } from '../../instrumentation.js'; -import { extractAvmVkData } from '../../verification_key/verification_key_data.js'; import { readProofsFromOutputDirectory } from '../proof_utils.js'; const logger = createLogger('bb-prover'); @@ -191,10 +188,10 @@ export class BBNativeRollupProver implements ServerCircuitProver { })) public async getAvmProof( inputs: AvmCircuitInputs, - ): Promise> { - const proofAndVk = await this.createAvmProof(inputs); - await this.verifyAvmProof(proofAndVk.proof.binaryProof, proofAndVk.verificationKey, inputs.publicInputs); - return proofAndVk; + ): Promise> { + const proof = await this.createAvmProof(inputs); + await this.verifyAvmProof(proof.binaryProof, inputs.publicInputs); + return proof; } public async getPublicChonkVerifierProof( @@ -530,11 +527,10 @@ export class BBNativeRollupProver implements ServerCircuitProver { private async createAvmProof( input: AvmCircuitInputs, - ): Promise> { + ): Promise> { const operation = async (bbWorkingDirectory: string) => { const provingResult = await this.generateAvmProofWithBB(input, bbWorkingDirectory); - const avmVK = await extractAvmVkData(provingResult.vkDirectoryPath!); const avmProof = await this.readAvmProofAsFields(provingResult.proofPath!); const circuitType = 'avm-circuit' as const; @@ -557,7 +553,7 @@ export class BBNativeRollupProver implements ServerCircuitProver { } satisfies CircuitProvingStats, ); - return makeProofAndVerificationKey(avmProof, avmVK); + return avmProof; }; return await this.runInDirectory(operation); } @@ -631,28 +627,19 @@ export class BBNativeRollupProver implements ServerCircuitProver { */ public async verifyProof(circuitType: ServerProtocolArtifact, proof: Proof) { const verificationKey = this.getVerificationKeyDataForCircuit(circuitType); - return await this.verifyWithKey(getUltraHonkFlavorForCircuit(circuitType), verificationKey, proof); - } - - public async verifyAvmProof( - proof: Proof, - verificationKey: VerificationKeyData, - publicInputs: AvmCircuitPublicInputs, - ) { - return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) => - verifyAvmProof(this.config.bbBinaryPath, this.config.bbWorkingDirectory, proofPath, publicInputs, vkPath, logger), + return await this.verifyInternal(proof, verificationKey, (proofPath, vkPath) => + verifyProof(this.config.bbBinaryPath, proofPath, vkPath, getUltraHonkFlavorForCircuit(circuitType), logger), ); } - public async verifyWithKey(flavor: UltraHonkFlavor, verificationKey: VerificationKeyData, proof: Proof) { - return await this.verifyWithKeyInternal(proof, verificationKey, (proofPath, vkPath) => - verifyProof(this.config.bbBinaryPath, proofPath, vkPath, flavor, logger), + public async verifyAvmProof(proof: Proof, publicInputs: AvmCircuitPublicInputs) { + return await this.verifyInternal(proof, /*verificationKey=*/ undefined, (proofPath, /*unused*/ _vkPath) => + verifyAvmProof(this.config.bbBinaryPath, this.config.bbWorkingDirectory, proofPath, publicInputs, logger), ); } - - private async verifyWithKeyInternal( + private async verifyInternal( proof: Proof, - verificationKey: { keyAsBytes: Buffer }, + verificationKey: { keyAsBytes: Buffer } | undefined, verificationFunction: (proofPath: string, vkPath: string) => Promise, ) { const operation = async (bbWorkingDirectory: string) => { @@ -660,11 +647,13 @@ export class BBNativeRollupProver implements ServerCircuitProver { const proofFileName = path.join(bbWorkingDirectory, PROOF_FILENAME); const verificationKeyPath = path.join(bbWorkingDirectory, VK_FILENAME); // TODO(https://github.com/AztecProtocol/aztec-packages/issues/13189): Put this proof parsing logic in the proof class. - await fs.writeFile(publicInputsFileName, proof.buffer.slice(0, proof.numPublicInputs * 32)); - await fs.writeFile(proofFileName, proof.buffer.slice(proof.numPublicInputs * 32)); - await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes); + await fs.writeFile(publicInputsFileName, proof.buffer.subarray(0, proof.numPublicInputs * 32)); + await fs.writeFile(proofFileName, proof.buffer.subarray(proof.numPublicInputs * 32)); + if (verificationKey !== undefined) { + await fs.writeFile(verificationKeyPath, verificationKey.keyAsBytes); + } - const result = await verificationFunction(proofFileName, verificationKeyPath!); + const result = await verificationFunction(proofFileName, verificationKeyPath); if (result.status === BB_RESULT.FAILURE) { const errorMessage = `Failed to verify proof from key!`; diff --git a/yarn-project/bb-prover/src/test/test_circuit_prover.ts b/yarn-project/bb-prover/src/test/test_circuit_prover.ts index 2863ffbd5ed1..1c430408336a 100644 --- a/yarn-project/bb-prover/src/test/test_circuit_prover.ts +++ b/yarn-project/bb-prover/src/test/test_circuit_prover.ts @@ -1,6 +1,5 @@ import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, - AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED, NESTED_RECURSIVE_PROOF_LENGTH, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, RECURSIVE_PROOF_LENGTH, @@ -51,14 +50,18 @@ import type { WitnessMap } from '@aztec/noir-types'; import { type CircuitSimulator, WASMSimulatorWithBlobs, emitCircuitSimulationStats } from '@aztec/simulator/server'; import type { AvmCircuitInputs } from '@aztec/stdlib/avm'; import { - type ProofAndVerificationKey, type PublicInputsAndRecursiveProof, type ServerCircuitProver, - makeProofAndVerificationKey, makePublicInputsAndRecursiveProof, } from '@aztec/stdlib/interfaces/server'; import type { ParityBasePrivateInputs, ParityPublicInputs, ParityRootPrivateInputs } from '@aztec/stdlib/parity'; -import { type Proof, ProvingRequestType, makeEmptyRecursiveProof, makeRecursiveProof } from '@aztec/stdlib/proofs'; +import { + type Proof, + ProvingRequestType, + RecursiveProof, + makeEmptyRecursiveProof, + makeRecursiveProof, +} from '@aztec/stdlib/proofs'; import { type BlockMergeRollupPrivateInputs, type BlockRollupPublicInputs, @@ -81,7 +84,6 @@ import { type TxMergeRollupPrivateInputs, type TxRollupPublicInputs, } from '@aztec/stdlib/rollup'; -import { VerificationKeyData } from '@aztec/stdlib/vks'; import { type TelemetryClient, getTelemetryClient, trackSpan } from '@aztec/telemetry-client'; import { ProverInstrumentation } from '../instrumentation.js'; @@ -400,17 +402,12 @@ export class TestCircuitProver implements ServerCircuitProver { ); } - public getAvmProof( - _inputs: AvmCircuitInputs, - ): Promise> { + public getAvmProof(_inputs: AvmCircuitInputs): Promise> { // We can't simulate the AVM because we don't have enough context to do so (e.g., DBs). - // We just return an empty proof and VK data. + // We just return an empty proof. this.logger.debug('Skipping AVM simulation in TestCircuitProver.'); return this.applyDelay(ProvingRequestType.PUBLIC_VM, () => - makeProofAndVerificationKey( - makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED), - VerificationKeyData.makeFake(AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED), - ), + makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED), ); } diff --git a/yarn-project/bb-prover/src/verification_key/verification_key_data.ts b/yarn-project/bb-prover/src/verification_key/verification_key_data.ts index 49191429d422..0307b8316789 100644 --- a/yarn-project/bb-prover/src/verification_key/verification_key_data.ts +++ b/yarn-project/bb-prover/src/verification_key/verification_key_data.ts @@ -1,9 +1,7 @@ -import { AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED } from '@aztec/constants'; import { Fr } from '@aztec/foundation/curves/bn254'; import { BufferReader } from '@aztec/foundation/serialize'; import { VerificationKeyAsFields, VerificationKeyData } from '@aztec/stdlib/vks'; -import { strict as assert } from 'assert'; import { promises as fs } from 'fs'; import * as path from 'path'; @@ -25,26 +23,3 @@ export async function extractVkData(vkDirectoryPath: string): Promise { - const rawBinary = await fs.readFile(path.join(vkDirectoryPath, VK_FILENAME)); - - const numFields = rawBinary.length / Fr.SIZE_IN_BYTES; - assert(numFields <= AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED, 'Invalid AVM verification key length'); - const reader = BufferReader.asReader(rawBinary); - const fieldsArray = reader.readArray(numFields, Fr); - - const fieldsArrayPadded = fieldsArray.concat( - Array(AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED - fieldsArray.length).fill(new Fr(0)), - ); - const vkAsFields = await VerificationKeyAsFields.fromKey(fieldsArrayPadded); - // TODO(#16644): We should have a different type for AVM verification keys since we don't have circuit size or num public inputs in AVM VKs. - const vk = new VerificationKeyData(vkAsFields, rawBinary); - return vk; -} diff --git a/yarn-project/bb-prover/src/verifier/bb_verifier.ts b/yarn-project/bb-prover/src/verifier/bb_verifier.ts index e215aeb4fdfa..3632f30f09b5 100644 --- a/yarn-project/bb-prover/src/verifier/bb_verifier.ts +++ b/yarn-project/bb-prover/src/verifier/bb_verifier.ts @@ -102,10 +102,6 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier { // Block below is almost copy-pasted from verifyProofForCircuit const operation = async (bbWorkingDirectory: string) => { - const logFunction = (message: string) => { - this.logger.debug(`${proofType} BB out - ${message}`); - }; - const proofPath = path.join(bbWorkingDirectory, PROOF_FILENAME); await writeChonkProofToPath(tx.chonkProof.attachPublicInputs(tx.data.publicInputs().toFields()), proofPath); @@ -118,7 +114,7 @@ export class BBCircuitVerifier implements ClientProtocolCircuitVerifier { this.config.bbBinaryPath, proofPath, verificationKeyPath, - logFunction, + this.logger, this.config.bbIVCConcurrency, ); verificationDuration = timer.ms(); diff --git a/yarn-project/ivc-integration/src/prove_native.ts b/yarn-project/ivc-integration/src/prove_native.ts index cf9f87f7c79b..3aeeb260fdbe 100644 --- a/yarn-project/ivc-integration/src/prove_native.ts +++ b/yarn-project/ivc-integration/src/prove_native.ts @@ -12,7 +12,6 @@ import { } from '@aztec/bb-prover'; import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, - AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED, CHONK_PROOF_LENGTH, HIDING_KERNEL_IO_PUBLIC_INPUTS_SIZE, NESTED_RECURSIVE_PROOF_LENGTH, @@ -153,7 +152,6 @@ export async function proveAvm( workingDirectory: string, logger: Logger, ): Promise<{ - vk: VerificationKeyAsFields; proof: Fr[]; publicInputs: AvmCircuitPublicInputs; }> { @@ -169,11 +167,7 @@ export async function proveAvm( } const avmProofPath = proofRes.proofPath; - const avmVkDirectoryPath = proofRes.vkDirectoryPath; expect(avmProofPath).toBeDefined(); - expect(avmVkDirectoryPath).toBeDefined(); - - const avmVkPath = path.join(proofRes.vkDirectoryPath as string, VK_FILENAME); // Read the binary proof const avmProofBuffer = await fs.readFile(avmProofPath!); @@ -191,26 +185,11 @@ export async function proveAvm( proof.push(new Fr(0)); } - // Read the key - const vkBuffer = await fs.readFile(avmVkPath!); - const vkReader = BufferReader.asReader(vkBuffer); - const vk: Fr[] = []; - while (!vkReader.isEmpty()) { - vk.push(Fr.fromBuffer(vkReader)); - } - // We extend to a fixed-size padded vk as during development any new AVM circuit precomputed - // column changes the vk length and we do not have a mechanism to feedback a cpp constant to noir/TS. - // TODO(#13390): Revive a non-padded vk proof - while (vk.length < AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED) { - vk.push(new Fr(0)); - } - const verificationResult = await verifyAvmProof( bbPath, workingDirectory, proofRes.proofPath!, avmCircuitInputs.publicInputs, - path.join(proofRes.vkDirectoryPath!, VK_FILENAME), logger, ); @@ -220,7 +199,6 @@ export async function proveAvm( return { proof, - vk: await VerificationKeyAsFields.fromKey(vk), publicInputs: avmCircuitInputs.publicInputs, }; } diff --git a/yarn-project/prover-client/src/orchestrator/orchestrator.ts b/yarn-project/prover-client/src/orchestrator/orchestrator.ts index 936abde3e69d..3085220cede0 100644 --- a/yarn-project/prover-client/src/orchestrator/orchestrator.ts +++ b/yarn-project/prover-client/src/orchestrator/orchestrator.ts @@ -1219,9 +1219,9 @@ export class ProvingOrchestrator implements EpochProver { }, ); - this.deferredProving(provingState, doAvmProving, proofAndVk => { + this.deferredProving(provingState, doAvmProving, proof => { logger.debug(`Proven VM for tx index: ${txIndex}`); - txProvingState.setAvmProof(proofAndVk); + txProvingState.setAvmProof(proof); this.checkAndEnqueueBaseRollup(provingState, txIndex); }); } diff --git a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts index e1da64c15442..9fb56f390fc0 100644 --- a/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts +++ b/yarn-project/prover-client/src/orchestrator/tx-proving-state.ts @@ -2,8 +2,8 @@ import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, NESTED_RECURSIVE_ROLLUP_HONK_PROO import type { Fr } from '@aztec/foundation/curves/bn254'; import { getVkData } from '@aztec/noir-protocol-circuits-types/server/vks'; import type { AvmCircuitInputs } from '@aztec/stdlib/avm'; -import type { ProofAndVerificationKey, PublicInputsAndRecursiveProof } from '@aztec/stdlib/interfaces/server'; -import { ProofData, ProofDataForFixedVk } from '@aztec/stdlib/proofs'; +import type { PublicInputsAndRecursiveProof } from '@aztec/stdlib/interfaces/server'; +import { ProofData, ProofDataForFixedVk, RecursiveProof } from '@aztec/stdlib/proofs'; import { type BaseRollupHints, PrivateBaseRollupHints, @@ -32,7 +32,7 @@ export class TxProvingState { PublicChonkVerifierPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH >; - private avm?: ProofAndVerificationKey; + private avmProof?: RecursiveProof; constructor( public readonly processedTx: ProcessedTx, @@ -46,7 +46,7 @@ export class TxProvingState { } public ready() { - return !this.requireAvmProof || (!!this.avm && !!this.publicChonkVerifier); + return !this.requireAvmProof || (!!this.avmProof && !!this.publicChonkVerifier); } public getAvmInputs(): AvmCircuitInputs { @@ -80,8 +80,8 @@ export class TxProvingState { this.publicChonkVerifier = publicChonkVerifierProofAndVk; } - public setAvmProof(avmProofAndVk: ProofAndVerificationKey) { - this.avm = avmProofAndVk; + public setAvmProof(avmProof: RecursiveProof) { + this.avmProof = avmProof; } #getPrivateBaseInputs() { @@ -105,7 +105,7 @@ export class TxProvingState { if (!this.publicChonkVerifier) { throw new Error('Tx not ready for proving base rollup: public chonk verifier proof undefined'); } - if (!this.avm) { + if (!this.avmProof) { throw new Error('Tx not ready for proving base rollup: avm proof undefined'); } if (!(this.baseRollupHints instanceof PublicBaseRollupHints)) { @@ -114,10 +114,7 @@ export class TxProvingState { const publicChonkVerifierProofData = toProofData(this.publicChonkVerifier); - const avmProofData = new ProofDataForFixedVk( - this.processedTx.avmProvingRequest.inputs.publicInputs, - this.avm.proof, - ); + const avmProofData = new ProofDataForFixedVk(this.processedTx.avmProvingRequest.inputs.publicInputs, this.avmProof); return new PublicTxBaseRollupPrivateInputs(publicChonkVerifierProofData, avmProofData, this.baseRollupHints); } diff --git a/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts b/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts index f7e6a1681f70..524de77bd18d 100644 --- a/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts +++ b/yarn-project/prover-client/src/proving_broker/broker_prover_facade.ts @@ -11,7 +11,6 @@ import { type PromiseWithResolvers, RunningPromise, promiseWithResolvers } from import { truncate } from '@aztec/foundation/string'; import type { AvmCircuitInputs } from '@aztec/stdlib/avm'; import { - type ProofAndVerificationKey, type ProofUri, type ProvingJobId, type ProvingJobInputsMap, @@ -23,7 +22,7 @@ import { makeProvingJobId, } from '@aztec/stdlib/interfaces/server'; import type { ParityBasePrivateInputs, ParityPublicInputs, ParityRootPrivateInputs } from '@aztec/stdlib/parity'; -import { ProvingRequestType } from '@aztec/stdlib/proofs'; +import { ProvingRequestType, RecursiveProof } from '@aztec/stdlib/proofs'; import type { BlockMergeRollupPrivateInputs, BlockRollupPublicInputs, @@ -399,7 +398,7 @@ export class BrokerCircuitProverFacade implements ServerCircuitProver { inputs: AvmCircuitInputs, signal?: AbortSignal, epochNumber?: EpochNumber, - ): Promise> { + ): Promise> { return this.enqueueJob( this.generateId(ProvingRequestType.PUBLIC_VM, inputs, epochNumber), ProvingRequestType.PUBLIC_VM, diff --git a/yarn-project/prover-client/src/test/mock_prover.ts b/yarn-project/prover-client/src/test/mock_prover.ts index afeb91ef92f8..d3d1ca19d307 100644 --- a/yarn-project/prover-client/src/test/mock_prover.ts +++ b/yarn-project/prover-client/src/test/mock_prover.ts @@ -1,6 +1,5 @@ import { AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED, - AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED, NESTED_RECURSIVE_PROOF_LENGTH, NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH, RECURSIVE_PROOF_LENGTH, @@ -14,7 +13,6 @@ import { type ProvingJobStatus, type PublicInputsAndRecursiveProof, type ServerCircuitProver, - makeProofAndVerificationKey, makePublicInputsAndRecursiveProof, } from '@aztec/stdlib/interfaces/server'; import type { ParityBasePrivateInputs, ParityRootPrivateInputs } from '@aztec/stdlib/parity'; @@ -106,12 +104,7 @@ export class MockProver implements ServerCircuitProver { constructor() {} getAvmProof(_inputs: AvmCircuitInputs, _signal?: AbortSignal, _epochNumber?: number) { - return Promise.resolve( - makeProofAndVerificationKey( - makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED), - VerificationKeyData.makeFake(AVM_V2_VERIFICATION_KEY_LENGTH_IN_FIELDS_PADDED), - ), - ); + return Promise.resolve(makeEmptyRecursiveProof(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED)); } getBaseParityProof(_inputs: ParityBasePrivateInputs, _signal?: AbortSignal, _epochNumber?: number) { diff --git a/yarn-project/stdlib/src/interfaces/proving-job.ts b/yarn-project/stdlib/src/interfaces/proving-job.ts index 14d3d09b2f3c..1a242da7974e 100644 --- a/yarn-project/stdlib/src/interfaces/proving-job.ts +++ b/yarn-project/stdlib/src/interfaces/proving-job.ts @@ -47,15 +47,6 @@ export type ProofAndVerificationKey = { verificationKey: VerificationKeyData; }; -function schemaForRecursiveProofAndVerificationKey( - proofLength: N, -): ZodFor> { - return z.object({ - proof: RecursiveProof.schemaFor(proofLength), - verificationKey: VerificationKeyData.schema, - }); -} - export function makeProofAndVerificationKey( proof: RecursiveProof, verificationKey: VerificationKeyData, @@ -213,7 +204,7 @@ export type ProvingJobInputsMap = { export const ProvingJobResult = z.discriminatedUnion('type', [ z.object({ type: z.literal(ProvingRequestType.PUBLIC_VM), - result: schemaForRecursiveProofAndVerificationKey(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED), + result: RecursiveProof.schemaFor(AVM_V2_PROOF_LENGTH_IN_FIELDS_PADDED), }), z.object({ type: z.literal(ProvingRequestType.PUBLIC_CHONK_VERIFIER), @@ -328,7 +319,7 @@ export const ProvingJobResult = z.discriminatedUnion('type', [ ]); export type ProvingJobResult = z.infer; export type ProvingJobResultsMap = { - [ProvingRequestType.PUBLIC_VM]: ProofAndVerificationKey; + [ProvingRequestType.PUBLIC_VM]: RecursiveProof; [ProvingRequestType.PUBLIC_CHONK_VERIFIER]: PublicInputsAndRecursiveProof< PublicChonkVerifierPublicInputs, typeof NESTED_RECURSIVE_ROLLUP_HONK_PROOF_LENGTH diff --git a/yarn-project/stdlib/src/interfaces/server_circuit_prover.ts b/yarn-project/stdlib/src/interfaces/server_circuit_prover.ts index c2642bd446fc..c761f2474e0b 100644 --- a/yarn-project/stdlib/src/interfaces/server_circuit_prover.ts +++ b/yarn-project/stdlib/src/interfaces/server_circuit_prover.ts @@ -9,6 +9,7 @@ import type { AvmCircuitInputs } from '../avm/avm.js'; import type { ParityBasePrivateInputs } from '../parity/parity_base_private_inputs.js'; import type { ParityPublicInputs } from '../parity/parity_public_inputs.js'; import type { ParityRootPrivateInputs } from '../parity/parity_root_private_inputs.js'; +import type { RecursiveProof } from '../proofs/recursive_proof.js'; import type { BlockMergeRollupPrivateInputs } from '../rollup/block_merge_rollup_private_inputs.js'; import type { BlockRollupPublicInputs } from '../rollup/block_rollup_public_inputs.js'; import type { @@ -34,7 +35,7 @@ import type { RootRollupPublicInputs } from '../rollup/root_rollup_public_inputs import type { TxMergeRollupPrivateInputs } from '../rollup/tx_merge_rollup_private_inputs.js'; import type { TxRollupPublicInputs } from '../rollup/tx_rollup_public_inputs.js'; import type { Tx } from '../tx/tx.js'; -import type { ProofAndVerificationKey, PublicInputsAndRecursiveProof } from './proving-job.js'; +import type { PublicInputsAndRecursiveProof } from './proving-job.js'; /** * Generates proofs for parity and rollup circuits. @@ -188,7 +189,7 @@ export interface ServerCircuitProver { inputs: AvmCircuitInputs, signal?: AbortSignal, epochNumber?: number, - ): Promise>; + ): Promise>; } export type IVCProofVerificationResult = {