From 1139308d6d90ade1868278915901f86b08daedda Mon Sep 17 00:00:00 2001 From: Lucas Xia Date: Mon, 18 Mar 2024 17:14:18 -0600 Subject: [PATCH] refactor: share verifier rounds (#4849) Addresses https://github.com/AztecProtocol/barretenberg/issues/882, but doesn't fully close it since recursive verifiers aren't shared. Creates OinkVerifier which executes all of the pre-sumcheck logic in the folding and ultra honk verifiers. This does not handle the recursive verifiers. I also create OinkOutput which serves as the output state that is passed from OinkVerifier back to UltraVerifier or ProtogalaxyVerifier. --- .../src/barretenberg/flavor/goblin_ultra.hpp | 1 + .../protogalaxy/protogalaxy_verifier.cpp | 76 +--------- .../protogalaxy_recursive_verifier.test.cpp | 6 +- .../barretenberg/ultra_honk/oink_verifier.cpp | 139 ++++++++++++++++++ .../barretenberg/ultra_honk/oink_verifier.hpp | 60 ++++++++ .../ultra_honk/ultra_verifier.cpp | 84 +---------- .../ultra_honk/ultra_verifier.hpp | 1 - 7 files changed, 217 insertions(+), 150 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp create mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp index 32842ebe9b5..39f9529314a 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp @@ -489,6 +489,7 @@ class GoblinUltraFlavor { /** * @brief Derived class that defines proof structure for GoblinUltra proofs, as well as supporting functions. * Note: Made generic for use in GoblinUltraRecursive. + * TODO(https://github.com/AztecProtocol/barretenberg/issues/877): Remove this Commitment template parameter */ template class Transcript_ : public NativeTranscript { public: diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index cf08f67d30a..2f82d72cc0c 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -1,81 +1,17 @@ #include "protogalaxy_verifier.hpp" #include "barretenberg/proof_system/library/grand_product_delta.hpp" +#include "barretenberg/ultra_honk/oink_verifier.hpp" namespace bb { template void ProtoGalaxyVerifier_::receive_and_finalise_instance(const std::shared_ptr& inst, const std::string& domain_separator) { - // Get circuit parameters and the public inputs - inst->verification_key->circuit_size = - transcript->template receive_from_prover(domain_separator + "_circuit_size"); - inst->verification_key->log_circuit_size = - static_cast(numeric::get_msb(inst->verification_key->circuit_size)); - inst->verification_key->num_public_inputs = - transcript->template receive_from_prover(domain_separator + "_public_input_size"); - inst->verification_key->pub_inputs_offset = - transcript->template receive_from_prover(domain_separator + "_pub_inputs_offset"); - inst->verification_key->public_inputs.clear(); - for (size_t i = 0; i < inst->verification_key->num_public_inputs; ++i) { - auto public_input_i = - transcript->template receive_from_prover(domain_separator + "_public_input_" + std::to_string(i)); - inst->verification_key->public_inputs.emplace_back(public_input_i); - } - - // Get commitments to first three wire polynomials - auto labels = inst->commitment_labels; - auto& witness_commitments = inst->witness_commitments; - witness_commitments.w_l = transcript->template receive_from_prover(domain_separator + "_" + labels.w_l); - witness_commitments.w_r = transcript->template receive_from_prover(domain_separator + "_" + labels.w_r); - witness_commitments.w_o = transcript->template receive_from_prover(domain_separator + "_" + labels.w_o); - - if constexpr (IsGoblinFlavor) { - // Get commitments to the ECC wire polynomials and databus polynomials - witness_commitments.ecc_op_wire_1 = - transcript->template receive_from_prover(domain_separator + "_" + labels.ecc_op_wire_1); - witness_commitments.ecc_op_wire_2 = - transcript->template receive_from_prover(domain_separator + "_" + labels.ecc_op_wire_2); - witness_commitments.ecc_op_wire_3 = - transcript->template receive_from_prover(domain_separator + "_" + labels.ecc_op_wire_3); - witness_commitments.ecc_op_wire_4 = - transcript->template receive_from_prover(domain_separator + "_" + labels.ecc_op_wire_4); - witness_commitments.calldata = - transcript->template receive_from_prover(domain_separator + "_" + labels.calldata); - witness_commitments.calldata_read_counts = - transcript->template receive_from_prover(domain_separator + "_" + labels.calldata_read_counts); - } - - // Get challenge for sorted list batching and wire four memory records commitment - auto eta = transcript->template get_challenge(domain_separator + "_eta"); - witness_commitments.sorted_accum = - transcript->template receive_from_prover(domain_separator + "_" + labels.sorted_accum); - witness_commitments.w_4 = transcript->template receive_from_prover(domain_separator + "_" + labels.w_4); - - // Get permutation challenges and commitment to permutation and lookup grand products - auto [beta, gamma] = - transcript->template get_challenges(domain_separator + "_beta", domain_separator + "_gamma"); - - if constexpr (IsGoblinFlavor) { - // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomial - witness_commitments.lookup_inverses = transcript->template receive_from_prover( - domain_separator + "_" + commitment_labels.lookup_inverses); - } - - witness_commitments.z_perm = - transcript->template receive_from_prover(domain_separator + "_" + labels.z_perm); - witness_commitments.z_lookup = - transcript->template receive_from_prover(domain_separator + "_" + labels.z_lookup); - - // Compute correction terms for grand products - const FF public_input_delta = compute_public_input_delta(inst->verification_key->public_inputs, - beta, - gamma, - inst->verification_key->circuit_size, - inst->verification_key->pub_inputs_offset); - const FF lookup_grand_product_delta = - compute_lookup_grand_product_delta(beta, gamma, inst->verification_key->circuit_size); - inst->relation_parameters = - RelationParameters{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta }; + auto& key = inst->verification_key; + OinkVerifier oink_verifier{ key, transcript, domain_separator + '_' }; + auto [relation_parameters, witness_commitments] = oink_verifier.verify(); + inst->relation_parameters = relation_parameters; + inst->witness_commitments = witness_commitments; // Get the relation separation challenges for (size_t idx = 0; idx < NUM_SUBRELATIONS - 1; idx++) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.test.cpp index 6bb9546696d..27583976cb8 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.test.cpp @@ -210,7 +210,8 @@ template class ProtoGalaxyRecursiveTests : public tes auto native_folding_manifest = native_folding_verifier.transcript->get_manifest(); for (size_t i = 0; i < recursive_folding_manifest.size(); ++i) { - EXPECT_EQ(recursive_folding_manifest[i], native_folding_manifest[i]); + EXPECT_EQ(recursive_folding_manifest[i], native_folding_manifest[i]) + << "Recursive Verifier/Verifier manifest discrepency in round " << i; } // Check for a failure flag in the recursive verifier circuit @@ -276,7 +277,8 @@ template class ProtoGalaxyRecursiveTests : public tes auto native_folding_manifest = native_folding_verifier.transcript->get_manifest(); for (size_t i = 0; i < recursive_folding_manifest.size(); ++i) { - EXPECT_EQ(recursive_folding_manifest[i], native_folding_manifest[i]); + EXPECT_EQ(recursive_folding_manifest[i], native_folding_manifest[i]) + << "Recursive Verifier/Verifier manifest discrepency in round " << i; } DeciderProver decider_prover(folding_proof.accumulator); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp new file mode 100644 index 00000000000..ac285ad0753 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -0,0 +1,139 @@ +#include "barretenberg/ultra_honk/oink_verifier.hpp" + +namespace bb { + +/** + * @brief Oink Verifier function that runs all the rounds of the verifier + * @details Returns the witness commitments and relation_parameters + * @tparam Flavor + * @return OinkOutput + */ +template OinkOutput OinkVerifier::verify() +{ + // Execute the Verifier rounds + execute_preamble_round(); + execute_wire_commitments_round(); + execute_sorted_list_accumulator_round(); + execute_log_derivative_inverse_round(); + execute_grand_product_computation_round(); + + return OinkOutput{ + .relation_parameters = relation_parameters, + .commitments = witness_comms, + }; +} + +/** + * @brief Get circuit size, public input size, and public inputs from transcript + * + */ +template void OinkVerifier::execute_preamble_round() +{ + // TODO(Adrian): Change the initialization of the transcript to take the VK hash? + const auto circuit_size = transcript->template receive_from_prover(domain_separator + "circuit_size"); + const auto public_input_size = + transcript->template receive_from_prover(domain_separator + "public_input_size"); + const auto pub_inputs_offset = + transcript->template receive_from_prover(domain_separator + "pub_inputs_offset"); + + ASSERT(circuit_size == key->circuit_size); + ASSERT(public_input_size == key->num_public_inputs); + ASSERT(pub_inputs_offset == key->pub_inputs_offset); + + key->public_inputs.clear(); + for (size_t i = 0; i < public_input_size; ++i) { + auto public_input_i = + transcript->template receive_from_prover(domain_separator + "public_input_" + std::to_string(i)); + key->public_inputs.emplace_back(public_input_i); + } +} + +/** + * @brief Get the wire polynomials (part of the witness), with the exception of the fourth wire, which is + * only received after adding memory records. In the Goblin Flavor, we also receive the ECC OP wires and the + * DataBus columns. + */ +template void OinkVerifier::execute_wire_commitments_round() +{ + // Get commitments to first three wire polynomials + witness_comms.w_l = transcript->template receive_from_prover(domain_separator + comm_labels.w_l); + witness_comms.w_r = transcript->template receive_from_prover(domain_separator + comm_labels.w_r); + witness_comms.w_o = transcript->template receive_from_prover(domain_separator + comm_labels.w_o); + + // If Goblin, get commitments to ECC op wire polynomials and DataBus columns + if constexpr (IsGoblinFlavor) { + witness_comms.ecc_op_wire_1 = + transcript->template receive_from_prover(domain_separator + comm_labels.ecc_op_wire_1); + witness_comms.ecc_op_wire_2 = + transcript->template receive_from_prover(domain_separator + comm_labels.ecc_op_wire_2); + witness_comms.ecc_op_wire_3 = + transcript->template receive_from_prover(domain_separator + comm_labels.ecc_op_wire_3); + witness_comms.ecc_op_wire_4 = + transcript->template receive_from_prover(domain_separator + comm_labels.ecc_op_wire_4); + witness_comms.calldata = + transcript->template receive_from_prover(domain_separator + comm_labels.calldata); + witness_comms.calldata_read_counts = + transcript->template receive_from_prover(domain_separator + comm_labels.calldata_read_counts); + } +} + +/** + * @brief Get sorted witness-table accumulator and fourth wire commitments + * + */ +template void OinkVerifier::execute_sorted_list_accumulator_round() +{ + // Get challenge for sorted list batching and wire four memory records + FF eta = transcript->template get_challenge(domain_separator + "eta"); + relation_parameters.eta = eta; + + // Get commitments to sorted list accumulator and fourth wire + witness_comms.sorted_accum = + transcript->template receive_from_prover(domain_separator + comm_labels.sorted_accum); + witness_comms.w_4 = transcript->template receive_from_prover(domain_separator + comm_labels.w_4); +} + +/** + * @brief Get log derivative inverse polynomial and its commitment, if GoblinFlavor + * + */ +template void OinkVerifier::execute_log_derivative_inverse_round() +{ + // Get permutation challenges + auto [beta, gamma] = transcript->template get_challenges(domain_separator + "beta", domain_separator + "gamma"); + relation_parameters.beta = beta; + relation_parameters.gamma = gamma; + // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomial + if constexpr (IsGoblinFlavor) { + witness_comms.lookup_inverses = + transcript->template receive_from_prover(domain_separator + comm_labels.lookup_inverses); + } +} + +/** + * @brief Compute lookup grand product delta and get permutation and lookup grand product commitments + * + */ +template void OinkVerifier::execute_grand_product_computation_round() +{ + const FF public_input_delta = compute_public_input_delta(key->public_inputs, + relation_parameters.beta, + relation_parameters.gamma, + key->circuit_size, + key->pub_inputs_offset); + const FF lookup_grand_product_delta = + compute_lookup_grand_product_delta(relation_parameters.beta, relation_parameters.gamma, key->circuit_size); + + relation_parameters.public_input_delta = public_input_delta; + relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; + + // Get commitment to permutation and lookup grand products + witness_comms.z_perm = transcript->template receive_from_prover(domain_separator + comm_labels.z_perm); + witness_comms.z_lookup = + transcript->template receive_from_prover(domain_separator + comm_labels.z_lookup); +} + +template class OinkVerifier; +template class OinkVerifier; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp new file mode 100644 index 00000000000..2b7a72b9175 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/flavor/goblin_ultra.hpp" +#include "barretenberg/flavor/ultra.hpp" +#include "barretenberg/proof_system/library/grand_product_delta.hpp" +#include "barretenberg/relations/relation_parameters.hpp" + +namespace bb { + +template struct OinkOutput { + bb::RelationParameters relation_parameters; + typename Flavor::WitnessCommitments commitments; +}; + +/** + * @brief Verifier class for all the presumcheck rounds, which are shared between the folding verifier and ultra + * verifier. + * @details This class contains execute_preamble_round(), execute_wire_commitments_round(), + * execute_sorted_list_accumulator_round(), execute_log_derivative_inverse_round(), and + * execute_grand_product_computation_round(). + * + * @tparam Flavor + */ +template class OinkVerifier { + using VerificationKey = typename Flavor::VerificationKey; + using WitnessCommitments = typename Flavor::WitnessCommitments; + using Transcript = typename Flavor::Transcript; + using FF = typename Flavor::FF; + using Commitment = typename Flavor::Commitment; + + public: + std::shared_ptr transcript; + std::shared_ptr key; + std::string domain_separator; + typename Flavor::CommitmentLabels comm_labels; + bb::RelationParameters relation_parameters; + WitnessCommitments witness_comms; + + OinkVerifier(const std::shared_ptr& verifier_key, + const std::shared_ptr& transcript, + std::string domain_separator = "") + : transcript(transcript) + , key(verifier_key) + , domain_separator(std::move(domain_separator)) + {} + + OinkOutput verify(); + + void execute_preamble_round(); + + void execute_wire_commitments_round(); + + void execute_sorted_list_accumulator_round(); + + void execute_log_derivative_inverse_round(); + + void execute_grand_product_computation_round(); +}; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index bcc7fadc333..34b197b06b8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -2,6 +2,7 @@ #include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/transcript/transcript.hpp" +#include "barretenberg/ultra_honk/oink_verifier.hpp" namespace bb { template @@ -31,7 +32,6 @@ UltraVerifier_::UltraVerifier_(UltraVerifier_&& other) template UltraVerifier_& UltraVerifier_::operator=(UltraVerifier_&& other) { key = other.key; - commitments.clear(); return *this; } @@ -42,92 +42,22 @@ template UltraVerifier_& UltraVerifier_::opera template bool UltraVerifier_::verify_proof(const HonkProof& proof) { using FF = typename Flavor::FF; - using Commitment = typename Flavor::Commitment; using PCS = typename Flavor::PCS; using ZeroMorph = ZeroMorphVerifier_; using VerifierCommitments = typename Flavor::VerifierCommitments; - using CommitmentLabels = typename Flavor::CommitmentLabels; - - bb::RelationParameters relation_parameters; transcript = std::make_shared(proof); - VerifierCommitments commitments{ key }; - CommitmentLabels commitment_labels; - - // TODO(Adrian): Change the initialization of the transcript to take the VK hash? - const auto circuit_size = transcript->template receive_from_prover("circuit_size"); - const auto public_input_size = transcript->template receive_from_prover("public_input_size"); - const auto pub_inputs_offset = transcript->template receive_from_prover("pub_inputs_offset"); + OinkVerifier oink_verifier{ key, transcript }; + auto [relation_parameters, witness_commitments] = oink_verifier.verify(); - if (circuit_size != key->circuit_size) { - return false; - } - if (public_input_size != key->num_public_inputs) { - return false; + // Copy the witness_commitments over to the VerifierCommitments + for (auto [wit_comm_1, wit_comm_2] : zip_view(commitments.get_witness(), witness_commitments.get_all())) { + wit_comm_1 = wit_comm_2; } - if (pub_inputs_offset != key->pub_inputs_offset) { - return false; - } - - std::vector public_inputs; - for (size_t i = 0; i < public_input_size; ++i) { - auto public_input_i = transcript->template receive_from_prover("public_input_" + std::to_string(i)); - public_inputs.emplace_back(public_input_i); - } - - // Get commitments to first three wire polynomials - commitments.w_l = transcript->template receive_from_prover(commitment_labels.w_l); - commitments.w_r = transcript->template receive_from_prover(commitment_labels.w_r); - commitments.w_o = transcript->template receive_from_prover(commitment_labels.w_o); - - // If Goblin, get commitments to ECC op wire polynomials and DataBus columns - if constexpr (IsGoblinFlavor) { - commitments.ecc_op_wire_1 = - transcript->template receive_from_prover(commitment_labels.ecc_op_wire_1); - commitments.ecc_op_wire_2 = - transcript->template receive_from_prover(commitment_labels.ecc_op_wire_2); - commitments.ecc_op_wire_3 = - transcript->template receive_from_prover(commitment_labels.ecc_op_wire_3); - commitments.ecc_op_wire_4 = - transcript->template receive_from_prover(commitment_labels.ecc_op_wire_4); - commitments.calldata = transcript->template receive_from_prover(commitment_labels.calldata); - commitments.calldata_read_counts = - transcript->template receive_from_prover(commitment_labels.calldata_read_counts); - } - - // Get challenge for sorted list batching and wire four memory records - FF eta = transcript->template get_challenge("eta"); - relation_parameters.eta = eta; - - // Get commitments to sorted list accumulator and fourth wire - commitments.sorted_accum = transcript->template receive_from_prover(commitment_labels.sorted_accum); - commitments.w_4 = transcript->template receive_from_prover(commitment_labels.w_4); - - // Get permutation challenges - auto [beta, gamma] = transcript->template get_challenges("beta", "gamma"); - - // If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomial - if constexpr (IsGoblinFlavor) { - commitments.lookup_inverses = - transcript->template receive_from_prover(commitment_labels.lookup_inverses); - } - - const FF public_input_delta = - compute_public_input_delta(public_inputs, beta, gamma, circuit_size, pub_inputs_offset); - const FF lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, circuit_size); - - relation_parameters.beta = beta; - relation_parameters.gamma = gamma; - relation_parameters.public_input_delta = public_input_delta; - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; - - // Get commitment to permutation and lookup grand products - commitments.z_perm = transcript->template receive_from_prover(commitment_labels.z_perm); - commitments.z_lookup = transcript->template receive_from_prover(commitment_labels.z_lookup); // Execute Sumcheck Verifier - const size_t log_circuit_size = numeric::get_msb(circuit_size); + const size_t log_circuit_size = numeric::get_msb(key->circuit_size); auto sumcheck = SumcheckVerifier(log_circuit_size, transcript); RelationSeparator alphas; for (size_t idx = 0; idx < alphas.size(); idx++) { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp index d9f17971848..ee8e31c3ec4 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.hpp @@ -27,7 +27,6 @@ template class UltraVerifier_ { bool verify_proof(const HonkProof& proof); std::shared_ptr key; - std::map commitments; std::shared_ptr transcript; };