From 0e425dbfc99af9fc2598a957acd8b71f3fd45fe9 Mon Sep 17 00:00:00 2001 From: ledwards2225 <98505400+ledwards2225@users.noreply.github.com> Date: Fri, 17 Nov 2023 14:46:34 -0700 Subject: [PATCH] feat: ZM updates for Translator concatenated polys (#3343) From Kesha: This PR adds polynomial "concatenation" functionality into ZeroMorph. The idea behind concatenation is the following: given several polynomials (for example, $X_1$, $X_2$, $X_3$, $X_4$, $Y_1$, $Y_2$, $Y_3$, $Y_4$) of length n, we want to show that the set of values in $X$ polynomials is identical to the values in $Y$.The way we can do it is with a grand product argument, however sumcheck complexity of the grand product argument is quadratic in the number of polynomials that are used in the GP (we have to extend the univariate to the degree d and then we need to multiply those (d+1) elements d times). However, if we were to perform the same grand product instead on polynomials $X= (X_1|X_2|X_3|X_4)$ and $Y=(Y_1|Y_2|Y_3|Y_4)$, the length of the sumcheck would increase 4 times, but the degree d would decrease proportionately. So let's say we have an original circuit of length n, where all non-permutation relations are satisfied (including on $X_i$ and $Y_i$ polynomials). However, for the grand product argument we extend the polynomials to length $k\cdot n$ , where $k$ is a power of 2. Then we use the property of Zeromorph that it uses univariate commitments for commiting to multilinear polynomials. Because of this property, the final univariate opening of $X$ at challenge $x$ is equivalent to opening $X_1+x^n\cdot X_2+x^{2n}\cdot X_3+x^{3n}\cdot X_4$. So what we do in Zeromorph is substitute the opening of a concatenated polynomial by opening of a polynomial derived from a combination of $X_i$ polynomials multiplied by powers of $x$. This allows us to have fewer commitments and avoid shifts to prove the composition of concatenated polynomials --- .../zeromorph/zeromorph.hpp | 109 +++++-- .../zeromorph/zeromorph.test.cpp | 304 ++---------------- .../verifier/ultra_recursive_verifier.cpp | 8 +- .../barretenberg/ultra_honk/ultra_prover.cpp | 3 +- .../ultra_honk/ultra_verifier.cpp | 7 +- 5 files changed, 124 insertions(+), 307 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp index 96c8a980c9b..93ec07ec533 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp @@ -1,6 +1,6 @@ #pragma once +#include "barretenberg/common/zip_view.hpp" #include "barretenberg/polynomials/polynomial.hpp" - namespace proof_system::honk::pcs::zeromorph { /** @@ -188,7 +188,7 @@ template class ZeroMorphProver_ { * * where f_batched = \sum_{i=0}^{m-1}\rho^i*f_i, g_batched = \sum_{i=0}^{l-1}\rho^{m+i}*g_i * - * and concatenation_term = \sum_{i=0}^{concatenation_index}(x^{i * min_N + 1}concatenation_groups_batched_{i}) + * and concatenation_term = \sum_{i=0}^{num_chunks_per_group}(x^{i * min_N + 1}concatenation_groups_batched_{i}) * * @note The concatenation term arises from an implementation detail in the Goblin Translator and is not part of the * conventional ZM protocol @@ -240,7 +240,7 @@ template class ZeroMorphProver_ { } // If necessary, add to Z_x the contribution related to concatenated polynomials: - // \sum_{i=0}^{concatenation_index}(x^{i * min_n + 1}concatenation_groups_batched_{i}). + // \sum_{i=0}^{num_chunks_per_group}(x^{i * min_n + 1}concatenation_groups_batched_{i}). // We are effectively reconstructing concatenated polynomials from their chunks now that we know x // Note: this is an implementation detail related to Goblin Translator and is not part of the standard protocol. if (!concatenation_groups_batched.empty()) { @@ -314,18 +314,20 @@ template class ZeroMorphProver_ { */ static void prove(const auto& f_polynomials, const auto& g_polynomials, - auto& evaluations, + auto&& f_evaluations, + auto&& g_shift_evaluations, auto& multilinear_challenge, auto& commitment_key, - auto& transcript) + auto& transcript, + const std::vector& concatenated_polynomials = {}, + const std::vector& concatenated_evaluations = {}, + const std::vector>& concatenation_groups = {}) { // Generate batching challenge \rho and powers 1,...,\rho^{m-1} FF rho = transcript.get_challenge("rho"); - std::vector rhos = powers_of_challenge(rho, evaluations.size()); // Extract multilinear challenge u and claimed multilinear evaluations from Sumcheck output std::span u_challenge = multilinear_challenge; - auto claimed_evaluations = evaluations.pointer_view(); size_t log_N = u_challenge.size(); size_t N = 1 << log_N; @@ -337,24 +339,47 @@ template class ZeroMorphProver_ { // evaluations produced by sumcheck of h_i = g_i_shifted. auto batched_evaluation = FF(0); Polynomial f_batched(N); // batched unshifted polynomials - size_t poly_idx = 0; // TODO(#391) zip - for (auto& f_poly : f_polynomials) { - f_batched.add_scaled(f_poly, rhos[poly_idx]); - batched_evaluation += rhos[poly_idx] * (*claimed_evaluations[poly_idx]); - ++poly_idx; + FF batching_scalar = FF(1); + for (auto [f_poly, f_eval] : zip_view(f_polynomials, f_evaluations)) { + f_batched.add_scaled(f_poly, batching_scalar); + batched_evaluation += batching_scalar * f_eval; + batching_scalar *= rho; } Polynomial g_batched(N); // batched to-be-shifted polynomials - for (auto& g_poly : g_polynomials) { - g_batched.add_scaled(g_poly, rhos[poly_idx]); - batched_evaluation += rhos[poly_idx] * (*claimed_evaluations[poly_idx]); - ++poly_idx; + for (auto [g_poly, g_shift_eval] : zip_view(g_polynomials, g_shift_evaluations)) { + g_batched.add_scaled(g_poly, batching_scalar); + batched_evaluation += batching_scalar * g_shift_eval; + batching_scalar *= rho; }; + size_t num_groups = concatenation_groups.size(); + size_t num_chunks_per_group = concatenation_groups.empty() ? 0 : concatenation_groups[0].size(); + // Concatenated polynomials + // std::vector concatenated_polynomials; + Polynomial concatenated_batched(N); + + // construct concatention_groups_batched + std::vector concatenation_groups_batched; + for (size_t i = 0; i < num_chunks_per_group; ++i) { + concatenation_groups_batched.push_back(Polynomial(N)); + } + // for each group + for (size_t i = 0; i < num_groups; ++i) { + concatenated_batched.add_scaled(concatenated_polynomials[i], batching_scalar); + // for each element in a group + for (size_t j = 0; j < num_chunks_per_group; ++j) { + concatenation_groups_batched[j].add_scaled(concatenation_groups[i][j], batching_scalar); + } + batched_evaluation += batching_scalar * concatenated_evaluations[i]; + batching_scalar *= rho; + } + // Compute the full batched polynomial f = f_batched + g_batched.shifted() = f_batched + h_batched. This is the // polynomial for which we compute the quotients q_k and prove f(u) = v_batched. auto f_polynomial = f_batched; f_polynomial += g_batched.shifted(); + f_polynomial += concatenated_batched; // Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1}) auto quotients = compute_multilinear_quotients(f_polynomial, u_challenge); @@ -386,8 +411,13 @@ template class ZeroMorphProver_ { compute_partially_evaluated_degree_check_polynomial(batched_quotient, quotients, y_challenge, x_challenge); // Compute ZeroMorph identity polynomial Z partially evaluated at x - auto Z_x = compute_partially_evaluated_zeromorph_identity_polynomial( - f_batched, g_batched, quotients, batched_evaluation, u_challenge, x_challenge); + auto Z_x = compute_partially_evaluated_zeromorph_identity_polynomial(f_batched, + g_batched, + quotients, + batched_evaluation, + u_challenge, + x_challenge, + concatenation_groups_batched); // Compute batched degree-check and ZM-identity quotient polynomial pi auto pi_polynomial = @@ -468,7 +498,7 @@ template class ZeroMorphVerifier_ { * + concatentation_term * where * - * concatenation_term = \sum{i=0}^{o-1}\sum_{j=0}^{concatenation_index}(rho^{m+l+i} * x^{j * min_N + 1} + * concatenation_term = \sum{i=0}^{o-1}\sum_{j=0}^{num_chunks_per_group}(rho^{m+l+i} * x^{j * min_N + 1} * * concatenation_groups_commitments_{i}_{j}) * * @note The concatenation term arises from an implementation detail in the Goblin Translator and is not part of the @@ -490,7 +520,7 @@ template class ZeroMorphVerifier_ { FF batched_evaluation, FF x_challenge, std::vector u_challenge, - std::vector> concatenation_groups_commitments = {}) + const std::vector>& concatenation_groups_commitments = {}) { size_t log_N = C_q_k.size(); size_t N = 1 << log_N; @@ -600,23 +630,33 @@ template class ZeroMorphVerifier_ { * @param transcript * @return std::array Inputs to the final pairing check */ - static std::array verify(auto& commitments, - auto& claimed_evaluations, - auto& multivariate_challenge, - auto& transcript) + static std::array verify( + auto&& unshifted_commitments, + auto&& to_be_shifted_commitments, + auto&& unshifted_evaluations, + auto&& shifted_evaluations, + auto& multivariate_challenge, + auto& transcript, + const std::vector>& concatenation_group_commitments = {}, + const std::vector& concatenated_evaluations = {}) { size_t log_N = multivariate_challenge.size(); FF rho = transcript.get_challenge("rho"); - // Compute powers of batching challenge rho - std::vector rhos = pcs::zeromorph::powers_of_challenge(rho, claimed_evaluations.size()); - // Construct batched evaluation v = sum_{i=0}^{m-1}\rho^i*f_i(u) + sum_{i=0}^{l-1}\rho^{m+i}*h_i(u) FF batched_evaluation = FF(0); - size_t evaluation_idx = 0; - for (auto& value : claimed_evaluations.get_unshifted_then_shifted()) { - batched_evaluation += value * rhos[evaluation_idx]; - ++evaluation_idx; + FF batching_scalar = FF(1); + for (auto& value : unshifted_evaluations) { + batched_evaluation += value * batching_scalar; + batching_scalar *= rho; + } + for (auto& value : shifted_evaluations) { + batched_evaluation += value * batching_scalar; + batching_scalar *= rho; + } + for (auto& value : concatenated_evaluations) { + batched_evaluation += value * batching_scalar; + batching_scalar *= rho; } // Receive commitments [q_k] @@ -639,13 +679,14 @@ template class ZeroMorphVerifier_ { auto C_zeta_x = compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge); // Compute commitment C_{Z_x} - Commitment C_Z_x = compute_C_Z_x(commitments.get_unshifted(), - commitments.get_to_be_shifted(), + Commitment C_Z_x = compute_C_Z_x(unshifted_commitments, + to_be_shifted_commitments, C_q_k, rho, batched_evaluation, x_challenge, - multivariate_challenge); + multivariate_challenge, + concatenation_group_commitments); // Compute commitment C_{\zeta,Z} auto C_zeta_Z = C_zeta_x + C_Z_x * z_challenge; diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp index 82b6191eca2..270f236ad68 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp @@ -80,135 +80,25 @@ template class ZeroMorphTest : public CommitmentTest { auto prover_transcript = BaseTranscript::prover_init_empty(); // Execute Prover protocol - { - auto rho = prover_transcript.get_challenge("ZM:rho"); - - // Compute batching of f_i and g_i polynomials: sum_{i=0}^{m-1}\rho^i*f_i and - // sum_{i=0}^{l-1}\rho^{m+i}*h_i, and also batched evaluation v = sum_{i=0}^{m-1}\rho^i*v_i + - // sum_{i=0}^{l-1}\rho^{m+i}*w_i. - auto f_batched = Polynomial(N); - auto g_batched = Polynomial(N); - auto v_evaluation = Fr(0); - auto rho_pow = Fr(1); - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_batched.add_scaled(f_polynomials[i], rho_pow); - v_evaluation += rho_pow * v_evaluations[i]; - rho_pow *= rho; - } - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_batched.add_scaled(g_polynomials[i], rho_pow); - v_evaluation += rho_pow * w_evaluations[i]; - rho_pow *= rho; - } - - // The new f is f_batched + g_batched.shifted() = f_batched + h_batched - auto f_polynomial = f_batched; - f_polynomial += g_batched.shifted(); - - // Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1}) - auto quotients = ZeroMorphProver::compute_multilinear_quotients(f_polynomial, u_challenge); - - // Compute and send commitments C_{q_k} = [q_k], k = 0,...,d-1 - std::vector q_k_commitments; - q_k_commitments.reserve(log_N); - for (size_t idx = 0; idx < log_N; ++idx) { - q_k_commitments[idx] = this->commit(quotients[idx]); - std::string label = "ZM:C_q_" + std::to_string(idx); - prover_transcript.send_to_verifier(label, q_k_commitments[idx]); - } - - // Get challenge y - auto y_challenge = prover_transcript.get_challenge("ZM:y"); - - // Compute the batched, lifted-degree quotient \hat{q} - auto batched_quotient = ZeroMorphProver::compute_batched_lifted_degree_quotient(quotients, y_challenge, N); - - // Compute and send the commitment C_q = [\hat{q}] - auto q_commitment = this->commit(batched_quotient); - prover_transcript.send_to_verifier("ZM:C_q", q_commitment); - - // Get challenges x and z - auto [x_challenge, z_challenge] = prover_transcript.get_challenges("ZM:x", "ZM:z"); - - // Compute degree check polynomial \zeta partially evaluated at x - auto zeta_x = ZeroMorphProver::compute_partially_evaluated_degree_check_polynomial( - batched_quotient, quotients, y_challenge, x_challenge); - - // Compute ZeroMorph identity polynomial Z partially evaluated at x - auto Z_x = ZeroMorphProver::compute_partially_evaluated_zeromorph_identity_polynomial( - f_batched, g_batched, quotients, v_evaluation, u_challenge, x_challenge); - - // Compute batched degree and ZM-identity quotient polynomial pi - auto pi_polynomial = ZeroMorphProver::compute_batched_evaluation_and_degree_check_quotient( - zeta_x, Z_x, x_challenge, z_challenge); - - // Compute and send proof commitment pi - auto pi_commitment = this->commit(pi_polynomial); - prover_transcript.send_to_verifier("ZM:PI", pi_commitment); - } + ZeroMorphProver::prove(f_polynomials, + g_polynomials, + v_evaluations, + w_evaluations, + u_challenge, + this->commitment_key, + prover_transcript); auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); // Execute Verifier protocol - { - // Challenge rho - auto rho = verifier_transcript.get_challenge("ZM:rho"); - - // Construct batched evaluation v = sum_{i=0}^{m-1}\rho^i*v_i + sum_{i=0}^{l-1}\rho^{m+i}*w_i - auto v_evaluation = Fr(0); - auto rho_pow = Fr(1); - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - v_evaluation += rho_pow * v_evaluations[i]; - rho_pow *= rho; - } - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - v_evaluation += rho_pow * w_evaluations[i]; - rho_pow *= rho; - } - - // Receive commitments [q_k] - std::vector C_q_k; - C_q_k.reserve(log_N); - for (size_t i = 0; i < log_N; ++i) { - C_q_k.emplace_back( - verifier_transcript.template receive_from_prover("ZM:C_q_" + std::to_string(i))); - } - - // Challenge y - auto y_challenge = verifier_transcript.get_challenge("ZM:y"); - - // Receive commitment C_{q} - auto C_q = verifier_transcript.template receive_from_prover("ZM:C_q"); - - // Challenges x, z - auto [x_challenge, z_challenge] = verifier_transcript.get_challenges("ZM:x", "ZM:z"); - - // Compute commitment C_{\zeta_x} - auto C_zeta_x = ZeroMorphVerifier::compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge); - - // Compute commitment C_{Z_x} - Commitment C_Z_x = ZeroMorphVerifier::compute_C_Z_x( - f_commitments, g_commitments, C_q_k, rho, v_evaluation, x_challenge, u_challenge); - - // Compute commitment C_{\zeta,Z} - auto C_zeta_Z = C_zeta_x + C_Z_x * z_challenge; + auto pairing_points = ZeroMorphVerifier::verify( + f_commitments, g_commitments, v_evaluations, w_evaluations, u_challenge, verifier_transcript); - // Receive proof commitment \pi - auto C_pi = verifier_transcript.template receive_from_prover("ZM:PI"); + verified = this->vk()->pairing_check(pairing_points[0], pairing_points[1]); - // The prover and verifier manifests should agree - EXPECT_EQ(prover_transcript.get_manifest(), verifier_transcript.get_manifest()); + // The prover and verifier manifests should agree + EXPECT_EQ(prover_transcript.get_manifest(), verifier_transcript.get_manifest()); - // Construct inputs and perform pairing check to verify claimed evaluation - // Note: The pairing check (without the degree check component X^{N_max-N-1}) can be expressed naturally as - // e(C_{\zeta,Z}, [1]_2) = e(pi, [X - x]_2). This can be rearranged (e.g. see the plonk paper) as - // e(C_{\zeta,Z} - x*pi, [1]_2) * e(-pi, [X]_2) = 1, or - // e(P_0, [1]_2) * e(P_1, [X]_2) = 1 - auto P0 = C_zeta_Z + C_pi * x_challenge; - auto P1 = -C_pi; - verified = this->vk()->pairing_check(P0, P1); - // EXPECT_TRUE(verified); - } return verified; } }; @@ -336,158 +226,34 @@ template class ZeroMorphWithConcatenationTest : public CommitmentT auto prover_transcript = BaseTranscript::prover_init_empty(); // Execute Prover protocol - { - auto rho = prover_transcript.get_challenge("ZM:rho"); - - // Compute batching of f_i and g_i polynomials: sum_{i=0}^{m-1}\rho^i*f_i and - // sum_{i=0}^{l-1}\rho^{m+i}*h_i, and also batched evaluation v = sum_{i=0}^{m-1}\rho^i*v_i + - // sum_{i=0}^{l-1}\rho^{m+i}*w_i. - auto f_batched = Polynomial(N); - auto g_batched = Polynomial(N); - auto concatenated_batched = Polynomial(N); - std::vector concatenation_groups_batched; - auto v_evaluation = Fr(0); - auto rho_pow = Fr(1); - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_batched.add_scaled(f_polynomials[i], rho_pow); - v_evaluation += rho_pow * v_evaluations[i]; - rho_pow *= rho; - } - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_batched.add_scaled(g_polynomials[i], rho_pow); - v_evaluation += rho_pow * w_evaluations[i]; - rho_pow *= rho; - } - for (size_t i = 0; i < concatenation_index; ++i) { - concatenation_groups_batched.push_back(Polynomial(N)); - } - for (size_t i = 0; i < NUM_CONCATENATED; ++i) { - concatenated_batched.add_scaled(concatenated_polynomials[i], rho_pow); - for (size_t j = 0; j < concatenation_index; ++j) { - concatenation_groups_batched[j].add_scaled(concatenation_groups[i][j], rho_pow); - } - v_evaluation += rho_pow * c_evaluations[i]; - rho_pow *= rho; - } - - // The new f is f_batched + g_batched.shifted() = f_batched + h_batched - auto f_polynomial = f_batched; - f_polynomial += g_batched.shifted(); - f_polynomial += concatenated_batched; - - // Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1}) - auto quotients = ZeroMorphProver::compute_multilinear_quotients(f_polynomial, u_challenge); - - // Compute and send commitments C_{q_k} = [q_k], k = 0,...,d-1 - std::vector q_k_commitments; - q_k_commitments.reserve(log_N); - for (size_t idx = 0; idx < log_N; ++idx) { - q_k_commitments[idx] = this->commit(quotients[idx]); - std::string label = "ZM:C_q_" + std::to_string(idx); - prover_transcript.send_to_verifier(label, q_k_commitments[idx]); - } - - // Get challenge y - auto y_challenge = prover_transcript.get_challenge("ZM:y"); - - // Compute the batched, lifted-degree quotient \hat{q} - auto batched_quotient = ZeroMorphProver::compute_batched_lifted_degree_quotient(quotients, y_challenge, N); - - // Compute and send the commitment C_q = [\hat{q}] - auto q_commitment = this->commit(batched_quotient); - prover_transcript.send_to_verifier("ZM:C_q", q_commitment); - - // Get challenges x and z - auto [x_challenge, z_challenge] = prover_transcript.get_challenges("ZM:x", "ZM:z"); - - // Compute degree check polynomial \zeta partially evaluated at x - auto zeta_x = ZeroMorphProver::compute_partially_evaluated_degree_check_polynomial( - batched_quotient, quotients, y_challenge, x_challenge); - - // Compute ZeroMorph identity polynomial Z partially evaluated at x - auto Z_x = ZeroMorphProver::compute_partially_evaluated_zeromorph_identity_polynomial( - f_batched, g_batched, quotients, v_evaluation, u_challenge, x_challenge, concatenation_groups_batched); - - // Compute batched degree and ZM-identity quotient polynomial pi - auto pi_polynomial = ZeroMorphProver::compute_batched_evaluation_and_degree_check_quotient( - zeta_x, Z_x, x_challenge, z_challenge); - - // Compute and send proof commitment pi - auto pi_commitment = this->commit(pi_polynomial); - prover_transcript.send_to_verifier("ZM:PI", pi_commitment); - } + ZeroMorphProver::prove(f_polynomials, // unshifted + g_polynomials, // to-be-shifted + v_evaluations, // unshifted + w_evaluations, // shifted + u_challenge, + this->commitment_key, + prover_transcript, + concatenated_polynomials, + c_evaluations, + concatenation_groups); auto verifier_transcript = BaseTranscript::verifier_init_empty(prover_transcript); // Execute Verifier protocol - { - // Challenge rho - auto rho = verifier_transcript.get_challenge("ZM:rho"); - - // Construct batched evaluation v = sum_{i=0}^{m-1}\rho^i*v_i + sum_{i=0}^{l-1}\rho^{m+i}*w_i - auto v_evaluation = Fr(0); - auto rho_pow = Fr(1); - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - v_evaluation += rho_pow * v_evaluations[i]; - rho_pow *= rho; - } - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - v_evaluation += rho_pow * w_evaluations[i]; - rho_pow *= rho; - } - for (size_t i = 0; i < NUM_CONCATENATED; ++i) { - v_evaluation += rho_pow * c_evaluations[i]; - rho_pow *= rho; - } - // Receive commitments [q_k] - std::vector C_q_k; - C_q_k.reserve(log_N); - for (size_t i = 0; i < log_N; ++i) { - C_q_k.emplace_back( - verifier_transcript.template receive_from_prover("ZM:C_q_" + std::to_string(i))); - } + auto pairing_points = ZeroMorphVerifier::verify(f_commitments, // unshifted + g_commitments, // to-be-shifted + v_evaluations, // unshifted + w_evaluations, // shifted + u_challenge, + verifier_transcript, + concatenation_groups_commitments, + c_evaluations); + + verified = this->vk()->pairing_check(pairing_points[0], pairing_points[1]); + + // The prover and verifier manifests should agree + EXPECT_EQ(prover_transcript.get_manifest(), verifier_transcript.get_manifest()); - // Challenge y - auto y_challenge = verifier_transcript.get_challenge("ZM:y"); - - // Receive commitment C_{q} - auto C_q = verifier_transcript.template receive_from_prover("ZM:C_q"); - - // Challenges x, z - auto [x_challenge, z_challenge] = verifier_transcript.get_challenges("ZM:x", "ZM:z"); - - // Compute commitment C_{\zeta_x} - auto C_zeta_x = ZeroMorphVerifier::compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge); - - // Compute commitment C_{Z_x} - Commitment C_Z_x = ZeroMorphVerifier::compute_C_Z_x(f_commitments, - g_commitments, - C_q_k, - rho, - v_evaluation, - x_challenge, - u_challenge, - concatenation_groups_commitments); - - // Compute commitment C_{\zeta,Z} - auto C_zeta_Z = C_zeta_x + C_Z_x * z_challenge; - - // Receive proof commitment \pi - auto C_pi = verifier_transcript.template receive_from_prover("ZM:PI"); - - // The prover and verifier manifests should agree - EXPECT_EQ(prover_transcript.get_manifest(), verifier_transcript.get_manifest()); - - // Construct inputs and perform pairing check to verify claimed evaluation - // Note: The pairing check (without the degree check component X^{N_max-N-1}) can be expressed naturally as - // e(C_{\zeta,Z}, [1]_2) = e(pi, [X - x]_2). This can be rearranged (e.g. see the plonk paper) as - // e(C_{\zeta,Z} - x*pi, [1]_2) * e(-pi, [X]_2) = 1, or - // e(P_0, [1]_2) * e(P_1, [X]_2) = 1 - auto P0 = C_zeta_Z + C_pi * x_challenge; - auto P1 = -C_pi; - verified = this->vk()->pairing_check(P0, P1); - // EXPECT_TRUE(verified); - } return verified; } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp index d94df58d62a..d4d69fa4514 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.cpp @@ -106,8 +106,12 @@ std::array UltraRecursiveVerifier_::ve auto [multivariate_challenge, claimed_evaluations, verified] = sumcheck.verify(relation_parameters, transcript); // Execute ZeroMorph multilinear PCS evaluation verifier - auto pairing_points = ZeroMorph::verify(commitments, claimed_evaluations, multivariate_challenge, transcript); - + auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + transcript); return pairing_points; } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp index f2ec19befbd..10931cd04b7 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp @@ -142,7 +142,8 @@ template void UltraProver_::execute_zeromorph_round { ZeroMorph::prove(instance->prover_polynomials.get_unshifted(), instance->prover_polynomials.get_to_be_shifted(), - sumcheck_output.claimed_evaluations, + sumcheck_output.claimed_evaluations.get_unshifted(), + sumcheck_output.claimed_evaluations.get_shifted(), sumcheck_output.challenge, commitment_key, transcript); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp index 2c9d2ba85d2..37a97ffeb7a 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_verifier.cpp @@ -128,7 +128,12 @@ template bool UltraVerifier_::verify_proof(const plonk // Execute ZeroMorph rounds. See https://hackmd.io/dlf9xEwhTQyE3hiGbq4FsA?view for a complete description of the // unrolled protocol. - auto pairing_points = ZeroMorph::verify(commitments, claimed_evaluations, multivariate_challenge, transcript); + auto pairing_points = ZeroMorph::verify(commitments.get_unshifted(), + commitments.get_to_be_shifted(), + claimed_evaluations.get_unshifted(), + claimed_evaluations.get_shifted(), + multivariate_challenge, + transcript); auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]);