Skip to content

Commit

Permalink
lots of comment and naming updates based on review
Browse files Browse the repository at this point in the history
  • Loading branch information
ledwards2225 committed Aug 18, 2023
1 parent 76c7640 commit 6a22879
Show file tree
Hide file tree
Showing 9 changed files with 50 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@

namespace proof_system::honk::flavor {

/**
* @brief The recursive counterpart to the "native" Ultra flavor.
* @details This flavor can be used to instantiate a recursive Ultra Honk verifier for a proof created using the
* conventional Ultra flavor. It is similar in structure to its native counterpart with two main differences: 1) the
* curve types are stdlib types (e.g. field_t instead of field) and 2) it does not specify any Prover related types
* (e.g. Polynomial, ExtendedEdges, etc.) since we do not emulate prover computation in circuits, i.e. it only makes
* sense to instantiate a Verifier with this flavor.
*
*/
class UltraRecursive {
public:
using CircuitBuilder = UltraCircuitBuilder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,9 @@ template <typename Curve> class ShplonkVerifier_ {
for (const auto& claim : claims) {
vanishing_evals.emplace_back(z_challenge - claim.opening_pair.challenge);
}
// If recursion, invert elements individually, otherwise batch invert
// If recursion, invert elements individually, otherwise batch invert. (Inversion is cheap in circuits since we
// need only prove the correctness of a known inverse, we do not emulate its computation. Hence no need for
// batch inversion).
std::vector<Fr> inverse_vanishing_evals;
if constexpr (Curve::is_stdlib_type) {
for (const auto& val : vanishing_evals) {
Expand Down Expand Up @@ -234,7 +236,7 @@ template <typename Curve> class ShplonkVerifier_ {
}

// [G] += G₀⋅[1] = [G] + (∑ⱼ ρʲ ⋅ vⱼ / ( r − xⱼ ))⋅[1]
Fr evaluation_zero; // 0 \in Fr
Fr evaluation_zero; // 0 \in Fr
GroupElement group_one; // [1]
if constexpr (Curve::is_stdlib_type) {
auto ctx = transcript.builder;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
#include <algorithm>
#include <array>

// TODO(#674): We need the functionality of BarycentricData for both field and field_t. The former is "literal" i.e. is
// compatible with constexpr operations, and the former is not. The functions for computing the pre-computable arrays in
// BarycentricData need to be constexpr and it takes some trickery to share these functions with the non-constexpr
// setting. Right now everything is more or less duplicated across BarycentricDataCompileTime and
// TODO(#674): We need the functionality of BarycentricData for both field (native) and field_t (stdlib). The former is
// is compatible with constexpr operations, and the former is not. The functions for computing the
// pre-computable arrays in BarycentricData need to be constexpr and it takes some trickery to share these functions
// with the non-constexpr setting. Right now everything is more or less duplicated across BarycentricDataCompileTime and
// BarycentricDataRunTime. There should be a way to share more of the logic.

/* IMPROVEMENT(Cody): This could or should be improved in various ways. In no particular order:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ TYPED_TEST_SUITE(BarycentricDataTests, FieldTypes);
#define BARYCENTIC_DATA_TESTS_TYPE_ALIASES using FF = TypeParam;

/**
* @brief Ensure auxilliary arrays (e.g. big_domain) are computed at compile time if possible (i.e. if FF is literal)
* @brief Ensure auxilliary arrays (e.g. big_domain) are computed at compile time if possible (i.e. if FF is a native
* field)
*
*/
TYPED_TEST(BarycentricDataTests, CompileTimeComputation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ template <typename Flavor> class SumcheckVerifier {
const size_t multivariate_d;
SumcheckVerifierRound<Flavor> round;

// verifier instantiates sumcheck with circuit size and a verifier transcript
// verifier instantiates sumcheck with circuit size
explicit SumcheckVerifier(size_t multivariate_n)
: multivariate_d(numeric::get_msb(multivariate_n))
, round(){};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ template <typename Builder> class Transcript {
template <class T> auto receive_from_prover(const std::string& label)
{
// Get native type corresponding to input type
using NativeType = typename StdlibTypes::template CorrespondingNativeType<T>::type;
using NativeType = typename StdlibTypes::template NativeType<T>::type;

// Extract the native element from the native transcript
NativeType element = native_transcript.template receive_from_prover<NativeType>(label);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ TEST(RecursiveHonkTranscript, InterfacesMatch)
// Confirm that the native and stdlib verifier transcripts have generated the same manifest
EXPECT_EQ(transcript.get_manifest(), native_transcript.get_manifest());

// TODO(luke): This doesn't check much of anything until hashing is constrained in the stdlib transcript
// TODO(#1351): The Honk stdlib transcript does not currently lay down contraints for fiat-shamir hashing so
// check_circuit has limited value.
EXPECT_TRUE(builder.check_circuit());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ UltraRecursiveVerifier_<Flavor>& UltraRecursiveVerifier_<Flavor>::operator=(Ultr
}

/**
* @brief This function verifies an Ultra Honk proof for given program settings.
* @brief This function constructs a recursive verifier circuit for an Ultra Honk proof of a given flavor.
*
*/
template <typename Flavor> std::array<typename Flavor::GroupElement, 2> UltraRecursiveVerifier_<Flavor>::verify_proof(const plonk::proof& proof)
template <typename Flavor>
std::array<typename Flavor::GroupElement, 2> UltraRecursiveVerifier_<Flavor>::verify_proof(const plonk::proof& proof)
{
using FF = typename Flavor::FF;
using GroupElement = typename Flavor::GroupElement;
Expand All @@ -53,25 +54,20 @@ template <typename Flavor> std::array<typename Flavor::GroupElement, 2> UltraRec
size_t prev_num_gates = builder->get_num_gates();

transcript = Transcript<Builder>{ builder, proof.proof_data };

auto commitments = VerifierCommitments(key);
auto commitment_labels = CommitmentLabels();

const auto circuit_size = transcript.template receive_from_prover<uint32_t>("circuit_size");
const auto public_input_size = transcript.template receive_from_prover<uint32_t>("public_input_size");
const auto pub_inputs_offset = transcript.template receive_from_prover<uint32_t>("pub_inputs_offset");

// Extract native integer types for these basic quantities for use in subsequent operations
auto circuit_size_native = static_cast<size_t>(circuit_size.get_value());
auto public_input_size_native = static_cast<size_t>(public_input_size.get_value());
auto pub_inputs_offset_native = static_cast<size_t>(pub_inputs_offset.get_value());

// For debugging purposes only
ASSERT(circuit_size_native == key->circuit_size);
ASSERT(public_input_size_native == key->num_public_inputs);
ASSERT(static_cast<size_t>(circuit_size.get_value()) == key->circuit_size);
ASSERT(static_cast<size_t>(public_input_size.get_value()) == key->num_public_inputs);

std::vector<FF> public_inputs;
for (size_t i = 0; i < public_input_size_native; ++i) {
for (size_t i = 0; i < static_cast<size_t>(public_input_size.get_value()); ++i) {
auto public_input_i = transcript.template receive_from_prover<FF>("public_input_" + std::to_string(i));
public_inputs.emplace_back(public_input_i);
}
Expand Down Expand Up @@ -105,7 +101,7 @@ template <typename Flavor> std::array<typename Flavor::GroupElement, 2> UltraRec
auto [beta, gamma] = transcript.get_challenges("beta", "gamma");

const FF public_input_delta = proof_system::honk::compute_public_input_delta<Flavor>(
public_inputs, beta, gamma, circuit_size, pub_inputs_offset_native);
public_inputs, beta, gamma, circuit_size, static_cast<size_t>(pub_inputs_offset.get_value()));
const FF lookup_grand_product_delta =
proof_system::honk::compute_lookup_grand_product_delta<FF>(beta, gamma, circuit_size);

Expand All @@ -119,7 +115,7 @@ template <typename Flavor> std::array<typename Flavor::GroupElement, 2> UltraRec
commitments.z_lookup = transcript.template receive_from_prover<Commitment>(commitment_labels.z_lookup);

// Execute Sumcheck Verifier
auto sumcheck = Sumcheck(circuit_size_native);
auto sumcheck = Sumcheck(static_cast<size_t>(circuit_size.get_value()));

std::optional sumcheck_output = sumcheck.verify(relation_parameters, transcript);

Expand Down Expand Up @@ -147,7 +143,10 @@ template <typename Flavor> std::array<typename Flavor::GroupElement, 2> UltraRec
info("Batched eval: num gates = ", builder->get_num_gates() - prev_num_gates);
prev_num_gates = builder->get_num_gates();

// Construct vectors of scalars for batched unshifted and to-be-shifted commitments
// Compute batched commitments needed for input to Gemini.
// Note: For efficiency in emulating the construction of the batched commitments, we want to perform a batch mul
// rather than naively accumulate the points one by one. To do this, we collect the points and scalars required for
// each MSM then perform the two batch muls.
const size_t NUM_UNSHIFTED = commitments.get_unshifted().size();
const size_t NUM_TO_BE_SHIFTED = commitments.get_to_be_shifted().size();
std::vector<FF> scalars_unshifted;
Expand All @@ -159,8 +158,8 @@ template <typename Flavor> std::array<typename Flavor::GroupElement, 2> UltraRec
for (size_t i = 0; i < NUM_TO_BE_SHIFTED; ++i) {
scalars_to_be_shifted.emplace_back(rhos[idx++]);
}
// TODO(luke): The powers_of_rho fctn does not set the context of rhos[0] = FF(1) so we do it explicitly here. Can we
// do something silly like set it to rho.pow(0) in the fctn to make it work both native and stdlib?
// TODO(luke): The powers_of_rho fctn does not set the context of rhos[0] = FF(1) so we do it explicitly here. Can
// we do something silly like set it to rho.pow(0) in the fctn to make it work both native and stdlib?
scalars_unshifted[0] = FF::from_witness(builder, 1);

// Batch the commitments to the unshifted and to-be-shifted polynomials using powers of rho
Expand All @@ -179,25 +178,25 @@ template <typename Flavor> std::array<typename Flavor::GroupElement, 2> UltraRec
// - d+1 commitments [Fold_{r}^(0)], [Fold_{-r}^(0)], and [Fold^(l)], l = 1:d-1
// - d+1 evaluations a_0_pos, and a_l, l = 0:d-1
auto gemini_claim = Gemini::reduce_verification(multivariate_challenge,
batched_evaluation,
batched_commitment_unshifted,
batched_commitment_to_be_shifted,
transcript);
batched_evaluation,
batched_commitment_unshifted,
batched_commitment_to_be_shifted,
transcript);

info("Gemini: num gates = ", builder->get_num_gates() - prev_num_gates);
prev_num_gates = builder->get_num_gates();

// Produce a Shplonk claim: commitment [Q] - [Q_z], evaluation zero (at random challenge z)
auto shplonk_claim = Shplonk::reduce_verification(pcs_verification_key, gemini_claim, transcript);

info("Shplonk: num gates = ", builder->get_num_gates() - prev_num_gates);
prev_num_gates = builder->get_num_gates();

info("Total: num gates = ", builder->get_num_gates());

// Constuct the inputs to the final KZG pairing check
auto pairing_points = PCS::compute_pairing_points(shplonk_claim, transcript);

return pairing_points;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,27 +107,27 @@ template <typename Builder> class StdlibTypesUtility {
* @tparam T
* @tparam LENGTH (used only for containers which specify a length, e.g. array/Univariate)
*/
template <typename T, size_t LENGTH = 0> struct CorrespondingNativeType {
template <typename T, size_t LENGTH = 0> struct NativeType {
using type = void;
};

template <size_t LENGTH> struct CorrespondingNativeType<uint32_t, LENGTH> {
template <size_t LENGTH> struct NativeType<uint32_t, LENGTH> {
using type = uint32_t;
};

template <size_t LENGTH> struct CorrespondingNativeType<field_ct, LENGTH> {
template <size_t LENGTH> struct NativeType<field_ct, LENGTH> {
using type = FF;
};

template <size_t LENGTH> struct CorrespondingNativeType<element_ct, LENGTH> {
template <size_t LENGTH> struct NativeType<element_ct, LENGTH> {
using type = Commitment;
};

template <size_t LENGTH> struct CorrespondingNativeType<std::array<field_ct, LENGTH>, 0> {
template <size_t LENGTH> struct NativeType<std::array<field_ct, LENGTH>, 0> {
using type = std::array<FF, LENGTH>;
};

template <size_t LENGTH> struct CorrespondingNativeType<Univariate_ct<LENGTH>, 0> {
template <size_t LENGTH> struct NativeType<Univariate_ct<LENGTH>, 0> {
using type = Univariate<LENGTH>;
};
};
Expand Down

0 comments on commit 6a22879

Please sign in to comment.