Skip to content

Commit

Permalink
feat: make shplemini proof constant (#8826)
Browse files Browse the repository at this point in the history
Make Shplemini proofs constant using the same approach as in other
places, add relevant github issues for handling the dummy rounds
properly, make the shplemini recursion test do full verification and
ensure recursive shplemini verifiers actually stay constant.
  • Loading branch information
maramihali authored and Rumata888 committed Sep 27, 2024
1 parent 0780ab9 commit 2dfa8f7
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ template <class Fr> inline std::vector<Fr> powers_of_evaluation_challenge(const

template <typename Curve> class GeminiProver_ {
using Fr = typename Curve::ScalarField;
using Commitment = typename Curve::AffineElement;
using Polynomial = bb::Polynomial<Fr>;
using Claim = ProverOpeningClaim<Curve>;

Expand Down Expand Up @@ -168,7 +169,7 @@ template <typename Curve> class GeminiVerifier_ {

// compute vector of powers of random evaluation point r
const Fr r = transcript->template get_challenge<Fr>("Gemini:r");
const std::vector<Fr> r_squares = gemini::powers_of_evaluation_challenge(r, num_variables);
const std::vector<Fr> r_squares = gemini::powers_of_evaluation_challenge(r, CONST_PROOF_SIZE_LOG_N);

// Get evaluations a_i, i = 0,...,m-1 from transcript
const std::vector<Fr> evaluations = get_gemini_evaluations(num_variables, transcript);
Expand Down Expand Up @@ -197,22 +198,24 @@ template <typename Curve> class GeminiVerifier_ {
return fold_polynomial_opening_claims;
}

static std::vector<Commitment> get_fold_commitments(const size_t log_circuit_size, auto& transcript)
static std::vector<Commitment> get_fold_commitments([[maybe_unused]] const size_t log_circuit_size,
auto& transcript)
{
std::vector<Commitment> fold_commitments;
fold_commitments.reserve(log_circuit_size - 1);
for (size_t i = 0; i < log_circuit_size - 1; ++i) {
fold_commitments.reserve(CONST_PROOF_SIZE_LOG_N - 1);
for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N - 1; ++i) {
const Commitment commitment =
transcript->template receive_from_prover<Commitment>("Gemini:FOLD_" + std::to_string(i + 1));
fold_commitments.emplace_back(commitment);
}
return fold_commitments;
}
static std::vector<Fr> get_gemini_evaluations(const size_t log_circuit_size, auto& transcript)
static std::vector<Fr> get_gemini_evaluations([[maybe_unused]] const size_t log_circuit_size, auto& transcript)
{
std::vector<Fr> gemini_evaluations;
gemini_evaluations.reserve(log_circuit_size);
for (size_t i = 1; i <= log_circuit_size; ++i) {
gemini_evaluations.reserve(CONST_PROOF_SIZE_LOG_N);

for (size_t i = 1; i <= CONST_PROOF_SIZE_LOG_N; ++i) {
const Fr evaluation = transcript->template receive_from_prover<Fr>("Gemini:a_" + std::to_string(i));
gemini_evaluations.emplace_back(evaluation);
}
Expand Down Expand Up @@ -241,29 +244,43 @@ template <typename Curve> class GeminiVerifier_ {
* @param fold_polynomial_evals Evaluations \f$ A_{i-1}(-r^{2^{i-1}}) \f$.
* @return Evaluation \f$ A_0(r) \f$.
*/
static Fr compute_gemini_batched_univariate_evaluation(size_t evaluation_point_size,
Fr& batched_eval_accumulator,
std::span<const Fr> evaluation_point,
std::span<const Fr> challenge_powers,
std::span<const Fr> fold_polynomial_evals)
static Fr compute_gemini_batched_univariate_evaluation(
const size_t num_variables,
Fr& batched_eval_accumulator,
std::span<const Fr> evaluation_point, // CONST_PROOF_SIZE
std::span<const Fr> challenge_powers, // r_squares CONST_PROOF_SIZE_LOG_N
std::span<const Fr> fold_polynomial_evals)
{
const size_t num_variables = evaluation_point_size;

const auto& evals = fold_polynomial_evals;

// Solve the sequence of linear equations
for (size_t l = num_variables; l != 0; --l) {
for (size_t l = CONST_PROOF_SIZE_LOG_N; l != 0; --l) {
// Get r²⁽ˡ⁻¹⁾
const Fr& challenge_power = challenge_powers[l - 1];
// Get A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾)
const Fr& eval_neg = evals[l - 1];
// Get uₗ₋₁
const Fr& u = evaluation_point[l - 1];
const Fr& eval_neg = evals[l - 1];
// Get A₍ₗ₋₁₎(−r²⁽ˡ⁻¹⁾)
// Compute the numerator
batched_eval_accumulator =
Fr batched_eval_round_acc =
((challenge_power * batched_eval_accumulator * 2) - eval_neg * (challenge_power * (Fr(1) - u) - u));
// Divide by the denominator
batched_eval_accumulator *= (challenge_power * (Fr(1) - u) + u).invert();
batched_eval_round_acc *= (challenge_power * (Fr(1) - u) + u).invert();

bool is_dummy_round = (l > num_variables);

if constexpr (Curve::is_stdlib_type) {
auto builder = evaluation_point[0].get_context();
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure!
stdlib::bool_t dummy_round = stdlib::bool_t(builder, is_dummy_round);
batched_eval_accumulator =
Fr::conditional_assign(dummy_round, batched_eval_accumulator, batched_eval_round_acc);

} else {
if (!is_dummy_round) {
batched_eval_accumulator = batched_eval_round_acc;
}
}
}

return batched_eval_accumulator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,23 @@ std::vector<typename GeminiProver_<Curve>::Claim> GeminiProver_<Curve>::prove(
auto fold_polynomials = compute_fold_polynomials(
log_n, multilinear_challenge, std::move(batched_unshifted), std::move(batched_to_be_shifted));

for (size_t l = 0; l < log_n - 1; l++) {
transcript->send_to_verifier("Gemini:FOLD_" + std::to_string(l + 1),
commitment_key->commit(fold_polynomials[l + 2]));
for (size_t l = 0; l < CONST_PROOF_SIZE_LOG_N - 1; l++) {
if (l < log_n - 1) {
transcript->send_to_verifier("Gemini:FOLD_" + std::to_string(l + 1),
commitment_key->commit(fold_polynomials[l + 2]));
} else {
transcript->send_to_verifier("Gemini:FOLD_" + std::to_string(l + 1), Commitment::one());
}
}
const Fr r_challenge = transcript->template get_challenge<Fr>("Gemini:r");
std::vector<Claim> claims = compute_fold_polynomial_evaluations(log_n, std::move(fold_polynomials), r_challenge);

for (size_t l = 1; l <= log_n; l++) {
transcript->send_to_verifier("Gemini:a_" + std::to_string(l), claims[l].opening_pair.evaluation);
for (size_t l = 1; l <= CONST_PROOF_SIZE_LOG_N; l++) {
if (l <= log_n) {
transcript->send_to_verifier("Gemini:a_" + std::to_string(l), claims[l].opening_pair.evaluation);
} else {
transcript->send_to_verifier("Gemini:a_" + std::to_string(l), Fr::zero());
}
}

return claims;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ template <typename Curve> class ShpleminiVerifier_ {
const Fr gemini_evaluation_challenge = transcript->template get_challenge<Fr>("Gemini:r");
// - Get evaluations (A₀(−r), A₁(−r²), ... , Aₙ₋₁(−r²⁽ⁿ⁻¹⁾))
const std::vector<Fr> gemini_evaluations = GeminiVerifier::get_gemini_evaluations(log_circuit_size, transcript);
// - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size
// - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size, I think this should be CONST_PROOF_SIZE
const std::vector<Fr> gemini_eval_challenge_powers =
gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, log_circuit_size);
gemini::powers_of_evaluation_challenge(gemini_evaluation_challenge, CONST_PROOF_SIZE_LOG_N);

// Process Shplonk transcript data:
// - Get Shplonk batching challenge
Expand All @@ -143,7 +143,7 @@ template <typename Curve> class ShpleminiVerifier_ {
// Get Shplonk opening point z
const Fr shplonk_evaluation_challenge = transcript->template get_challenge<Fr>("Shplonk:z");
// Start computing the scalar to be multiplied by [1]₁
Fr constant_term_accumulator{ 0 };
Fr constant_term_accumulator = Fr(0);

// Initialize the vector of scalars placing the scalar 1 correposnding to Q_commitment
std::vector<Fr> scalars;
Expand All @@ -167,7 +167,7 @@ template <typename Curve> class ShpleminiVerifier_ {

// Place the commitments to prover polynomials in the commitments vector. Compute the evaluation of the
// batched multilinear polynomial. Populate the vector of scalars for the final batch mul
Fr batched_evaluation{ 0 };
Fr batched_evaluation = Fr(0);
batch_multivariate_opening_claims(unshifted_commitments,
shifted_commitments,
unshifted_evaluations,
Expand Down Expand Up @@ -334,17 +334,34 @@ template <typename Curve> class ShpleminiVerifier_ {
std::vector<Fr>& scalars,
Fr& constant_term_accumulator)
{

// Initialize batching challenge as ν²
Fr current_batching_challenge = shplonk_batching_challenge * shplonk_batching_challenge;
for (size_t j = 0; j < log_circuit_size - 1; ++j) {
Fr current_batching_challenge = shplonk_batching_challenge.sqr();
for (size_t j = 0; j < CONST_PROOF_SIZE_LOG_N - 1; ++j) {
bool is_dummy_round = j >= (log_circuit_size - 1);
// Compute the scaling factor (ν²⁺ⁱ) / (z + r²⁽ⁱ⁺²⁾) for i = 0, … , d-2
Fr scaling_factor = current_batching_challenge * inverse_vanishing_evals[j + 2];
// Place the scaling factor to the 'scalars' vector
scalars.emplace_back(-scaling_factor);

if constexpr (Curve::is_stdlib_type) {
auto builder = shplonk_batching_challenge.get_context();
// TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure!
stdlib::bool_t dummy_round = stdlib::bool_t(builder, is_dummy_round);
Fr zero = Fr(0);
zero.convert_constant_to_fixed_witness(builder);
scaling_factor = Fr::conditional_assign(dummy_round, zero, scaling_factor);
} else {
if (is_dummy_round) {
scaling_factor = 0;
}
}

// Add Aᵢ(−r²ⁱ) for i = 1, … , n-1 to the constant term accumulator
constant_term_accumulator += scaling_factor * gemini_evaluations[j + 1];
// Update the batching challenge
current_batching_challenge *= shplonk_batching_challenge;

// Place the scaling factor to the 'scalars' vector
scalars.emplace_back(-scaling_factor);
// Move com(Aᵢ) to the 'commitments' vector
commitments.emplace_back(std::move(fold_commitments[j]));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,6 @@ TYPED_TEST(ShpleminiTest, CorrectnessOfGeminiClaimBatching)
scalars,
expected_constant_term_accumulator);

EXPECT_EQ(commitments.size(), prover_commitments.size());
// Compute the group element using the output of Shplemini method
GroupElement shplemini_result = batch_mul_native(commitments, scalars);

Expand Down
Loading

0 comments on commit 2dfa8f7

Please sign in to comment.