diff --git a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp index 210e570ae60a..7161cc078c28 100644 --- a/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp +++ b/barretenberg/cpp/src/barretenberg/boomerang_value_detection/graph_description_goblin.test.cpp @@ -23,15 +23,17 @@ class BoomerangGoblinRecursiveVerifierTests : public testing::Test { using OuterDeciderProvingKey = DeciderProvingKey_; using Commitment = MergeVerifier::Commitment; + using TableCommitment = MergeVerifier::TableCommitments; using RecursiveCommitment = GoblinRecursiveVerifier::MergeVerifier::Commitment; - using TableCommitments = GoblinRecursiveVerifier::MergeVerifier::TableCommitments; + using RecursiveTableCommitment = GoblinRecursiveVerifier::MergeVerifier::TableCommitments; static void SetUpTestSuite() { bb::srs::init_file_crs_factory(bb::srs::bb_crs_path()); } struct ProverOutput { GoblinProof proof; Goblin::VerificationKey verifier_input; - std::array t_commitments; + TableCommitment t_commitments; + TableCommitment T_prev_commitments; }; /** @@ -58,17 +60,21 @@ class BoomerangGoblinRecursiveVerifierTests : public testing::Test { GoblinMockCircuits::construct_simple_circuit(builder); goblin_final.op_queue->merge(); // Subtable values and commitments - needed for (Recursive)MergeVerifier - std::array t_commitments; + TableCommitment t_commitments; + TableCommitment T_prev_commitments; auto t_current = goblin_final.op_queue->construct_current_ultra_ops_subtable_columns(); + auto T_prev = goblin_final.op_queue->construct_previous_ultra_ops_table_columns(); CommitmentKey pcs_commitment_key(goblin_final.op_queue->get_ultra_ops_table_num_rows()); for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) { t_commitments[idx] = pcs_commitment_key.commit(t_current[idx]); + T_prev_commitments[idx] = pcs_commitment_key.commit(T_prev[idx]); } // Output is a goblin proof plus ECCVM/Translator verification keys return { goblin_final.prove(), { std::make_shared(), std::make_shared() }, - t_commitments }; + t_commitments, + T_prev_commitments }; } }; @@ -78,18 +84,21 @@ class BoomerangGoblinRecursiveVerifierTests : public testing::Test { */ TEST_F(BoomerangGoblinRecursiveVerifierTests, graph_description_basic) { - auto [proof, verifier_input, t_commitments] = create_goblin_prover_output(); + auto [proof, verifier_input, t_commitments, T_prev_commitments] = create_goblin_prover_output(); Builder builder; // Merge commitments - TableCommitments recursive_t_commitments; + RecursiveTableCommitment recursive_t_commitments; + RecursiveTableCommitment recursive_T_prev_commitments; for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) { recursive_t_commitments[idx] = RecursiveCommitment::from_witness(&builder, t_commitments[idx]); + recursive_T_prev_commitments[idx] = RecursiveCommitment::from_witness(&builder, T_prev_commitments[idx]); } GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_t_commitments); + GoblinRecursiveVerifierOutput output = + verifier.verify(proof, recursive_t_commitments, recursive_T_prev_commitments); output.points_accumulator.set_public(); // Construct and verify a proof for the Goblin Recursive Verifier circuit { diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 76080b13ab41..a43e9d345210 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -95,12 +95,19 @@ std::pair ClientIVC:: perform_recursive_verification_and_databus_consistency_checks( ClientCircuit& circuit, const StdlibVerifierInputs& verifier_inputs, + const TableCommitments& T_prev_commitments, const std::shared_ptr& accumulation_recursive_transcript) { // Witness commitments and public inputs corresponding to the incoming instance WitnessCommitments witness_commitments; std::vector public_inputs; + // Commitments to the previous status of the op_queue, to be finalized according to the recursive verification we + // are performing + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1492): Change Merge verifier API and improve the name + // of the following variable. + TableCommitments finalised_T_prev_commitments = T_prev_commitments; + switch (verifier_inputs.type) { case QUEUE_TYPE::PG: { // Construct stdlib verifier accumulator from the native counterpart computed on a previous round @@ -138,6 +145,9 @@ std::pair ClientIVC:: witness_commitments = std::move(verifier_accum->witness_commitments); public_inputs = std::move(verifier.public_inputs); + // T_prev = 0 in the first recursive verification + finalised_T_prev_commitments = HidingKernelIO::empty_ecc_op_tables(circuit); + break; } case QUEUE_TYPE::PG_FINAL: { @@ -152,20 +162,18 @@ std::pair ClientIVC:: } } - // Extract the commitments to the subtable corresponding to the incoming circuit - TableCommitments t_commitments = witness_commitments.get_ecc_op_wires().get_copy(); - - // Recursively verify the corresponding merge proof - auto [pairing_points, merged_table_commitments] = - goblin.recursively_verify_merge(circuit, t_commitments, accumulation_recursive_transcript); - PairingPoints nested_pairing_points; // to be extracted from public inputs of app or kernel proof just verified if (verifier_inputs.is_kernel) { // Reconstruct the input from the previous kernel from its public inputs KernelIO kernel_input; // pairing points, databus return data commitments kernel_input.reconstruct_from_public(public_inputs); + nested_pairing_points = kernel_input.pairing_inputs; + // T_prev is read by the public input of the previous kernel K_{i-1} at the beginning of the recursive + // verification of of the folding of K_{i-1} (kernel), A_{i,1} (app), .., A_{i, n} (app). This verification + // happens in K_{i} + finalised_T_prev_commitments = kernel_input.ecc_op_tables; // Perform databus consistency checks kernel_input.kernel_return_data.assert_equal(witness_commitments.calldata); @@ -183,6 +191,13 @@ std::pair ClientIVC:: bus_depot.set_app_return_data_commitment(witness_commitments.return_data); } + // Extract the commitments to the subtable corresponding to the incoming circuit + TableCommitments t_commitments = witness_commitments.get_ecc_op_wires().get_copy(); + + // Recursively verify the corresponding merge proof + auto [pairing_points, merged_table_commitments] = goblin.recursively_verify_merge( + circuit, t_commitments, finalised_T_prev_commitments, accumulation_recursive_transcript); + pairing_points.aggregate(nested_pairing_points); return { pairing_points, merged_table_commitments }; @@ -217,7 +232,7 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) while (!stdlib_verification_queue.empty()) { const StdlibVerifierInputs& verifier_input = stdlib_verification_queue.front(); auto [pairing_points, merged_table_commitments] = perform_recursive_verification_and_databus_consistency_checks( - circuit, verifier_input, accumulation_recursive_transcript); + circuit, verifier_input, T_prev_commitments, accumulation_recursive_transcript); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1376): Optimize recursion aggregation - seems // we can use `batch_mul` here to decrease the size of the `ECCOpQueue`, but must be cautious with FS security. @@ -240,6 +255,7 @@ void ClientIVC::complete_kernel_circuit_logic(ClientCircuit& circuit) kernel_output.pairing_inputs = points_accumulator; kernel_output.kernel_return_data = bus_depot.get_kernel_return_data_commitment(circuit); kernel_output.app_return_data = bus_depot.get_app_return_data_commitment(circuit); + kernel_output.ecc_op_tables = T_prev_commitments; kernel_output.set_public(); } @@ -407,8 +423,11 @@ std::pair ClientIVC::comp // Extract the commitments to the subtable corresponding to the incoming circuit TableCommitments t_commitments = witness_commitments.get_ecc_op_wires().get_copy(); // Perform recursive verification of the last merge proof - auto [points_accumulator, merged_table_commitments] = - goblin.recursively_verify_merge(circuit, t_commitments, pg_merge_transcript); + auto [points_accumulator, merged_table_commitments] = goblin.recursively_verify_merge( + circuit, + t_commitments, + kernel_input.ecc_op_tables, // Commitment to the status of the op_queue before folding the tail kernel + pg_merge_transcript); points_accumulator.aggregate(kernel_input.pairing_inputs); @@ -502,8 +521,8 @@ bool ClientIVC::verify(const Proof& proof, const VerificationKey& vk) verifier.verification_key->witness_commitments.get_ecc_op_wires().get_copy(); // Goblin verification (final merge, eccvm, translator) - auto [goblin_verified, _merged_table_commitments] = - Goblin::verify(proof.goblin_proof, t_commitments, civc_verifier_transcript); + bool goblin_verified = + Goblin::verify(proof.goblin_proof, t_commitments, T_prev_commitments, civc_verifier_transcript); vinfo("Goblin verified: ", goblin_verified); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1396): State tracking in CIVC verifiers. diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp index 5cf7a3ad7be9..bb3d445b70f3 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -205,6 +205,7 @@ class ClientIVC { perform_recursive_verification_and_databus_consistency_checks( ClientCircuit& circuit, const StdlibVerifierInputs& verifier_inputs, + const TableCommitments& T_prev_commitments, const std::shared_ptr& accumulation_recursive_transcript); // Complete the logic of a kernel circuit (e.g. PG/merge recursive verification, databus consistency checks) diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 389e2d2e30fd..229ba0de2a90 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -37,7 +37,7 @@ static constexpr uint32_t NUM_LIBRA_COMMITMENTS = 3; // extra evaluations static constexpr uint32_t NUM_SMALL_IPA_EVALUATIONS = 4; -static constexpr uint32_t MERGE_PROOF_SIZE = 65; // used to ensure mock proofs are generated correctly +static constexpr uint32_t MERGE_PROOF_SIZE = 49; // used to ensure mock proofs are generated correctly // There are 5 distinguished wires in ECCVM that have to be opened as univariates to establish the connection between // ECCVM and Translator diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp index 24aa7fa07937..fdd63d2e5bbc 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp @@ -99,6 +99,7 @@ ClientIVC::VerifierInputs create_mock_verification_queue_entry(const ClientIVC:: { using FF = ClientIVC::FF; using MegaVerificationKey = ClientIVC::MegaVerificationKey; + using Flavor = ClientIVC::Flavor; // Use the trace settings to determine the correct dyadic size and the public inputs offset MegaExecutionTraceBlocks blocks; @@ -106,26 +107,41 @@ ClientIVC::VerifierInputs create_mock_verification_queue_entry(const ClientIVC:: blocks.compute_offsets(/*is_structured=*/true); size_t dyadic_size = blocks.get_structured_dyadic_size(); size_t pub_inputs_offset = blocks.pub_inputs.trace_offset(); - // All circuits have pairing point public inputs; kernels have additional public inputs for two databus commitments - size_t num_public_inputs = bb::PAIRING_POINTS_SIZE; - if (is_kernel) { - num_public_inputs += bb::PROPAGATED_DATABUS_COMMITMENTS_SIZE; - } - // Construct a mock Oink or PG proof + // Construct a mock Oink or PG proof and a mock MegaHonk verification key std::vector proof; - if (verification_type == ClientIVC::QUEUE_TYPE::OINK) { - proof = create_mock_oink_proof(num_public_inputs); - } else if (verification_type == ClientIVC::QUEUE_TYPE::PG || verification_type == ClientIVC::QUEUE_TYPE::PG_FINAL) { - proof = create_mock_pg_proof(num_public_inputs); + std::shared_ptr verification_key; + + if (is_kernel) { + using KernelIO = stdlib::recursion::honk::KernelIO; + switch (verification_type) { + case ClientIVC::QUEUE_TYPE::OINK: + proof = create_mock_oink_proof(); + break; + case ClientIVC::QUEUE_TYPE::PG: + case ClientIVC::QUEUE_TYPE::PG_FINAL: + proof = create_mock_pg_proof(); + break; + default: + throw_or_abort("Invalid verification type! Only OINK, PG and PG_FINAL are supported"); + } + verification_key = create_mock_honk_vk(dyadic_size, pub_inputs_offset); } else { - throw_or_abort("Invalid verification type! Only OINK, PG and PG_FINAL are supported"); + using AppIO = stdlib::recursion::honk::AppIO; + switch (verification_type) { + case ClientIVC::QUEUE_TYPE::OINK: + proof = create_mock_oink_proof(); + break; + case ClientIVC::QUEUE_TYPE::PG: + case ClientIVC::QUEUE_TYPE::PG_FINAL: + proof = create_mock_pg_proof(); + break; + default: + throw_or_abort("Invalid verification type! Only OINK, PG and PG_FINAL are supported"); + } + verification_key = create_mock_honk_vk(dyadic_size, pub_inputs_offset); } - // Construct a mock MegaHonk verification key - std::shared_ptr verification_key = - create_mock_honk_vk(dyadic_size, num_public_inputs, pub_inputs_offset); - return ClientIVC::VerifierInputs{ proof, verification_key, verification_type, is_kernel }; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp index f28345682e7e..b4fe5f15f649 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp @@ -481,8 +481,6 @@ TEST_F(IvcRecursionConstraintTest, GenerateHidingKernelVKFromConstraints) // construct a mock tail kernel acir_format::mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG_FINAL, /*is_kernel=*/true); AcirProgram program = construct_mock_kernel_program(ivc->verification_queue); - // acir_format::mock_ivc_accumulation(ivc, ClientIVC::QUEUE_TYPE::PG_FINAL, /*is_kernel=*/true); - // program = construct_mock_kernel_program(ivc->verification_queue); program.witness = {}; // remove the witness to mimick VK construction context kernel_vk = construct_kernel_vk_from_acir_program(program, TraceSettings()); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.cpp index 1ece4124f736..dcabb8fd4011 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.cpp @@ -13,6 +13,7 @@ #include "barretenberg/stdlib/pairing_points.hpp" #include "barretenberg/stdlib/primitives/bigfield/constants.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/special_public_inputs/special_public_inputs.hpp" #include "barretenberg/ultra_honk/decider_keys.hpp" #include "proof_surgeon.hpp" #include "recursion_constraint.hpp" @@ -42,36 +43,17 @@ void populate_field_elements_for_mock_commitments(std::vector& fields, const * @brief Create a mock oink proof that has the correct structure but is not in general valid * */ -template HonkProof create_mock_oink_proof(const size_t num_public_inputs) +template HonkProof create_mock_oink_proof() { HonkProof proof; // Populate mock public inputs - // Get some values for a valid aggregation object and use them here to avoid divide by 0 or other issues. - std::array::PUBLIC_INPUTS_SIZE> - dummy_pairing_points_values = stdlib::recursion::PairingPoints::construct_dummy(); - size_t public_input_count = 0; - for (size_t i = 0; i < stdlib::recursion::PairingPoints::PUBLIC_INPUTS_SIZE; i++) { - proof.emplace_back(dummy_pairing_points_values[i]); - public_input_count++; - } + typename Flavor::CircuitBuilder builder; + PublicInputs::add_default(builder); - if (public_input_count < num_public_inputs) { - // Databus commitments if necessary - for (size_t i = 0; i < NUM_DATABUS_COMMITMENTS; ++i) { - // We represent commitments in the public inputs as biggroup elements. - using BigGroup = stdlib::element_default::element, - stdlib::field_t, - curve::BN254::Group>; - auto pub_input_comm_vals = BigGroup::construct_dummy(); - for (const fr& comm_fr : pub_input_comm_vals) { - proof.emplace_back(comm_fr); - public_input_count++; - } - } + for (const auto& pub : builder.public_inputs()) { + proof.emplace_back(builder.get_variable(pub)); } - BB_ASSERT_EQ(public_input_count, num_public_inputs, "Mock oink proof has the wrong number of public inputs."); // Populate mock witness polynomial commitments populate_field_elements_for_mock_commitments(proof, Flavor::NUM_WITNESS_ENTITIES); @@ -122,10 +104,10 @@ template HonkProof create_mock_decider_proof() * @brief Create a mock honk proof that has the correct structure but is not in general valid * */ -template HonkProof create_mock_honk_proof(const size_t num_public_inputs) +template HonkProof create_mock_honk_proof() { // Construct a Honk proof as the concatenation of an Oink proof and a Decider proof - HonkProof oink_proof = create_mock_oink_proof(num_public_inputs); + HonkProof oink_proof = create_mock_oink_proof(); HonkProof decider_proof = create_mock_decider_proof(); HonkProof proof; proof.reserve(oink_proof.size() + decider_proof.size()); @@ -138,10 +120,10 @@ template HonkProof create_mock_honk_proof(const size_t num_pub * @brief Create a mock PG proof that has the correct structure but is not in general valid * */ -template HonkProof create_mock_pg_proof(const size_t num_public_inputs) +template HonkProof create_mock_pg_proof() { // The first part of a PG proof is an Oink proof - HonkProof proof = create_mock_oink_proof(num_public_inputs); + HonkProof proof = create_mock_oink_proof(); // Populate mock perturbator coefficients for (size_t idx = 1; idx <= CONST_PG_LOG_N; idx++) { @@ -177,9 +159,9 @@ Goblin::MergeProof create_mock_merge_proof() // Populate mock subtable size proof.emplace_back(mock_val); - // There are 12 entities in the merge protocol (4 columns x 3 components: T_{prev,j}, T_j, g_j(X) = X^{l-1} t_j(X)) + // There are 8 entities in the merge protocol (4 columns x 2 components: T_j, g_j(X) = X^{l-1} t_j(X)) // and 8 evaluations (4 columns x 2 components: g_j(kappa), t_j(1/kappa)) - const size_t NUM_TRANSCRIPT_ENTITIES = 12; + const size_t NUM_TRANSCRIPT_ENTITIES = 8; const size_t NUM_TRANSCRIPT_EVALUATIONS = 8; // Transcript poly commitments @@ -212,15 +194,14 @@ Goblin::MergeProof create_mock_merge_proof() * @brief Create a mock MegaHonk VK that has the correct structure * */ -template +template std::shared_ptr create_mock_honk_vk(const size_t dyadic_size, - const size_t num_public_inputs, const size_t pub_inputs_offset) { // Set relevant VK metadata and commitments auto honk_verification_key = std::make_shared(); honk_verification_key->log_circuit_size = bb::numeric::get_msb(dyadic_size); - honk_verification_key->num_public_inputs = num_public_inputs; + honk_verification_key->num_public_inputs = PublicInputs::PUBLIC_INPUTS_SIZE; honk_verification_key->pub_inputs_offset = pub_inputs_offset; // must be set correctly for (auto& commitment : honk_verification_key->get_all()) { @@ -241,7 +222,8 @@ template std::shared_ptr> crea // Set relevant VK metadata and commitments auto decider_verification_key = std::make_shared>(); std::shared_ptr vk = - create_mock_honk_vk(0, 0, 0); // metadata does not need to be accurate + create_mock_honk_vk>( + 0, 0); // metadata does not need to be accurate decider_verification_key->vk = vk; decider_verification_key->is_accumulator = true; decider_verification_key->gate_challenges = std::vector(static_cast(CONST_PG_LOG_N), 0); @@ -254,19 +236,33 @@ template std::shared_ptr> crea } // Explicitly instantiate template functions -template HonkProof create_mock_oink_proof(const size_t); -template HonkProof create_mock_oink_proof(const size_t); +template HonkProof create_mock_oink_proof(); +template HonkProof create_mock_oink_proof(); +template HonkProof create_mock_oink_proof>(); + +template HonkProof create_mock_oink_proof>(); template HonkProof create_mock_decider_proof(); template HonkProof create_mock_decider_proof(); -template HonkProof create_mock_honk_proof(const size_t); -template HonkProof create_mock_honk_proof(const size_t); +template HonkProof create_mock_honk_proof(); +template HonkProof create_mock_honk_proof(); +template HonkProof create_mock_honk_proof>(); + +template HonkProof create_mock_honk_proof>(); + +template HonkProof create_mock_pg_proof(); +template HonkProof create_mock_pg_proof(); +template HonkProof create_mock_pg_proof>(); -template HonkProof create_mock_pg_proof(const size_t); -template std::shared_ptr create_mock_honk_vk(const size_t, - const size_t, - const size_t); +template std::shared_ptr create_mock_honk_vk( + const size_t, const size_t); +template std::shared_ptr create_mock_honk_vk( + const size_t, const size_t); +template std::shared_ptr create_mock_honk_vk< + MegaFlavor, + stdlib::recursion::honk::HidingKernelIO>(const size_t, const size_t); template std::shared_ptr> create_mock_decider_vk(); } // namespace acir_format diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.hpp index b9f611a049d7..eef92550e588 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.hpp @@ -14,15 +14,14 @@ namespace acir_format { -template bb::HonkProof create_mock_oink_proof(const size_t num_public_inputs); +template bb::HonkProof create_mock_oink_proof(); template bb::HonkProof create_mock_decider_proof(); -template bb::HonkProof create_mock_honk_proof(const size_t num_public_inputs); -template bb::HonkProof create_mock_pg_proof(const size_t num_public_inputs); +template bb::HonkProof create_mock_honk_proof(); +template bb::HonkProof create_mock_pg_proof(); bb::Goblin::MergeProof create_mock_merge_proof(); -template +template std::shared_ptr create_mock_honk_vk(const size_t dyadic_size, - const size_t num_public_inputs, const size_t pub_inputs_offset); template std::shared_ptr> create_mock_decider_vk(); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.test.cpp index 59fd8a58aa0f..b91f44252af9 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/mock_verifier_inputs.test.cpp @@ -3,6 +3,7 @@ #include "acir_format_mocks.hpp" #include "barretenberg/client_ivc/client_ivc.hpp" #include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/stdlib/special_public_inputs/special_public_inputs.hpp" #include "barretenberg/ultra_honk/decider_proving_key.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -31,15 +32,48 @@ TEST(MockVerifierInputsTest, MockMergeProofSize) } /** - * @brief Check that the size of a mock Oink proof matches expectation based on Flavor + * @brief Check that the size of a mock Oink proof matches expectation for MegaFlavor * */ -TYPED_TEST(MockVerifierInputsTest, MockOinkProofSize) +TEST(MockVerifierInputsTest, MockMegaOinkProofSize) { - using Flavor = TypeParam; + using Flavor = MegaFlavor; + using Builder = MegaCircuitBuilder; + + { + // AppIO + const size_t NUM_PUBLIC_INPUTS = stdlib::recursion::honk::AppIO::PUBLIC_INPUTS_SIZE; + HonkProof honk_proof = create_mock_oink_proof(); + EXPECT_EQ(honk_proof.size(), Flavor::OINK_PROOF_LENGTH_WITHOUT_PUB_INPUTS + NUM_PUBLIC_INPUTS); + } + + { + // KernelIO + const size_t NUM_PUBLIC_INPUTS = stdlib::recursion::honk::KernelIO::PUBLIC_INPUTS_SIZE; + HonkProof honk_proof = create_mock_oink_proof(); + EXPECT_EQ(honk_proof.size(), Flavor::OINK_PROOF_LENGTH_WITHOUT_PUB_INPUTS + NUM_PUBLIC_INPUTS); + } + + { + // HidingKernelIO + const size_t NUM_PUBLIC_INPUTS = stdlib::recursion::honk::HidingKernelIO::PUBLIC_INPUTS_SIZE; + HonkProof honk_proof = create_mock_oink_proof>(); + EXPECT_EQ(honk_proof.size(), Flavor::OINK_PROOF_LENGTH_WITHOUT_PUB_INPUTS + NUM_PUBLIC_INPUTS); + } +} + +/** + * @brief Check that the size of a mock Oink proof matches expectation for UltraFlavor + * + */ +TEST(MockVerifierInputsTest, MockUltraOinkProofSize) +{ + using Flavor = UltraFlavor; + using Builder = UltraCircuitBuilder; - const size_t NUM_PUBLIC_INPUTS = PAIRING_POINTS_SIZE; - HonkProof honk_proof = create_mock_oink_proof(NUM_PUBLIC_INPUTS); + // DefaultIO + const size_t NUM_PUBLIC_INPUTS = stdlib::recursion::honk::DefaultIO::PUBLIC_INPUTS_SIZE; + HonkProof honk_proof = create_mock_oink_proof>(); EXPECT_EQ(honk_proof.size(), Flavor::OINK_PROOF_LENGTH_WITHOUT_PUB_INPUTS + NUM_PUBLIC_INPUTS); } @@ -56,14 +90,47 @@ TYPED_TEST(MockVerifierInputsTest, MockDeciderProofSize) } /** - * @brief Check that the size of a mock Honk proof matches expectation based on Flavor + * @brief Check that the size of a mock Honk proof matches expectation based for MegaFlavor * */ -TYPED_TEST(MockVerifierInputsTest, MockHonkProofSize) +TEST(MockVerifierInputsTest, MockMegaHonkProofSize) { - using Flavor = TypeParam; + using Flavor = MegaFlavor; + using Builder = MegaCircuitBuilder; + + { + // AppIO + const size_t NUM_PUBLIC_INPUTS = stdlib::recursion::honk::AppIO::PUBLIC_INPUTS_SIZE; + HonkProof honk_proof = create_mock_honk_proof(); + EXPECT_EQ(honk_proof.size(), Flavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS + NUM_PUBLIC_INPUTS); + } + + { + // KernelIO + const size_t NUM_PUBLIC_INPUTS = stdlib::recursion::honk::KernelIO::PUBLIC_INPUTS_SIZE; + HonkProof honk_proof = create_mock_honk_proof(); + EXPECT_EQ(honk_proof.size(), Flavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS + NUM_PUBLIC_INPUTS); + } + + { + // HidingKernelIO + const size_t NUM_PUBLIC_INPUTS = stdlib::recursion::honk::HidingKernelIO::PUBLIC_INPUTS_SIZE; + HonkProof honk_proof = create_mock_honk_proof>(); + EXPECT_EQ(honk_proof.size(), Flavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS + NUM_PUBLIC_INPUTS); + } +} + +/** + * @brief Check that the size of a mock Honk proof matches expectation for UltraFlavor + * + */ +TEST(MockVerifierInputsTest, MockHonkProofSize) +{ + using Flavor = UltraFlavor; + using Builder = UltraCircuitBuilder; - const size_t NUM_PUBLIC_INPUTS = PAIRING_POINTS_SIZE; - HonkProof honk_proof = create_mock_honk_proof(NUM_PUBLIC_INPUTS); + // DefaultIO + const size_t NUM_PUBLIC_INPUTS = stdlib::recursion::honk::DefaultIO::PUBLIC_INPUTS_SIZE; + HonkProof honk_proof = create_mock_honk_proof>(); EXPECT_EQ(honk_proof.size(), Flavor::PROOF_LENGTH_WITHOUT_PUB_INPUTS + NUM_PUBLIC_INPUTS); } diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp index ac448abc61ee..3612d66e0ba2 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.cpp @@ -77,6 +77,7 @@ GoblinProof Goblin::prove() std::pair Goblin::recursively_verify_merge( MegaBuilder& builder, const RecursiveTableCommitments& t_commitments, + const RecursiveTableCommitments& T_prev_commitments, const std::shared_ptr& transcript) { ASSERT(!merge_verification_queue.empty()); @@ -85,19 +86,22 @@ std::pair Goblin::recu const stdlib::Proof stdlib_merge_proof(builder, merge_proof); MergeRecursiveVerifier merge_verifier{ &builder, MergeSettings::PREPEND, transcript }; - auto [pairing_points, merged_table_commitments] = merge_verifier.verify_proof(stdlib_merge_proof, t_commitments); + auto [pairing_points, merged_table_commitments] = + merge_verifier.verify_proof(stdlib_merge_proof, t_commitments, T_prev_commitments); merge_verification_queue.pop_front(); // remove the processed proof from the queue return { pairing_points, merged_table_commitments }; } -std::pair Goblin::verify(const GoblinProof& proof, - const TableCommitments& t_commitments, - const std::shared_ptr& transcript) +bool Goblin::verify(const GoblinProof& proof, + const TableCommitments& t_commitments, + const TableCommitments& T_prev_commitments, + const std::shared_ptr& transcript) { MergeVerifier merge_verifier(MergeSettings::PREPEND, transcript); - auto [merge_verified, merged_table_commitments] = merge_verifier.verify_proof(proof.merge_proof, t_commitments); + auto [merge_verified, merged_table_commitments] = + merge_verifier.verify_proof(proof.merge_proof, t_commitments, T_prev_commitments); ECCVMVerifier eccvm_verifier(transcript); bool eccvm_verified = eccvm_verifier.verify_proof(proof.eccvm_proof); @@ -121,9 +125,8 @@ std::pair Goblin::verify(const GoblinProof& proo vinfo("translation verified?: ", translation_verified); vinfo("consistency verified?: ", op_queue_consistency_verified); - return { merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified && - op_queue_consistency_verified, - merged_table_commitments }; + return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified && + op_queue_consistency_verified; } } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 9c606f4daa81..83eb1a78a761 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -96,12 +96,14 @@ class Goblin { * @param builder The circuit in which the recursive verification will be performed. * @param subtable_commitments The subtable commitments data, containing the commitments to t_j read from the * transcript by the PG verifier with which the Merge verifier shares a transcript + * @param T_prev_commitments The full op_queue table commitments after the previous iteration of merge * @param transcript The transcript to be passed to the MergeRecursiveVerifier. * @return Pair of PairingPoints and commitments to the merged tables as read from the proof by the Merge verifier */ std::pair recursively_verify_merge( MegaBuilder& builder, const RecursiveTableCommitments& t_commitments, + const RecursiveTableCommitments& T_prev_commitments, const std::shared_ptr& transcript); /** @@ -110,15 +112,17 @@ class Goblin { * @param proof * @param subtable_commitments The subtable commitments data, containing the commitments to t_j read from the * transcript by the PG verifier with which the Merge verifier shares a transcript + * @param T_prev_commitments The full op_queue table commitments after the previous iteration of merge * @param merged_table_commitment The commitment to the merged table as read from the proof * @param transcript * * @return Pair of verification result and commitments to the merged tables as read from the proof by the Merge * verifier */ - static std::pair verify(const GoblinProof& proof, - const TableCommitments& t_commitments, - const std::shared_ptr& transcript); + static bool verify(const GoblinProof& proof, + const TableCommitments& t_commitments, + const TableCommitments& T_prev_commitments, + const std::shared_ptr& transcript); }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.cpp index 1945120f3666..005f948db729 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/client_ivc_verifier/client_ivc_recursive_verifier.cpp @@ -27,9 +27,14 @@ ClientIVCRecursiveVerifier::Output ClientIVCRecursiveVerifier::verify(const Stdl // Perform Goblin recursive verification GoblinVerificationKey goblin_verification_key{}; - TableCommitments t_commitments = verifier.key->witness_commitments.get_ecc_op_wires().get_copy(); + TableCommitments t_commitments = verifier.key->witness_commitments.get_ecc_op_wires() + .get_copy(); // Commitments to subtables added by the hiding kernel GoblinVerifier goblin_verifier{ builder.get(), goblin_verification_key, civc_rec_verifier_transcript }; - GoblinRecursiveVerifierOutput output = goblin_verifier.verify(proof.goblin_proof, t_commitments); + GoblinRecursiveVerifierOutput output = goblin_verifier.verify( + proof.goblin_proof, + t_commitments, + mega_output.ecc_op_tables // Commitments to the state of the ecc op_queue as computed insided the hiding kernel + ); output.points_accumulator.aggregate(mega_output.points_accumulator); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1396): State tracking in CIVC verifiers return { output }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.cpp index 12a9168046f2..5f2b61806c1a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.cpp @@ -16,10 +16,11 @@ namespace bb::stdlib::recursion::honk { * */ GoblinRecursiveVerifierOutput GoblinRecursiveVerifier::verify(const GoblinProof& proof, - const TableCommitments& t_commitments) + const TableCommitments& t_commitments, + const TableCommitments& T_prev_commitments) { StdlibProof stdlib_proof(*builder, proof); - return verify(stdlib_proof, t_commitments); + return verify(stdlib_proof, t_commitments, T_prev_commitments); } /** @@ -29,13 +30,16 @@ GoblinRecursiveVerifierOutput GoblinRecursiveVerifier::verify(const GoblinProof& * @param t_commitments The commitments to the subtable for the merge being verified * */ +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1492): Modify Merge verifier API and package inputs in a +// single struct GoblinRecursiveVerifierOutput GoblinRecursiveVerifier::verify(const StdlibProof& proof, - const TableCommitments& t_commitments) + const TableCommitments& t_commitments, + const TableCommitments& T_prev_commitments) { // Verify the final merge step MergeVerifier merge_verifier{ builder, MergeSettings::PREPEND, transcript }; auto [merge_pairing_points, merged_table_commitments] = - merge_verifier.verify_proof(proof.merge_proof, t_commitments); + merge_verifier.verify_proof(proof.merge_proof, t_commitments, T_prev_commitments); // Run the ECCVM recursive verifier ECCVMVerifier eccvm_verifier{ builder, verification_keys.eccvm_verification_key, transcript }; @@ -56,6 +60,6 @@ GoblinRecursiveVerifierOutput GoblinRecursiveVerifier::verify(const StdlibProof& // and final merge verifier translator_verifier.verify_consistency_with_final_merge(merged_table_commitments); - return { translator_pairing_points, opening_claim, ipa_proof, merged_table_commitments }; + return { translator_pairing_points, opening_claim, ipa_proof }; } } // namespace bb::stdlib::recursion::honk diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.hpp index 43339aae6003..c753d8a3a54d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.hpp @@ -21,7 +21,6 @@ struct GoblinRecursiveVerifierOutput { PairingAccumulator points_accumulator; OpeningClaim opening_claim; stdlib::Proof ipa_proof; - TableCommitments merged_table_commitments; }; class GoblinRecursiveVerifier { @@ -67,9 +66,9 @@ class GoblinRecursiveVerifier { , transcript(transcript){}; [[nodiscard("IPA claim and Pairing points should be accumulated")]] GoblinRecursiveVerifierOutput verify( - const GoblinProof&, const TableCommitments& t_commitments); + const GoblinProof&, const TableCommitments& t_commitments, const TableCommitments& T_prev_commitments); [[nodiscard("IPA claim and Pairing points should be accumulated")]] GoblinRecursiveVerifierOutput verify( - const StdlibProof&, const TableCommitments& t_commitments); + const StdlibProof&, const TableCommitments& t_commitments, const TableCommitments& T_prev_commitments); private: Builder* builder; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp index 8d6822b89d57..b65cae81f648 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/goblin_recursive_verifier.test.cpp @@ -32,7 +32,9 @@ class GoblinRecursiveVerifierTests : public testing::Test { GoblinProof proof; Goblin::VerificationKey verifier_input; TableCommitments t_commitments; + TableCommitments T_prev_commitments; RecursiveTableCommitments recursive_t_commitments; + RecursiveTableCommitments recursive_T_prev_commitments; }; /** @@ -62,24 +64,29 @@ class GoblinRecursiveVerifierTests : public testing::Test { // Subtable values and commitments - needed for (Recursive)MergeVerifier TableCommitments t_commitments; + TableCommitments T_prev_commitments; auto t_current = goblin_final.op_queue->construct_current_ultra_ops_subtable_columns(); + auto T_prev = goblin_final.op_queue->construct_previous_ultra_ops_table_columns(); CommitmentKey pcs_commitment_key(goblin_final.op_queue->get_ultra_ops_table_num_rows()); for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) { t_commitments[idx] = pcs_commitment_key.commit(t_current[idx]); + T_prev_commitments[idx] = pcs_commitment_key.commit(T_prev[idx]); } RecursiveTableCommitments recursive_t_commitments; + RecursiveTableCommitments recursive_T_prev_commitments; if (outer_builder != nullptr) { for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) { recursive_t_commitments[idx] = RecursiveCommitment::from_witness(outer_builder, t_commitments[idx]); + recursive_T_prev_commitments[idx] = + RecursiveCommitment::from_witness(outer_builder, T_prev_commitments[idx]); } } // Output is a goblin proof plus ECCVM/Translator verification keys - return { goblin_final.prove(), - { std::make_shared(), std::make_shared() }, - t_commitments, - recursive_t_commitments }; + return { goblin_final.prove(), { std::make_shared(), std::make_shared() }, + t_commitments, T_prev_commitments, + recursive_t_commitments, recursive_T_prev_commitments }; } }; @@ -89,11 +96,16 @@ class GoblinRecursiveVerifierTests : public testing::Test { */ TEST_F(GoblinRecursiveVerifierTests, NativeVerification) { - auto [proof, verifier_input, t_commitments, _] = create_goblin_prover_output(); + auto [proof, + verifier_input, + t_commitments, + T_prev_commitments, + _recursive_t_commitments, + _recursive_T_prev_commitments] = create_goblin_prover_output(); std::shared_ptr verifier_transcript = std::make_shared(); - EXPECT_TRUE(std::get<0>(Goblin::verify(proof, t_commitments, verifier_transcript))); + EXPECT_TRUE(Goblin::verify(proof, t_commitments, T_prev_commitments, verifier_transcript)); } /** @@ -104,10 +116,16 @@ TEST_F(GoblinRecursiveVerifierTests, Basic) { Builder builder; - auto [proof, verifier_input, t_commitments, recursive_t_commitments] = create_goblin_prover_output(&builder); + auto [proof, + verifier_input, + t_commitments, + T_prev_commitments, + recursive_t_commitments, + recursive_T_prev_commitments] = create_goblin_prover_output(&builder); GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_t_commitments); + GoblinRecursiveVerifierOutput output = + verifier.verify(proof, recursive_t_commitments, recursive_T_prev_commitments); output.points_accumulator.set_public(); info("Recursive Verifier: num gates = ", builder.num_gates); @@ -137,11 +155,16 @@ TEST_F(GoblinRecursiveVerifierTests, IndependentVKHash) -> std::tuple> { Builder builder; - auto [proof, verifier_input, t_commitments, recursive_t_commitments] = - create_goblin_prover_output(&builder, inner_size); + auto [proof, + verifier_input, + t_commitments, + T_prev_commitments, + recursive_t_commitments, + recursive_T_prev_commitments] = create_goblin_prover_output(&builder, inner_size); GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - GoblinRecursiveVerifierOutput output = verifier.verify(proof, recursive_t_commitments); + GoblinRecursiveVerifierOutput output = + verifier.verify(proof, recursive_t_commitments, recursive_T_prev_commitments); output.points_accumulator.set_public(); info("Recursive Verifier: num gates = ", builder.num_gates); @@ -170,7 +193,12 @@ TEST_F(GoblinRecursiveVerifierTests, ECCVMFailure) { Builder builder; - auto [proof, verifier_input, t_commitments, recursive_t_commitments] = create_goblin_prover_output(&builder); + auto [proof, + verifier_input, + t_commitments, + T_prev_commitments, + recursive_t_commitments, + recursive_T_prev_commitments] = create_goblin_prover_output(&builder); // Tamper with the ECCVM proof for (auto& val : proof.eccvm_proof.pre_ipa_proof) { @@ -181,7 +209,8 @@ TEST_F(GoblinRecursiveVerifierTests, ECCVMFailure) } GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - GoblinRecursiveVerifierOutput goblin_rec_verifier_output = verifier.verify(proof, recursive_t_commitments); + GoblinRecursiveVerifierOutput goblin_rec_verifier_output = + verifier.verify(proof, recursive_t_commitments, recursive_T_prev_commitments); srs::init_file_crs_factory(bb::srs::bb_crs_path()); auto crs_factory = srs::get_grumpkin_crs_factory(); @@ -202,7 +231,12 @@ TEST_F(GoblinRecursiveVerifierTests, ECCVMFailure) */ TEST_F(GoblinRecursiveVerifierTests, TranslatorFailure) { - auto [proof, verifier_input, t_commitments, _] = create_goblin_prover_output(); + auto [proof, + verifier_input, + t_commitments, + T_prev_commitments, + _recursive_t_commitments, + _recursive_T_prev_commitments] = create_goblin_prover_output(); // Tamper with the Translator proof preamble { @@ -217,12 +251,15 @@ TEST_F(GoblinRecursiveVerifierTests, TranslatorFailure) Builder builder; RecursiveTableCommitments recursive_t_commitments; + RecursiveTableCommitments recursive_T_prev_commitments; for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) { recursive_t_commitments[idx] = RecursiveCommitment::from_witness(&builder, t_commitments[idx]); + recursive_T_prev_commitments[idx] = RecursiveCommitment::from_witness(&builder, T_prev_commitments[idx]); } GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - [[maybe_unused]] auto goblin_rec_verifier_output = verifier.verify(tampered_proof, recursive_t_commitments); + [[maybe_unused]] auto goblin_rec_verifier_output = + verifier.verify(tampered_proof, recursive_t_commitments, recursive_T_prev_commitments); EXPECT_FALSE(CircuitChecker::check(builder)); } // Tamper with the Translator proof non-preamble values @@ -241,12 +278,15 @@ TEST_F(GoblinRecursiveVerifierTests, TranslatorFailure) Builder builder; RecursiveTableCommitments recursive_t_commitments; + RecursiveTableCommitments recursive_T_prev_commitments; for (size_t idx = 0; idx < MegaFlavor::NUM_WIRES; idx++) { recursive_t_commitments[idx] = RecursiveCommitment::from_witness(&builder, t_commitments[idx]); + recursive_T_prev_commitments[idx] = RecursiveCommitment::from_witness(&builder, T_prev_commitments[idx]); } GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - [[maybe_unused]] auto goblin_rec_verifier_output = verifier.verify(tampered_proof, recursive_t_commitments); + [[maybe_unused]] auto goblin_rec_verifier_output = + verifier.verify(tampered_proof, recursive_t_commitments, recursive_T_prev_commitments); EXPECT_FALSE(CircuitChecker::check(builder)); } } @@ -259,7 +299,12 @@ TEST_F(GoblinRecursiveVerifierTests, TranslationEvaluationsFailure) { Builder builder; - auto [proof, verifier_input, t_commitments, recursive_t_commitments] = create_goblin_prover_output(&builder); + auto [proof, + verifier_input, + t_commitments, + T_prev_commitments, + recursive_t_commitments, + recursive_T_prev_commitments] = create_goblin_prover_output(&builder); // Tamper with the evaluation of `op` witness. The index is computed manually. // TODO(https://github.com/AztecProtocol/barretenberg/issues/1298): @@ -268,7 +313,8 @@ TEST_F(GoblinRecursiveVerifierTests, TranslationEvaluationsFailure) proof.eccvm_proof.pre_ipa_proof[op_limb_index] += 1; GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - [[maybe_unused]] auto goblin_rec_verifier_output = verifier.verify(proof, recursive_t_commitments); + [[maybe_unused]] auto goblin_rec_verifier_output = + verifier.verify(proof, recursive_t_commitments, recursive_T_prev_commitments); EXPECT_FALSE(CircuitChecker::check(builder)); } @@ -287,12 +333,17 @@ TEST_F(GoblinRecursiveVerifierTests, TranslatorMergeConsistencyFailure) Builder builder; - auto [proof, verifier_input, t_commitments, recursive_t_commitments] = create_goblin_prover_output(&builder); + auto [proof, + verifier_input, + t_commitments, + T_prev_commitments, + recursive_t_commitments, + recursive_T_prev_commitments] = create_goblin_prover_output(&builder); std::shared_ptr verifier_transcript = std::make_shared(); // Check natively that the proof is correct. - EXPECT_TRUE(std::get<0>(Goblin::verify(proof, t_commitments, verifier_transcript))); + EXPECT_TRUE(Goblin::verify(proof, t_commitments, T_prev_commitments, verifier_transcript)); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1298): // Better recursion testing - create more flexible proof tampering tests. @@ -319,7 +370,8 @@ TEST_F(GoblinRecursiveVerifierTests, TranslatorMergeConsistencyFailure) // Construct and check the Goblin Recursive Verifier circuit GoblinRecursiveVerifier verifier{ &builder, verifier_input }; - [[maybe_unused]] auto goblin_rec_verifier_output = verifier.verify(proof, recursive_t_commitments); + [[maybe_unused]] auto goblin_rec_verifier_output = + verifier.verify(proof, recursive_t_commitments, recursive_T_prev_commitments); EXPECT_FALSE(CircuitChecker::check(builder)); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_recursive_verifier.cpp index 710d838f942a..758ea8052b13 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_recursive_verifier.cpp @@ -64,6 +64,7 @@ MergeRecursiveVerifier_::MergeRecursiveVerifier_(CircuitBuilder* * by the PG verifier with which the Merge verifier shares a transcript * @param t_commitments The subtable commitments data, containing the commitments to t_j read from the transcript * by the PG verifier with which the Merge verifier shares a transcript + * @param T_prev_commitments The full op_queue table commitments after the previous iteration of merge * @return std::pair Pair of the pairing inputs for final verification and the * commitments to the merged tables as read from the proof */ @@ -71,7 +72,8 @@ template std::pair::PairingPoints, typename MergeRecursiveVerifier_::TableCommitments> MergeRecursiveVerifier_::verify_proof(const stdlib::Proof& proof, - const TableCommitments& t_commitments) + const TableCommitments& t_commitments, + const TableCommitments& T_prev_commitments) { using Claims = typename ShplonkVerifier_::LinearCombinationOfClaims; @@ -84,10 +86,8 @@ MergeRecursiveVerifier_::verify_proof(const stdlib::Proof table_commitments; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1473): remove receiving commitment to T_prev - auto T_prev_commitment = transcript->template receive_from_prover("T_PREV_" + std::to_string(idx)); - auto left_table = settings == MergeSettings::PREPEND ? t_commitments[idx] : T_prev_commitment; - auto right_table = settings == MergeSettings::PREPEND ? T_prev_commitment : t_commitments[idx]; + auto left_table = settings == MergeSettings::PREPEND ? t_commitments[idx] : T_prev_commitments[idx]; + auto right_table = settings == MergeSettings::PREPEND ? T_prev_commitments[idx] : t_commitments[idx]; table_commitments.emplace_back(left_table); table_commitments.emplace_back(right_table); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_recursive_verifier.hpp index 984a7bac7712..a4672c398cd8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_recursive_verifier.hpp @@ -37,7 +37,9 @@ template class MergeRecursiveVerifier_ { const std::shared_ptr& transcript = std::make_shared()); [[nodiscard("Pairing points should be accumulated")]] std::pair verify_proof( - const stdlib::Proof& proof, const TableCommitments& t_commitments); + const stdlib::Proof& proof, + const TableCommitments& t_commitments, + const TableCommitments& T_prev_commitments); }; } // namespace bb::stdlib::recursion::goblin diff --git a/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_verifier.test.cpp index 9ef93b02d821..edffb8a1fee7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/merge_verifier/merge_verifier.test.cpp @@ -44,8 +44,8 @@ template class RecursiveMergeVerifierTest : public test static void tamper_with_proof(MergeProof& merge_proof, const TamperProofMode tampering_mode) { const size_t shift_idx = 0; // Index of shift_size in the merge proof - const size_t m_commitment_idx = 5; // Index of first commitment to merged table in merge proof - const size_t l_eval_idx = 50; // Index of first evaluation of l(1/kappa) in merge proof + const size_t m_commitment_idx = 1; // Index of first commitment to merged table in merge proof + const size_t l_eval_idx = 34; // Index of first evaluation of l(1/kappa) in merge proof switch (tampering_mode) { case TamperProofMode::Shift: @@ -87,12 +87,18 @@ template class RecursiveMergeVerifierTest : public test // Subtable values and commitments - needed for (Recursive)MergeVerifier TableCommitments t_commitments; + TableCommitments T_prev_commitments; RecursiveTableCommitments recursive_t_commitments; + RecursiveTableCommitments recursive_T_prev_commitments; auto t_current = op_queue->construct_current_ultra_ops_subtable_columns(); + auto T_prev = op_queue->construct_previous_ultra_ops_table_columns(); for (size_t idx = 0; idx < InnerFlavor::NUM_WIRES; idx++) { - auto cm = merge_prover.pcs_commitment_key.commit(t_current[idx]); - t_commitments[idx] = cm; - recursive_t_commitments[idx] = RecursiveMergeVerifier::Commitment::from_witness(&outer_circuit, cm); + t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]); + T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]); + recursive_t_commitments[idx] = + RecursiveMergeVerifier::Commitment::from_witness(&outer_circuit, t_commitments[idx]); + recursive_T_prev_commitments[idx] = + RecursiveMergeVerifier::Commitment::from_witness(&outer_circuit, T_prev_commitments[idx]); } // Create a recursive merge verification circuit for the merge proof @@ -100,7 +106,7 @@ template class RecursiveMergeVerifierTest : public test verifier.transcript->enable_manifest(); const stdlib::Proof stdlib_merge_proof(outer_circuit, merge_proof); auto [pairing_points, recursive_merged_table_commitments] = - verifier.verify_proof(stdlib_merge_proof, recursive_t_commitments); + verifier.verify_proof(stdlib_merge_proof, recursive_t_commitments, recursive_T_prev_commitments); // Check for a failure flag in the recursive verifier circuit EXPECT_EQ(outer_circuit.failed(), !expected) << outer_circuit.err(); @@ -109,7 +115,8 @@ template class RecursiveMergeVerifierTest : public test // verifier and check that the result agrees. MergeVerifier native_verifier{ settings }; native_verifier.transcript->enable_manifest(); - auto [verified_native, merged_table_commitments] = native_verifier.verify_proof(merge_proof, t_commitments); + auto [verified_native, merged_table_commitments] = + native_verifier.verify_proof(merge_proof, t_commitments, T_prev_commitments); VerifierCommitmentKey pcs_verification_key; bool verified_recursive = pcs_verification_key.pairing_check(pairing_points.P0.get_value(), pairing_points.P1.get_value()); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/special_public_inputs/special_public_inputs.hpp b/barretenberg/cpp/src/barretenberg/stdlib/special_public_inputs/special_public_inputs.hpp index 13c306ec9610..11896150da1c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/special_public_inputs/special_public_inputs.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/special_public_inputs/special_public_inputs.hpp @@ -11,6 +11,7 @@ #include "barretenberg/stdlib/pairing_points.hpp" #include "barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" +#include "barretenberg/stdlib/primitives/databus/databus.hpp" #include "barretenberg/stdlib/primitives/public_input_component/public_input_component.hpp" namespace bb::stdlib::recursion::honk { @@ -32,19 +33,21 @@ class KernelIO { using G1 = Curve::Group; using FF = Curve::ScalarField; using PairingInputs = stdlib::recursion::PairingPoints; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1490): Make PublicInputComponent work with arrays + using TableCommitments = std::array; using PublicPoint = stdlib::PublicInputComponent; using PublicPairingPoints = stdlib::PublicInputComponent; - PairingInputs pairing_inputs; // Inputs {P0, P1} to an EC pairing check - G1 kernel_return_data; // Commitment to the return data of a kernel circuit - G1 app_return_data; // Commitment to the return data of an app circuit - // G1 ecc_op_table; + PairingInputs pairing_inputs; // Inputs {P0, P1} to an EC pairing check + G1 kernel_return_data; // Commitment to the return data of a kernel circuit + G1 app_return_data; // Commitment to the return data of an app circuit + TableCommitments ecc_op_tables; // commitments to merged tables obtained from recursive Merge verification // FF pg_acc_hash; // Total size of the kernel IO public inputs - static constexpr size_t PUBLIC_INPUTS_SIZE = - PairingInputs::PUBLIC_INPUTS_SIZE + G1::PUBLIC_INPUTS_SIZE + G1::PUBLIC_INPUTS_SIZE; + static constexpr size_t PUBLIC_INPUTS_SIZE = PairingInputs::PUBLIC_INPUTS_SIZE + G1::PUBLIC_INPUTS_SIZE + + G1::PUBLIC_INPUTS_SIZE + Builder::NUM_WIRES * G1::PUBLIC_INPUTS_SIZE; /** * @brief Reconstructs the IO components from a public inputs array. @@ -62,8 +65,10 @@ class KernelIO { index += G1::PUBLIC_INPUTS_SIZE; app_return_data = PublicPoint::reconstruct(public_inputs, PublicComponentKey{ index }); index += G1::PUBLIC_INPUTS_SIZE; - // ecc_op_table = PublicPoint::reconstruct(public_inputs, PublicComponentKey{ index }); - // index += G1::PUBLIC_INPUTS_SIZE; + for (auto& table_commitment : ecc_op_tables) { + table_commitment = PublicPoint::reconstruct(public_inputs, PublicComponentKey{ index }); + index += G1::PUBLIC_INPUTS_SIZE; + } // pg_acc_hash = FF::reconstruct(public_inputs, PublicComponentKey{ index }); } @@ -76,13 +81,34 @@ class KernelIO { pairing_inputs.set_public(); kernel_return_data.set_public(); app_return_data.set_public(); - // ecc_op_table.set_public(); + for (auto& table_commitment : ecc_op_tables) { + table_commitment.set_public(); + } // pg_acc_hash.set_public(); // Finalize the public inputs to ensure no more public inputs can be added hereafter. Builder* builder = pairing_inputs.P0.get_context(); builder->finalize_public_inputs(); } + + /** + * @brief Add default public inputs when they are not present + * + */ + static void add_default(Builder& builder) + { + PairingInputs::add_default_to_public_inputs(builder); + G1 kernel_return_data = DataBusDepot::construct_default_commitment(builder); + kernel_return_data.set_public(); + G1 app_return_data = DataBusDepot::construct_default_commitment(builder); + app_return_data.set_public(); + TableCommitments ecc_op_tables; + for (auto& table_commitment : ecc_op_tables) { + table_commitment = G1(DEFAULT_ECC_COMMITMENT); + table_commitment.convert_constant_to_fixed_witness(&builder); + table_commitment.set_public(); + } + }; }; /** @@ -149,13 +175,13 @@ template class HidingKernelIO { using G1 = Curve::Group; using FF = Curve::ScalarField; using PairingInputs = stdlib::recursion::PairingPoints; + using TableCommitments = std::array; using PublicPoint = stdlib::PublicInputComponent; using PublicPairingPoints = stdlib::PublicInputComponent; - PairingInputs pairing_inputs; // Inputs {P0, P1} to an EC pairing check - std::array - ecc_op_tables; // commitments to merged tables obtained from final Merge verification + PairingInputs pairing_inputs; // Inputs {P0, P1} to an EC pairing check + TableCommitments ecc_op_tables; // commitments to merged tables obtained from final Merge verification // Total size of the IO public inputs static constexpr size_t PUBLIC_INPUTS_SIZE = @@ -194,9 +220,19 @@ template class HidingKernelIO { builder->finalize_public_inputs(); } - static std::array empty_ecc_op_tables(Builder& builder) + /** + * @brief Construct commitments to empty subtables + * + * @details In the first iteration of the Merge, the verifier sets the commitments to the previous full state of the + * op_queue equal to the commitments to the empty tables. This ensures that prover cannot lie, as the starting point + * of the merge is fixed. + * + * @param builder + * @return TableCommitments + */ + static TableCommitments empty_ecc_op_tables(Builder& builder) { - std::array empty_tables; + TableCommitments empty_tables; for (auto& table_commitment : empty_tables) { table_commitment = G1::point_at_infinity(&builder); } @@ -204,9 +240,9 @@ template class HidingKernelIO { return empty_tables; } - static std::array default_ecc_op_tables(Builder& builder) + static TableCommitments default_ecc_op_tables(Builder& builder) { - std::array default_tables; + TableCommitments default_tables; for (auto& table_commitment : default_tables) { table_commitment = G1(DEFAULT_ECC_COMMITMENT); table_commitment.convert_constant_to_fixed_witness(&builder); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/special_public_inputs/special_public_inputs.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/special_public_inputs/special_public_inputs.test.cpp index 1ef8af5f68fd..fcd41bf4c1f5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/special_public_inputs/special_public_inputs.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/special_public_inputs/special_public_inputs.test.cpp @@ -21,10 +21,16 @@ TEST_F(SpecialPublicInputsTests, Basic) using G1Native = Curve::GroupNative::affine_element; using FFNative = Curve::ScalarFieldNative; + static constexpr size_t NUM_WIRES = Builder::NUM_WIRES; + G1Native P0_val = G1Native::random_element(); G1Native P1_val = G1Native::random_element(); G1Native kernel_return_data_val = G1Native::random_element(); G1Native app_return_data_val = G1Native::random_element(); + std::array ecc_op_tables_val; + for (auto& commitment : ecc_op_tables_val) { + commitment = G1Native::random_element(); + } // Store the public inputs of the first circuit to be used by the second std::vector public_inputs; @@ -39,6 +45,9 @@ TEST_F(SpecialPublicInputsTests, Basic) kernel_output.pairing_inputs = pairing_inputs; kernel_output.kernel_return_data = G1::from_witness(&builder, kernel_return_data_val); kernel_output.app_return_data = G1::from_witness(&builder, app_return_data_val); + for (auto [table_commitment, table_val] : zip_view(kernel_output.ecc_op_tables, ecc_op_tables_val)) { + table_commitment = G1::from_witness(&builder, table_val); + } // Propagate the kernel output via the public inputs kernel_output.set_public(); @@ -67,6 +76,9 @@ TEST_F(SpecialPublicInputsTests, Basic) EXPECT_EQ(kernel_input.pairing_inputs.P1.get_value(), P1_val); EXPECT_EQ(kernel_input.kernel_return_data.get_value(), kernel_return_data_val); EXPECT_EQ(kernel_input.app_return_data.get_value(), app_return_data_val); + for (auto [reconstructed_commitment, commitment] : zip_view(kernel_input.ecc_op_tables, ecc_op_tables_val)) { + EXPECT_EQ(reconstructed_commitment.get_value(), commitment); + } } } @@ -265,13 +277,11 @@ TEST_F(SpecialPublicInputsTests, HidingKernel) // Set the output values PairingInputs pairing_inputs{ G1::from_witness(&builder, P0_val), G1::from_witness(&builder, P1_val) }; - std::array ecc_op_tables; - for (size_t idx = 0; idx < NUM_WIRES; idx++) { - ecc_op_tables[idx] = G1::from_witness(&builder, ecc_op_tables_val[idx]); - } - hiding_output.pairing_inputs = pairing_inputs; - hiding_output.ecc_op_tables = ecc_op_tables; + + for (auto [table_commitment, table_val] : zip_view(hiding_output.ecc_op_tables, ecc_op_tables_val)) { + table_commitment = G1::from_witness(&builder, table_val); + } // Propagate the kernel output via the public inputs hiding_output.set_public(); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index dbc706969f06..3d15dafbcb30 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -84,12 +84,15 @@ template class MegaHonkTests : public ::testing::Test { // Construct Merge commitments MergeVerifier::TableCommitments t_commitments; + MergeVerifier::TableCommitments T_prev_commitments; auto t_current = op_queue->construct_current_ultra_ops_subtable_columns(); + auto T_prev = op_queue->construct_previous_ultra_ops_table_columns(); for (size_t idx = 0; idx < Flavor::NUM_WIRES; idx++) { t_commitments[idx] = merge_prover.pcs_commitment_key.commit(t_current[idx]); + T_prev_commitments[idx] = merge_prover.pcs_commitment_key.commit(T_prev[idx]); } - auto [verified, _] = merge_verifier.verify_proof(merge_proof, t_commitments); + auto [verified, _] = merge_verifier.verify_proof(merge_proof, t_commitments, T_prev_commitments); return verified; } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 20f49ec98e0e..e1f4c9095c1a 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -90,10 +90,6 @@ MergeProver::MergeProof MergeProver::construct_proof() // TODO(https://github.com/AztecProtocol/barretenberg/issues/1473): remove generation of commitment to T_prev // Compute commitments [T_prev], [m_j], [g_j], and send to the verifier for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - // Note: This is hacky at the moment because the prover still needs to commit to T_prev. Once we connect two - // steps of the Merge, T_prev will not be sent by the Merge prover, so the following lines will be removed - auto previous_table = settings == MergeSettings::PREPEND ? right_table[idx] : left_table[idx]; - transcript->send_to_verifier("T_PREV" + std::to_string(idx), pcs_commitment_key.commit(previous_table)); transcript->send_to_verifier("MERGED_TABLE_" + std::to_string(idx), pcs_commitment_key.commit(merged_table[idx])); transcript->send_to_verifier("LEFT_TABLE_REVERSED_" + std::to_string(idx), diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp index 96f4637fb15f..a5a0a08400e5 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp @@ -57,11 +57,12 @@ MergeVerifier::MergeVerifier(const MergeSettings settings, const std::shared_ptr * @param proof * @param t_commitments The subtable commitments data, containing the commitments to t_j read from the transcript * by the PG verifier with which the Merge verifier shares a transcript + * @param T_prev_commitments The full op_queue table commitments after the previous iteration of merge * @return std::pair Pair of verification result and the commitments to the merged tables as * read from the proof */ std::pair MergeVerifier::verify_proof( - const HonkProof& proof, const TableCommitments& t_commitments) + const HonkProof& proof, const TableCommitments& t_commitments, const TableCommitments& T_prev_commitments) { using Claims = typename ShplonkVerifier_::LinearCombinationOfClaims; @@ -74,10 +75,8 @@ std::pair MergeVerifier::verify_ // The vector is composed of: [l_1], [r_1], [m_1], [g_1], ..., [l_4], [r_4], [m_4], [g_4] std::vector table_commitments; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1473): remove receiving commitment to T_prev - auto T_prev_commitment = transcript->template receive_from_prover("T_PREV_" + std::to_string(idx)); - auto left_table = settings == MergeSettings::PREPEND ? t_commitments[idx] : T_prev_commitment; - auto right_table = settings == MergeSettings::PREPEND ? T_prev_commitment : t_commitments[idx]; + auto left_table = settings == MergeSettings::PREPEND ? t_commitments[idx] : T_prev_commitments[idx]; + auto right_table = settings == MergeSettings::PREPEND ? T_prev_commitments[idx] : t_commitments[idx]; table_commitments.emplace_back(left_table); table_commitments.emplace_back(right_table); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp index 906b8d98036e..36e5c80856f7 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp @@ -39,7 +39,9 @@ class MergeVerifier { explicit MergeVerifier(const MergeSettings settings = MergeSettings::PREPEND, const std::shared_ptr& transcript = std::make_shared()); - std::pair verify_proof(const HonkProof& proof, const TableCommitments& t_commitments); + std::pair verify_proof(const HonkProof& proof, + const TableCommitments& t_commitments, + const TableCommitments& T_prev_commitments); }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp index 2096b5570eb0..e5b635ee1801 100644 --- a/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/vm2/constraining/recursion/goblin_avm_recursive_verifier.hpp @@ -139,9 +139,12 @@ class AvmGoblinRecursiveVerifier { // Recursively verify the goblin proof\pi_G in the Ultra circuit TableCommitments t_commitments = mega_verifier.key->witness_commitments.get_ecc_op_wires().get_copy(); + TableCommitments T_prev_commitments = + stdlib::recursion::honk::HidingKernelIO::empty_ecc_op_tables( + ultra_builder); // Empty ecc op tables because there is only one layer of Goblin GoblinRecursiveVerifier goblin_verifier{ &ultra_builder, inner_output.goblin_vk, transcript }; GoblinRecursiveVerifierOutput goblin_verifier_output = - goblin_verifier.verify(inner_output.goblin_proof, t_commitments); + goblin_verifier.verify(inner_output.goblin_proof, t_commitments, T_prev_commitments); goblin_verifier_output.points_accumulator.aggregate(mega_verifier_output.points_accumulator); // Validate the consistency of the AVM2 verifier inputs {\pi, pub_inputs, VK}_{AVM2} between the inner (Mega) @@ -213,6 +216,8 @@ class AvmGoblinRecursiveVerifier { // Public inputs IO inputs; inputs.pairing_inputs = points_accumulator; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1489): Can we avoid paying for these public inputs + // given that they are not used? inputs.ecc_op_tables = stdlib::recursion::honk::HidingKernelIO::default_ecc_op_tables( mega_builder); // There is only one layer of Goblin, so the verifier will set T_prev // to the empty table and disregard this value