Skip to content

Commit

Permalink
refactor: share verifier rounds (#4849)
Browse files Browse the repository at this point in the history
Addresses AztecProtocol/barretenberg#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.
  • Loading branch information
lucasxia01 authored Mar 18, 2024
1 parent 85ac726 commit 1139308
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 150 deletions.
1 change: 1 addition & 0 deletions barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename Commitment> class Transcript_ : public NativeTranscript {
public:
Expand Down
Original file line number Diff line number Diff line change
@@ -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 <class VerifierInstances>
void ProtoGalaxyVerifier_<VerifierInstances>::receive_and_finalise_instance(const std::shared_ptr<Instance>& inst,
const std::string& domain_separator)
{
// Get circuit parameters and the public inputs
inst->verification_key->circuit_size =
transcript->template receive_from_prover<uint32_t>(domain_separator + "_circuit_size");
inst->verification_key->log_circuit_size =
static_cast<size_t>(numeric::get_msb(inst->verification_key->circuit_size));
inst->verification_key->num_public_inputs =
transcript->template receive_from_prover<uint32_t>(domain_separator + "_public_input_size");
inst->verification_key->pub_inputs_offset =
transcript->template receive_from_prover<uint32_t>(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<FF>(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<Commitment>(domain_separator + "_" + labels.w_l);
witness_commitments.w_r = transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.w_r);
witness_commitments.w_o = transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.w_o);

if constexpr (IsGoblinFlavor<Flavor>) {
// Get commitments to the ECC wire polynomials and databus polynomials
witness_commitments.ecc_op_wire_1 =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.ecc_op_wire_1);
witness_commitments.ecc_op_wire_2 =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.ecc_op_wire_2);
witness_commitments.ecc_op_wire_3 =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.ecc_op_wire_3);
witness_commitments.ecc_op_wire_4 =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.ecc_op_wire_4);
witness_commitments.calldata =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.calldata);
witness_commitments.calldata_read_counts =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.calldata_read_counts);
}

// Get challenge for sorted list batching and wire four memory records commitment
auto eta = transcript->template get_challenge<FF>(domain_separator + "_eta");
witness_commitments.sorted_accum =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.sorted_accum);
witness_commitments.w_4 = transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.w_4);

// Get permutation challenges and commitment to permutation and lookup grand products
auto [beta, gamma] =
transcript->template get_challenges<FF>(domain_separator + "_beta", domain_separator + "_gamma");

if constexpr (IsGoblinFlavor<Flavor>) {
// If Goblin (i.e. using DataBus) receive commitments to log-deriv inverses polynomial
witness_commitments.lookup_inverses = transcript->template receive_from_prover<Commitment>(
domain_separator + "_" + commitment_labels.lookup_inverses);
}

witness_commitments.z_perm =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.z_perm);
witness_commitments.z_lookup =
transcript->template receive_from_prover<Commitment>(domain_separator + "_" + labels.z_lookup);

// Compute correction terms for grand products
const FF public_input_delta = compute_public_input_delta<Flavor>(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<FF>(beta, gamma, inst->verification_key->circuit_size);
inst->relation_parameters =
RelationParameters<FF>{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta };
auto& key = inst->verification_key;
OinkVerifier<Flavor> 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++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ template <typename RecursiveFlavor> 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
Expand Down Expand Up @@ -276,7 +277,8 @@ template <typename RecursiveFlavor> 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);
Expand Down
139 changes: 139 additions & 0 deletions barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp
Original file line number Diff line number Diff line change
@@ -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<Flavor>
*/
template <IsUltraFlavor Flavor> OinkOutput<Flavor> OinkVerifier<Flavor>::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<Flavor>{
.relation_parameters = relation_parameters,
.commitments = witness_comms,
};
}

/**
* @brief Get circuit size, public input size, and public inputs from transcript
*
*/
template <IsUltraFlavor Flavor> void OinkVerifier<Flavor>::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<uint32_t>(domain_separator + "circuit_size");
const auto public_input_size =
transcript->template receive_from_prover<uint32_t>(domain_separator + "public_input_size");
const auto pub_inputs_offset =
transcript->template receive_from_prover<uint32_t>(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<FF>(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 <IsUltraFlavor Flavor> void OinkVerifier<Flavor>::execute_wire_commitments_round()
{
// Get commitments to first three wire polynomials
witness_comms.w_l = transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.w_l);
witness_comms.w_r = transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.w_r);
witness_comms.w_o = transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.w_o);

// If Goblin, get commitments to ECC op wire polynomials and DataBus columns
if constexpr (IsGoblinFlavor<Flavor>) {
witness_comms.ecc_op_wire_1 =
transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.ecc_op_wire_1);
witness_comms.ecc_op_wire_2 =
transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.ecc_op_wire_2);
witness_comms.ecc_op_wire_3 =
transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.ecc_op_wire_3);
witness_comms.ecc_op_wire_4 =
transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.ecc_op_wire_4);
witness_comms.calldata =
transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.calldata);
witness_comms.calldata_read_counts =
transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.calldata_read_counts);
}
}

/**
* @brief Get sorted witness-table accumulator and fourth wire commitments
*
*/
template <IsUltraFlavor Flavor> void OinkVerifier<Flavor>::execute_sorted_list_accumulator_round()
{
// Get challenge for sorted list batching and wire four memory records
FF eta = transcript->template get_challenge<FF>(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<Commitment>(domain_separator + comm_labels.sorted_accum);
witness_comms.w_4 = transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.w_4);
}

/**
* @brief Get log derivative inverse polynomial and its commitment, if GoblinFlavor
*
*/
template <IsUltraFlavor Flavor> void OinkVerifier<Flavor>::execute_log_derivative_inverse_round()
{
// Get permutation challenges
auto [beta, gamma] = transcript->template get_challenges<FF>(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<Flavor>) {
witness_comms.lookup_inverses =
transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.lookup_inverses);
}
}

/**
* @brief Compute lookup grand product delta and get permutation and lookup grand product commitments
*
*/
template <IsUltraFlavor Flavor> void OinkVerifier<Flavor>::execute_grand_product_computation_round()
{
const FF public_input_delta = compute_public_input_delta<Flavor>(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<FF>(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<Commitment>(domain_separator + comm_labels.z_perm);
witness_comms.z_lookup =
transcript->template receive_from_prover<Commitment>(domain_separator + comm_labels.z_lookup);
}

template class OinkVerifier<UltraFlavor>;
template class OinkVerifier<GoblinUltraFlavor>;

} // namespace bb
60 changes: 60 additions & 0 deletions barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.hpp
Original file line number Diff line number Diff line change
@@ -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 <IsUltraFlavor Flavor> struct OinkOutput {
bb::RelationParameters<typename Flavor::FF> 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 <IsUltraFlavor Flavor> 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> transcript;
std::shared_ptr<VerificationKey> key;
std::string domain_separator;
typename Flavor::CommitmentLabels comm_labels;
bb::RelationParameters<FF> relation_parameters;
WitnessCommitments witness_comms;

OinkVerifier(const std::shared_ptr<VerificationKey>& verifier_key,
const std::shared_ptr<Transcript>& transcript,
std::string domain_separator = "")
: transcript(transcript)
, key(verifier_key)
, domain_separator(std::move(domain_separator))
{}

OinkOutput<Flavor> 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
Loading

0 comments on commit 1139308

Please sign in to comment.