From 343a29615ca6667a0c03d111c81b5725b0995fdd Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Thu, 17 Apr 2025 22:44:13 +0000 Subject: [PATCH] delete zeromorph --- .../ultra_bench/ultra_honk_rounds.bench.cpp | 5 +- .../zeromorph/zeromorph.hpp | 813 ------------------ .../zeromorph/zeromorph.test.cpp | 591 ------------- .../zeromorph.test.cpp | 139 --- 4 files changed, 1 insertion(+), 1547 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp diff --git a/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp index 621dfba72f9a..81d82a55b72e 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/ultra_bench/ultra_honk_rounds.bench.cpp @@ -18,8 +18,7 @@ enum { LOG_DERIVATIVE_INVERSE, GRAND_PRODUCT_COMPUTATION, GENERATE_ALPHAS, - RELATION_CHECK, - ZEROMORPH + RELATION_CHECK }; /** @@ -58,7 +57,6 @@ BB_PROFILE static void test_round_inner(State& state, MegaProver& prover, size_t DeciderProver_ decider_prover(prover.proving_key, prover.transcript); time_if_index(RELATION_CHECK, [&] { decider_prover.execute_relation_check_rounds(); }); - time_if_index(ZEROMORPH, [&] { decider_prover.execute_pcs_rounds(); }); } BB_PROFILE static void test_round(State& state, size_t index) noexcept { @@ -91,6 +89,5 @@ ROUND_BENCHMARK(LOG_DERIVATIVE_INVERSE)->Iterations(1); ROUND_BENCHMARK(GRAND_PRODUCT_COMPUTATION)->Iterations(1); ROUND_BENCHMARK(GENERATE_ALPHAS)->Iterations(1); ROUND_BENCHMARK(RELATION_CHECK); -ROUND_BENCHMARK(ZEROMORPH); BENCHMARK_MAIN(); diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp deleted file mode 100644 index 0e2350fb58f2..000000000000 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.hpp +++ /dev/null @@ -1,813 +0,0 @@ -#pragma once -#include "barretenberg/commitment_schemes/claim.hpp" -#include "barretenberg/commitment_schemes/commitment_key.hpp" -#include "barretenberg/commitment_schemes/utils/batch_mul_native.hpp" -#include "barretenberg/commitment_schemes/verification_key.hpp" -#include "barretenberg/common/debug_log.hpp" -#include "barretenberg/common/ref_span.hpp" -#include "barretenberg/common/ref_vector.hpp" -#include "barretenberg/common/zip_view.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/stdlib/primitives/biggroup/biggroup.hpp" -#include "barretenberg/stdlib/primitives/witness/witness.hpp" -#include "barretenberg/transcript/transcript.hpp" - -namespace bb { - -/** - * @brief Compute powers of a given challenge - * - * @tparam FF - * @param challenge - * @param num_powers - * @return std::vector - */ -template inline std::vector powers_of_challenge(const FF challenge, const size_t num_powers) -{ - std::vector challenge_powers = { FF(1), challenge }; - challenge_powers.reserve(num_powers); - for (size_t j = 2; j < num_powers; j++) { - challenge_powers.emplace_back(challenge_powers[j - 1] * challenge); - } - return challenge_powers; -}; - -/** - * @brief Prover for ZeroMorph multilinear PCS - * - * @tparam Curve - The curve used for arithmetising ZeroMorph - */ -template class ZeroMorphProver_ { - using FF = typename Curve::ScalarField; - using Commitment = typename Curve::AffineElement; - using Polynomial = bb::Polynomial; - using OpeningClaim = ProverOpeningClaim; - - // TODO(#742): Set this N_max to be the number of G1 elements in the mocked zeromorph SRS once it's in place. - // (Then, eventually, set it based on the real SRS). For now we set it to be larger then the Client IVC recursive - // verifier circuit. - static const size_t N_max = 1 << 25; - - public: - /** - * @brief Compute multivariate quotients q_k(X_0, ..., X_{k-1}) for f(X_0, ..., X_{n-1}) - * @details Starting from the coefficients of f, compute q_k inductively from k = n - 1, to k = 0. - * f needs to be updated at each step. - * - * First, compute q_{n-1} of size N/2 by - * q_{n-1}[l] = f[N/2 + l ] - f[l]. - * - * Update f by f[l] <- f[l] + u_{n-1} * q_{n-1}[l]; f now has size N/2. - * Compute q_{n-2} of size N/(2^2) by - * q_{n-2}[l] = f[N/2^2 + l] - f[l]. - * - * Update f by f[l] <- f[l] + u_{n-2} * q_{n-2}[l]; f now has size N/(2^2). - * Compute q_{n-3} of size N/(2^3) by - * q_{n-3}[l] = f[N/2^3 + l] - f[l]. Repeat similarly until you reach q_0. - * - * @param polynomial Multilinear polynomial f(X_0, ..., X_{d-1}) - * @param u_challenge Multivariate challenge u = (u_0, ..., u_{d-1}) - * @return std::vector The quotients q_k - */ - static std::vector compute_multilinear_quotients(Polynomial& polynomial, - std::span u_challenge) - { - DEBUG_LOG(polynomial, u_challenge); - size_t log_N = numeric::get_msb(polynomial.size()); - // Define the vector of quotients q_k, k = 0, ..., log_N-1 - std::vector quotients; - for (size_t k = 0; k < log_N; ++k) { - size_t size = 1 << k; - quotients.emplace_back(Polynomial(size)); // degree 2^k - 1 - } - - // Compute the coefficients of q_{n-1} - size_t size_q = 1 << (log_N - 1); - Polynomial q{ size_q }; - for (size_t l = 0; l < size_q; ++l) { - q.at(l) = polynomial[size_q + l] - polynomial[l]; - } - - quotients[log_N - 1] = q.share(); - DEBUG_LOG(quotients[log_N - 1], log_N - 1); - - std::vector f_k; - f_k.resize(size_q); - - std::vector g(polynomial.data(), polynomial.data() + size_q); - - // Compute q_k in reverse order from k= n-2, i.e. q_{n-2}, ..., q_0 - for (size_t k = 1; k < log_N; ++k) { - // Compute f_k - for (size_t l = 0; l < size_q; ++l) { - f_k[l] = g[l] + u_challenge[log_N - k] * q[l]; - } - - size_q = size_q / 2; - q = Polynomial{ size_q }; - - for (size_t l = 0; l < size_q; ++l) { - q.at(l) = f_k[size_q + l] - f_k[l]; - } - - quotients[log_N - k - 1] = q.share(); - g = f_k; - } - - return quotients; - } - - /** - * @brief Construct batched, lifted-degree univariate quotient \hat{q} = \sum_k y^k * X^{N - d_k - 1} * q_k - * @details The purpose of the batched lifted-degree quotient is to reduce the individual degree checks - * deg(q_k) <= 2^k - 1 to a single degree check on \hat{q}. This is done by first shifting each of the q_k to the - * right (i.e. multiplying by an appropriate power of X) so that each is degree N-1, then batching them all together - * using powers of the provided challenge. Note: In practice, we do not actually compute the shifted q_k, we simply - * accumulate them into \hat{q} at the appropriate offset. - * - * @param quotients Polynomials q_k, interpreted as univariates; deg(q_k) = 2^k - 1 - * @param N circuit size - * @return Polynomial - */ - static Polynomial compute_batched_lifted_degree_quotient(std::vector& quotients, - FF y_challenge, - size_t N) - { - DEBUG_LOG(quotients, y_challenge, N); - // Batched lifted degree quotient polynomial - auto result = Polynomial(N); - - // Compute \hat{q} = \sum_k y^k * X^{N - d_k - 1} * q_k - size_t k = 0; - auto scalar = FF(1); // y^k - for (auto& quotient : quotients) { - // Rather than explicitly computing the shifts of q_k by N - d_k - 1 (i.e. multiplying q_k by X^{N - d_k - - // 1}) then accumulating them, we simply accumulate y^k*q_k into \hat{q} at the index offset N - d_k - 1 - auto deg_k = static_cast((1 << k) - 1); - size_t offset = N - deg_k - 1; - for (size_t idx = 0; idx < deg_k + 1; ++idx) { - result.at(offset + idx) += scalar * quotient[idx]; - } - scalar *= y_challenge; // update batching scalar y^k - k++; - } - - return result; - } - - /** - * @brief Compute partially evaluated degree check polynomial \zeta_x = q - \sum_k y^k * x^{N - d_k - 1} * q_k - * @details Compute \zeta_x, where - * - * \zeta_x = q - \sum_k y^k * x^{N - d_k - 1} * q_k - * - * @param batched_quotient - * @param quotients - * @param y_challenge - * @param x_challenge - * @return Polynomial Degree check polynomial \zeta_x such that \zeta_x(x) = 0 - */ - static Polynomial compute_partially_evaluated_degree_check_polynomial(Polynomial& batched_quotient, - std::vector& quotients, - FF y_challenge, - FF x_challenge) - { - DEBUG_LOG(batched_quotient, quotients, y_challenge, x_challenge); - size_t N = batched_quotient.size(); - size_t log_N = quotients.size(); - - // Initialize partially evaluated degree check polynomial \zeta_x to \hat{q} - auto result = batched_quotient; - - auto y_power = FF(1); // y^k - for (size_t k = 0; k < log_N; ++k) { - // Accumulate y^k * x^{N - d_k - 1} * q_k into \hat{q} - auto deg_k = static_cast((1 << k) - 1); - auto x_power = x_challenge.pow(N - deg_k - 1); // x^{N - d_k - 1} - - result.add_scaled(quotients[k], -y_power * x_power); - - y_power *= y_challenge; // update batching scalar y^k - } - - return result; - } - - /** - * @brief Compute partially evaluated zeromorph identity polynomial Z_x - * @details Compute Z_x, where - * - * Z_x = x * f_batched + g_batched - v * x * \Phi_n(x) - * - x * \sum_k (x^{2^k}\Phi_{n-k-1}(x^{2^{k-1}}) - u_k\Phi_{n-k}(x^{2^k})) * q_k - * + concatentation_term - * - * 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}^{num_chunks_per_group}(x^{i * min_N + 1}concatenation_groups_batched_{i}) - * - * @note The concatenation term arises from an implementation detail in the Translator and is not part of the - * conventional ZM protocol - * @param input_polynomial - * @param quotients - * @param v_evaluation - * @param x_challenge - * @return Polynomial - */ - static Polynomial compute_partially_evaluated_zeromorph_identity_polynomial( - Polynomial& f_batched, - Polynomial& g_batched, - std::vector& quotients, - FF v_evaluation, - std::span u_challenge, - FF x_challenge, - std::vector concatenation_groups_batched = {}) - { - DEBUG_LOG( - f_batched, g_batched, quotients, v_evaluation, u_challenge, x_challenge, concatenation_groups_batched); - size_t N = f_batched.size(); - size_t log_N = quotients.size(); - - // Initialize Z_x with x * \sum_{i=0}^{m-1} f_i + \sum_{i=0}^{l-1} g_i - // Make sure g_batched does not have any starting implicit/virtual 0s as we will assign to [0] - auto result = g_batched.full(); - result.add_scaled(f_batched, x_challenge); - - // Compute Z_x -= v * x * \Phi_n(x) - auto phi_numerator = x_challenge.pow(N) - 1; // x^N - 1 - auto phi_n_x = phi_numerator / (x_challenge - 1); - result.at(0) -= v_evaluation * x_challenge * phi_n_x; - - // Add contribution from q_k polynomials - auto x_power = x_challenge; // x^{2^k} - for (size_t k = 0; k < log_N; ++k) { - x_power = x_challenge.pow(1 << k); // x^{2^k} - - // \Phi_{n-k-1}(x^{2^{k + 1}}) - auto phi_term_1 = phi_numerator / (x_challenge.pow(1 << (k + 1)) - 1); - - // \Phi_{n-k}(x^{2^k}) - auto phi_term_2 = phi_numerator / (x_challenge.pow(1 << k) - 1); - - // x^{2^k} * \Phi_{n-k-1}(x^{2^{k+1}}) - u_k * \Phi_{n-k}(x^{2^k}) - auto scalar = x_power * phi_term_1 - u_challenge[k] * phi_term_2; - - scalar *= x_challenge; - scalar *= FF(-1); - - result.add_scaled(quotients[k], scalar); - } - - // If necessary, add to Z_x the contribution related to concatenated polynomials: - // \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 Translator and is not part of the standard protocol. - if (!concatenation_groups_batched.empty()) { - size_t MINICIRCUIT_N = N / concatenation_groups_batched.size(); - auto x_to_minicircuit_N = - x_challenge.pow(MINICIRCUIT_N); // power of x used to shift polynomials to the right - auto running_shift = x_challenge; - for (size_t i = 0; i < concatenation_groups_batched.size(); i++) { - result.add_scaled(concatenation_groups_batched[i], running_shift); - running_shift *= x_to_minicircuit_N; - } - } - - return result; - } - - /** - * @brief Compute combined evaluation and degree-check polynomial pi - * @details Compute univariate polynomial pi, where - * - * pi = (\zeta_c + z*Z_x) X^{N_{max}-(N-1)} - * - * The proof that pi(x) = 0 for some verifier challenge x will then be computed as part of the univariate PCS - * opening. If this is instantiated with KZG, the PCS is going to compute the quotient - * q_pi = (q_\zeta + z*q_Z)X^{N_{max}-(N-1)}, with q_\zeta = \zeta_x/(X-x), q_Z = Z_x/(X-x), - * - * @param Z_x - * @param zeta_x - * @param x_challenge - * @param z_challenge - * @param N_max - * @return Polynomial - */ - static Polynomial compute_batched_evaluation_and_degree_check_polynomial(Polynomial& zeta_x, - Polynomial& Z_x, - FF z_challenge) - { - DEBUG_LOG(zeta_x, Z_x, z_challenge); - // We cannot commit to polynomials with size > N_max - size_t N = zeta_x.size(); - ASSERT(N <= N_max); - - // Compute batched polynomial zeta_x + Z_x - auto batched_polynomial = zeta_x; - batched_polynomial.add_scaled(Z_x, z_challenge); - - // TODO(#742): To complete the degree check, we need to do an opening proof for x_challenge with a univariate - // PCS for the degree-lifted polynomial (\zeta_c + z*Z_x)*X^{N_max - N - 1}. If this PCS is KZG, verification - // then requires a pairing check similar to the standard KZG check but with [1]_2 replaced by [X^{N_max - N - // -1}]_2. Two issues: A) we do not have an SRS with these G2 elements (so need to generate a fake setup until - // we can do the real thing), and B) its not clear to me how to update our pairing algorithms to do this type of - // pairing. For now, simply construct pi without the shift and do a standard KZG pairing check if the PCS is - // KZG. When we're ready, all we have to do to make this fully legit is commit to the shift here and update the - // pairing check accordingly. Note: When this is implemented properly, it doesnt make sense to store the - // (massive) shifted polynomial of size N_max. Ideally would only store the unshifted version and just compute - // the shifted commitment directly via a new method. - - return batched_polynomial; - } - - /** - * @brief * @brief Returns a univariate opening claim equivalent to a set of multilinear evaluation claims for - * unshifted polynomials f_i and to-be-shifted polynomials g_i to be subsequently proved with a univariate PCS - * - * @param f_polynomials Unshifted polynomials - * @param g_polynomials To-be-shifted polynomials (of which the shifts h_i were evaluated by sumcheck) - * @param evaluations Set of evaluations v_i = f_i(u), w_i = h_i(u) = g_i_shifted(u) - * @param multilinear_challenge Multilinear challenge point u - * @param commitment_key - * @param transcript - */ - template - static OpeningClaim prove(FF circuit_size, - RefSpan f_polynomials, - RefSpan g_polynomials, - RefSpan f_evaluations, - RefSpan g_shift_evaluations, - std::span multilinear_challenge, - const std::shared_ptr>& commitment_key, - const std::shared_ptr& transcript, - RefSpan concatenated_polynomials = {}, - RefSpan concatenated_evaluations = {}, - const std::vector>& concatenation_groups = {}) - { - DEBUG_LOG(f_polynomials, - g_polynomials, - g_shift_evaluations, - multilinear_challenge, - commitment_key, - transcript, - concatenated_polynomials, - concatenated_evaluations, - concatenation_groups); - // Generate batching challenge \rho and powers 1,...,\rho^{m-1} - const FF rho = transcript->template get_challenge("rho"); - - // Extract multilinear challenge u and claimed multilinear evaluations from Sumcheck output - std::span u_challenge = multilinear_challenge; - size_t log_N = numeric::get_msb(static_cast(circuit_size)); - size_t N = 1 << log_N; - - // Compute batching of unshifted polynomials f_i and to-be-shifted polynomials g_i: - // f_batched = sum_{i=0}^{m-1}\rho^i*f_i and g_batched = sum_{i=0}^{l-1}\rho^{m+i}*g_i, - // and also batched evaluation - // v = sum_{i=0}^{m-1}\rho^i*f_i(u) + sum_{i=0}^{l-1}\rho^{m+i}*h_i(u). - // Note: g_batched is formed from the to-be-shifted polynomials, but the batched evaluation incorporates the - // evaluations produced by sumcheck of h_i = g_i_shifted. - FF batched_evaluation{ 0 }; - Polynomial f_batched(N); // batched unshifted polynomials - FF batching_scalar{ 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 - 1, N, 1 }; // batched to-be-shifted polynomials - 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 - 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. - Polynomial 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}) - std::vector quotients = compute_multilinear_quotients(f_polynomial, u_challenge); - // Compute and send commitments C_{q_k} = [q_k], k = 0,...,d-1 - for (size_t idx = 0; idx < log_N; ++idx) { - Commitment q_k_commitment = commitment_key->commit(quotients[idx]); - DEBUG_LOG(idx, quotients[idx], q_k_commitment); - std::string label = "ZM:C_q_" + std::to_string(idx); - transcript->send_to_verifier(label, q_k_commitment); - } - // Add buffer elements to remove log_N dependence in proof - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1159): Decouple constants from primitives. - for (size_t idx = log_N; idx < CONST_PROOF_SIZE_LOG_N; ++idx) { - auto buffer_element = Commitment::one(); - std::string label = "ZM:C_q_" + std::to_string(idx); - transcript->send_to_verifier(label, buffer_element); - } - - // Get challenge y - FF y_challenge = transcript->template get_challenge("ZM:y"); - - // Compute the batched, lifted-degree quotient \hat{q} - auto batched_quotient = compute_batched_lifted_degree_quotient(quotients, y_challenge, N); - - // Compute and send the commitment C_q = [\hat{q}] - auto q_commitment = commitment_key->commit(batched_quotient); - transcript->send_to_verifier("ZM:C_q", q_commitment); - - // Get challenges x and z - auto [x_challenge, z_challenge] = transcript->template get_challenges("ZM:x", "ZM:z"); - - // Compute degree check polynomial \zeta partially evaluated at x - auto zeta_x = - 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, - concatenation_groups_batched); - - // Compute batched degree-check and ZM-identity quotient polynomial pi - auto pi_polynomial = compute_batched_evaluation_and_degree_check_polynomial(zeta_x, Z_x, z_challenge); - - // Returns the claim used to generate an opening proof for the univariate polynomial at x_challenge - return { pi_polynomial, { .challenge = x_challenge, .evaluation = FF(0) } }; - } -}; - -/** - * @brief Verifier for ZeroMorph multilinear PCS - * - * @tparam Curve - The Curve used to arithmetise ZeroMorph - */ -template class ZeroMorphVerifier_ { - using FF = typename Curve::ScalarField; - using Commitment = typename Curve::AffineElement; - - public: - /** - * @brief Compute commitment to partially evaluated batched lifted degree quotient identity - * @details Compute commitment C_{\zeta_x} = [\zeta_x]_1 using homomorphicity: - * - * C_{\zeta_x} = [q]_1 - \sum_k y^k * x^{N - d_k - 1} * [q_k]_1 - * - * @param C_q Commitment to batched lifted degree quotient - * @param C_q_k Commitments to quotients q_k - * @param y_challenge - * @param x_challenge - * @return Commitment - */ - static Commitment compute_C_zeta_x(const Commitment& C_q, - std::vector& C_q_k, - FF y_challenge, - FF x_challenge, - const FF log_circuit_size, - const FF circuit_size) - { - size_t N{ 0 }; - size_t log_N{ 0 }; - if constexpr (Curve::is_stdlib_type) { - N = static_cast(circuit_size.get_value()); - log_N = static_cast(log_circuit_size.get_value()); - } else { - N = static_cast(circuit_size); - log_N = static_cast(log_circuit_size); - } - - // Instantiate containers for input to batch mul - std::vector scalars; - std::vector commitments; - - // Contribution from C_q - if constexpr (Curve::is_stdlib_type) { - auto builder = x_challenge.get_context(); - scalars.emplace_back(FF(builder, 1)); - } else { - scalars.emplace_back(FF(1)); - } - commitments.emplace_back(C_q); - - // Contribution from C_q_k, k = 0,...,log_N-1 - for (size_t k = 0; k < CONST_PROOF_SIZE_LOG_N; ++k) { - // Utilize dummy rounds in order to make verifier circuit independent of proof size - bool is_dummy_round = k >= log_N; - auto deg_k = static_cast((1 << k) - 1); - // Compute scalar y^k * x^{N - deg_k - 1} - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): pow may not add proper constraints - FF scalar = y_challenge.pow(k); - size_t x_exponent = is_dummy_round ? 0 : N - deg_k - 1; - scalar *= x_challenge.pow(x_exponent); - scalar *= FF(-1); - if constexpr (Curve::is_stdlib_type) { - auto builder = x_challenge.get_context(); - FF zero = FF(0); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1114): insecure dummy_round derivation! - stdlib::bool_t dummy_round = stdlib::witness_t(builder, is_dummy_round); - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): is it kosher to reassign like this? - scalar = FF::conditional_assign(dummy_round, zero, scalar); - } else { - if (is_dummy_round) { - scalar = 0; - } - } - scalars.emplace_back(scalar); - commitments.emplace_back(C_q_k[k]); - } - - // Compute batch mul to get the result - if constexpr (Curve::is_stdlib_type) { - // If Ultra and using biggroup, handle edge cases in batch_mul - if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { - return Commitment::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); - } else { - return Commitment::batch_mul(commitments, scalars); - } - } else { - return batch_mul_native(commitments, scalars); - } - } - - /** - * @brief Compute commitment to partially evaluated ZeroMorph identity Z - * @details Compute commitment C_{Z_x} = [Z_x]_1 using homomorphicity: - * - * C_{Z_x} = x * \sum_{i=0}^{m-1}\rho^i*[f_i] + \sum_{i=0}^{l-1}\rho^{m+i}*[g_i] - v * x * \Phi_n(x) * [1]_1 - * - x * \sum_k (x^{2^k}\Phi_{n-k-1}(x^{2^{k-1}}) - u_k\Phi_{n-k}(x^{2^k})) * [q_k] - * + concatentation_term - * where - * - * 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 Translator and is not part of the - * conventional ZM protocol - * @param g1_identity first element in the SRS - * @param f_commitments Commitments to unshifted polynomials [f_i] - * @param g_commitments Commitments to to-be-shifted polynomials [g_i] - * @param C_q_k Commitments to q_k - * @param rho - * @param batched_evaluation \sum_{i=0}^{m-1} \rho^i*f_i(u) + \sum_{i=0}^{l-1} \rho^{m+i}*h_i(u) - * @param x_challenge - * @param u_challenge multilinear challenge - * @param concatenation_groups_commitments - * @return Commitment - */ - static Commitment compute_C_Z_x(const Commitment& g1_identity, - RefSpan f_commitments, - RefSpan g_commitments, - std::span C_q_k, - FF rho, - FF batched_evaluation, - FF x_challenge, - std::span u_challenge, - const FF log_circuit_size, - const FF circuit_size, - const std::vector>& concatenation_groups_commitments = {}) - { - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1144): Add proper constraints for taking the log of - // a field_t. - size_t N{ 0 }; - size_t log_N{ 0 }; - if constexpr (Curve::is_stdlib_type) { - N = static_cast(circuit_size.get_value()); - log_N = static_cast(log_circuit_size.get_value()); - } else { - N = static_cast(circuit_size); - log_N = static_cast(log_circuit_size); - } - - std::vector scalars; - std::vector commitments; - - // Phi_n(x) = (x^N - 1) / (x - 1) - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): pow may not add proper constraints - auto phi_numerator = x_challenge.pow(N) - 1; // x^N - 1 - auto phi_n_x = phi_numerator / (x_challenge - 1); - - // Add contribution: -v * x * \Phi_n(x) * [1]_1 - scalars.emplace_back(FF(-1) * batched_evaluation * x_challenge * phi_n_x); - - commitments.emplace_back(g1_identity); - - // Add contribution: x * \sum_{i=0}^{m-1} \rho^i*[f_i] - auto rho_pow = FF(1); - for (auto& commitment : f_commitments) { - scalars.emplace_back(x_challenge * rho_pow); - commitments.emplace_back(commitment); - rho_pow *= rho; - } - - // Add contribution: \sum_{i=0}^{l-1} \rho^{m+i}*[g_i] - for (auto& commitment : g_commitments) { - scalars.emplace_back(rho_pow); - commitments.emplace_back(commitment); - rho_pow *= rho; - } - - // If applicable, add contribution from concatenated polynomial commitments - // Note: this is an implementation detail related to Translator and is not part of the standard protocol. - if (!concatenation_groups_commitments.empty()) { - size_t CONCATENATION_GROUP_SIZE = concatenation_groups_commitments[0].size(); - size_t MINICIRCUIT_N = N / CONCATENATION_GROUP_SIZE; - std::vector x_shifts; - auto current_x_shift = x_challenge; - auto x_to_minicircuit_n = x_challenge.pow(MINICIRCUIT_N); - for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { - x_shifts.emplace_back(current_x_shift); - current_x_shift *= x_to_minicircuit_n; - } - for (auto& concatenation_group_commitment : concatenation_groups_commitments) { - for (size_t i = 0; i < CONCATENATION_GROUP_SIZE; ++i) { - scalars.emplace_back(rho_pow * x_shifts[i]); - commitments.emplace_back(concatenation_group_commitment[i]); - } - rho_pow *= rho; - } - } - - // Add contributions: scalar * [q_k], k = 0,...,log_N, where - // scalar = -x * (x^{2^k} * \Phi_{n-k-1}(x^{2^{k+1}}) - u_k * \Phi_{n-k}(x^{2^k})) - auto x_pow_2k = x_challenge; // x^{2^k} - auto x_pow_2kp1 = x_challenge * x_challenge; // x^{2^{k + 1}} - for (size_t k = 0; k < CONST_PROOF_SIZE_LOG_N; ++k) { - // Utilize dummy rounds in order to make verifier circuit independent of proof size - bool is_dummy_round = k >= log_N; - if constexpr (Curve::is_stdlib_type) { - auto builder = x_challenge.get_context(); - stdlib::bool_t dummy_scalar = stdlib::witness_t(builder, is_dummy_round); - auto phi_term_1 = phi_numerator / (x_pow_2kp1 - 1); // \Phi_{n-k-1}(x^{2^{k + 1}}) - auto phi_term_2 = phi_numerator / (x_pow_2k - 1); // \Phi_{n-k}(x^{2^k}) - - auto scalar = x_pow_2k * phi_term_1; - scalar -= u_challenge[k] * phi_term_2; - scalar *= x_challenge; - scalar *= -FF(1); - - FF zero = FF::from_witness(builder, 0); - scalar = FF::conditional_assign(dummy_scalar, zero, scalar); - scalars.emplace_back(scalar); - commitments.emplace_back(C_q_k[k]); - - x_pow_2k = FF::conditional_assign(dummy_scalar, x_pow_2k, x_pow_2kp1); - x_pow_2kp1 = FF::conditional_assign(dummy_scalar, x_pow_2kp1, x_pow_2kp1 * x_pow_2kp1); - } else { - if (is_dummy_round) { - scalars.emplace_back(0); - commitments.emplace_back(C_q_k[k]); - } else { - auto phi_term_1 = phi_numerator / (x_pow_2kp1 - 1); // \Phi_{n-k-1}(x^{2^{k + 1}}) - auto phi_term_2 = phi_numerator / (x_pow_2k - 1); // \Phi_{n-k}(x^{2^k}) - - auto scalar = x_pow_2k * phi_term_1; - scalar -= u_challenge[k] * phi_term_2; - scalar *= x_challenge; - scalar *= FF(-1); - - scalars.emplace_back(scalar); - commitments.emplace_back(C_q_k[k]); - - // Update powers of challenge x - x_pow_2k = x_pow_2kp1; - x_pow_2kp1 *= x_pow_2kp1; - } - } - } - - if constexpr (Curve::is_stdlib_type) { - // If Ultra and using biggroup, handle edge cases in batch_mul - if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { - return Commitment::batch_mul(commitments, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); - } else { - return Commitment::batch_mul(commitments, scalars); - } - } else { - return batch_mul_native(commitments, scalars); - } - } - - /** - * @brief Return the univariate opening claim used to verify, in a subsequent PCS, a set of multilinear evaluation - * claims for unshifted polynomials f_i and to-be-shifted polynomials g_i - * - * @param commitments Commitments to polynomials f_i and g_i (unshifted and to-be-shifted) - * @param claimed_evaluations Claimed evaluations v_i = f_i(u) and w_i = h_i(u) = g_i_shifted(u) - * @param multivariate_challenge Challenge point u - * @param transcript - * @return VerifierAccumulator Inputs to the final PCS verification check that will be accumulated - */ - template - static OpeningClaim verify(FF circuit_size, - RefSpan unshifted_commitments, - RefSpan to_be_shifted_commitments, - RefSpan unshifted_evaluations, - RefSpan shifted_evaluations, - std::span multivariate_challenge, - const Commitment& g1_identity, - const std::shared_ptr& transcript, - const std::vector>& concatenation_group_commitments = {}, - RefSpan concatenated_evaluations = {}) - { - FF log_N; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1039): Connect witness log_N to circuit size - if constexpr (Curve::is_stdlib_type) { - log_N = FF(static_cast(numeric::get_msb(static_cast(circuit_size.get_value())))); - } else { - log_N = numeric::get_msb(static_cast(circuit_size)); - } - FF rho = transcript->template get_challenge("rho"); - - // 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); - 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] - std::vector C_q_k; - C_q_k.reserve(CONST_PROOF_SIZE_LOG_N); - for (size_t i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { - C_q_k.emplace_back(transcript->template receive_from_prover("ZM:C_q_" + std::to_string(i))); - } - - // Challenge y - FF y_challenge = transcript->template get_challenge("ZM:y"); - - // Receive commitment C_{q} - auto C_q = transcript->template receive_from_prover("ZM:C_q"); - - // Challenges x, z - auto [x_challenge, z_challenge] = transcript->template get_challenges("ZM:x", "ZM:z"); - - // Compute commitment C_{\zeta_x} - auto C_zeta_x = compute_C_zeta_x(C_q, C_q_k, y_challenge, x_challenge, log_N, circuit_size); - - // Compute commitment C_{Z_x} - Commitment C_Z_x = compute_C_Z_x(g1_identity, - unshifted_commitments, - to_be_shifted_commitments, - C_q_k, - rho, - batched_evaluation, - x_challenge, - multivariate_challenge, - log_N, - circuit_size, - concatenation_group_commitments); - - // Compute commitment C_{\zeta,Z} - Commitment C_zeta_Z; - if constexpr (Curve::is_stdlib_type) { - // Express operation as a batch_mul in order to use Goblinization if available - auto builder = z_challenge.get_context(); - std::vector scalars = { FF(builder, 1), z_challenge }; - std::vector points = { C_zeta_x, C_Z_x }; - // If Ultra and using biggroup, handle edge cases in batch_mul - if constexpr (IsUltraBuilder && stdlib::IsBigGroup) { - C_zeta_Z = Commitment::batch_mul(points, scalars, /*max_num_bits=*/0, /*with_edgecases=*/true); - } else { - C_zeta_Z = Commitment::batch_mul(points, scalars); - } - } else { - C_zeta_Z = C_zeta_x + C_Z_x * z_challenge; - } - - return { .opening_pair = { .challenge = x_challenge, .evaluation = FF(0) }, .commitment = C_zeta_Z }; - } -}; - -} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp deleted file mode 100644 index a816c3635771..000000000000 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/zeromorph/zeromorph.test.cpp +++ /dev/null @@ -1,591 +0,0 @@ -// #include "zeromorph.hpp" -// #include "barretenberg/commitment_schemes/commitment_key.test.hpp" -// #include "barretenberg/commitment_schemes/ipa/ipa.hpp" -// #include "barretenberg/commitment_schemes/kzg/kzg.hpp" -// #include - -// namespace bb { - -// template class ZeroMorphTest : public CommitmentTest { -// public: -// using Curve = typename PCS::Curve; -// using Fr = typename Curve::ScalarField; -// using Polynomial = bb::Polynomial; -// using Commitment = typename Curve::AffineElement; -// using GroupElement = typename Curve::Element; -// using VerifierAccumulator = typename PCS::VerifierAccumulator; -// using ZeroMorphProver = ZeroMorphProver_; -// using ZeroMorphVerifier = ZeroMorphVerifier_; - -// using TupleOfConcatenationInputs = std::tuple>, -// std::vector, -// std::vector, -// std::vector>>; - -// /** -// * @brief Data structure for encapsulating a set of multilinear polynomials used to test the protocol, their -// * evaluations at the point that we want to create an evaluation proof for and -// * their commitments. Alternatively, the polynomials and commitments can be the ones to-be-shifted, while the -// * evaluations are for their shifted version. -// * -// */ -// struct PolynomialsEvaluationsCommitments { -// std::vector polynomials; -// std::vector evaluations; -// std::vector commitments; -// }; - -// /** -// * @brief Data structure used to test the protocol's alternative for Goblin Translator. -// * -// */ -// struct ConcatenationInputs { -// std::vector> concatenation_groups; -// std::vector concatenated_polynomials; -// std::vector c_evaluations; -// std::vector> concatenation_groups_commitments; -// }; - -// /** -// * @brief Evaluate Phi_k(x) = \sum_{i=0}^k x^i using the direct inefficent formula -// * -// */ -// Fr Phi(Fr challenge, size_t subscript) -// { -// size_t length = 1 << subscript; -// auto result = Fr(0); -// for (size_t idx = 0; idx < length; ++idx) { -// result += challenge.pow(idx); -// } -// return result; -// } - -// /** -// * @brief Construct and verify ZeroMorph proof of batched multilinear evaluation with shifts -// * @details The goal is to construct and verify a single batched multilinear evaluation proof for m polynomials -// f_i -// * and l polynomials h_i. It is assumed that the h_i are shifts of polynomials g_i (the "to-be-shifted" -// * polynomials), which are a subset of the f_i. This is what is encountered in practice. We accomplish this using -// * evaluations of h_i but commitments to only their unshifted counterparts g_i (which we get for "free" since -// * commitments [g_i] are contained in the set of commitments [f_i]). -// */ -// bool execute_zeromorph_protocol(size_t NUM_UNSHIFTED, -// size_t NUM_SHIFTED, -// [[maybe_unused]] size_t NUM_CONCATENATED = 0) -// { -// size_t N = 2; -// size_t log_N = numeric::get_msb(N); - -// std::vector u_challenge = this->random_evaluation_point(log_N); - -// // Construct some random multilinear polynomials f_i, their commitments and their evaluations v_i = f_i(u) -// PolynomialsEvaluationsCommitments unshifted_input = -// polynomials_comms_and_evaluations(u_challenge, NUM_UNSHIFTED); - -// // Construct polynomials and commitments from f_i that are to be shifted and compute their shifted -// evaluations PolynomialsEvaluationsCommitments shifted_input = -// to_be_shifted_polynomials_and_comms_and_shifted_evaluations(unshifted_input, u_challenge, NUM_SHIFTED); - -// bool verified = false; -// if (NUM_CONCATENATED == 0) { -// verified = prove_and_verify(N, unshifted_input, shifted_input, u_challenge); -// } else { -// verified = -// prove_and_verify_with_concatenation(N, unshifted_input, shifted_input, u_challenge, -// NUM_CONCATENATED); -// } - -// return verified; -// } - -// /** -// * @brief Generate some random multilinear polynomials and compute their evaluation at the set challenge as well -// as -// * their commitments, returned as a tuple to be used in the subsequent protocol. -// */ -// PolynomialsEvaluationsCommitments polynomials_comms_and_evaluations(std::vector u_challenge, -// size_t NUM_UNSHIFTED) -// { -// // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) -// std::vector f_polynomials; // unshifted polynomials -// std::vector v_evaluations; -// std::vector f_commitments; -// size_t poly_length = 1 << u_challenge.size(); -// for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { -// f_polynomials.emplace_back(Polynomial::random(poly_length, 1)); // ensure f is "shiftable" -// v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); -// f_commitments.emplace_back(this->commit(f_polynomials[i])); -// } -// return { f_polynomials, v_evaluations, f_commitments }; -// } - -// /** -// * @brief Generate shifts of polynomials and compute their evaluation at the -// * set challenge as well as their commitments, returned as a tuple to be used in the subsequent protocol. -// */ -// PolynomialsEvaluationsCommitments to_be_shifted_polynomials_and_comms_and_shifted_evaluations( -// PolynomialsEvaluationsCommitments unshifted_inputs, std::vector u_challenge, size_t NUM_SHIFTED) -// { -// std::vector f_polynomials = unshifted_inputs.polynomials; -// std::vector f_commitments = unshifted_inputs.commitments; - -// std::vector g_polynomials; // to-be-shifted polynomials -// std::vector h_polynomials; // shifts of the to-be-shifted polynomials -// std::vector w_evaluations; // shifted evaluations -// std::vector g_commitments; - -// // For testing purposes, pick the first NUM_SHIFTED polynomials to be shifted -// for (size_t i = 0; i < NUM_SHIFTED; ++i) { -// g_polynomials.emplace_back(f_polynomials[i]); -// h_polynomials.emplace_back(g_polynomials[i].shifted()); -// w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); -// g_commitments.emplace_back(f_commitments[i]); -// } -// return { g_polynomials, w_evaluations, g_commitments }; -// } - -// /** -// * @brief Generate the tuple of concatenation inputs used to test Zeromorph special functionality that avoids -// high -// * degrees in the Goblin Translator. -// */ -// ConcatenationInputs concatenation_inputs(std::vector u_challenge, size_t NUM_CONCATENATED) -// { - -// size_t concatenation_index = 2; -// size_t N = 1 << u_challenge.size(); -// size_t MINI_CIRCUIT_N = N / concatenation_index; - -// // Polynomials "chunks" that are concatenated in the PCS -// std::vector> concatenation_groups; - -// // Concatenated polynomials -// std::vector concatenated_polynomials; - -// // Evaluations of concatenated polynomials -// std::vector c_evaluations; - -// // For each polynomial to be concatenated -// for (size_t i = 0; i < NUM_CONCATENATED; ++i) { -// std::vector concatenation_group; -// Polynomial concatenated_polynomial(N); -// // For each chunk -// for (size_t j = 0; j < concatenation_index; j++) { -// Polynomial chunk_polynomial(N); -// // Fill the chunk polynomial with random values and appropriately fill the space in -// // concatenated_polynomial -// for (size_t k = 0; k < MINI_CIRCUIT_N; k++) { -// // Chunks should be shiftable -// auto tmp = Fr(0); -// if (k > 0) { -// tmp = Fr::random_element(this->engine); -// } -// chunk_polynomial.at(k) = tmp; -// concatenated_polynomial.at(j * MINI_CIRCUIT_N + k) = tmp; -// } -// concatenation_group.emplace_back(chunk_polynomial); -// } -// // Store chunks -// concatenation_groups.emplace_back(concatenation_group); -// // Store concatenated polynomial -// concatenated_polynomials.emplace_back(concatenated_polynomial); -// // Get evaluation -// c_evaluations.emplace_back(concatenated_polynomial.evaluate_mle(u_challenge)); -// } - -// // Compute commitments of all polynomial chunks -// std::vector> concatenation_groups_commitments; -// for (size_t i = 0; i < NUM_CONCATENATED; ++i) { -// std::vector concatenation_group_commitment; -// for (size_t j = 0; j < concatenation_index; j++) { -// concatenation_group_commitment.emplace_back(this->commit(concatenation_groups[i][j])); -// } -// concatenation_groups_commitments.emplace_back(concatenation_group_commitment); -// } - -// return { concatenation_groups, concatenated_polynomials, c_evaluations, concatenation_groups_commitments }; -// }; - -// bool prove_and_verify(size_t N, -// PolynomialsEvaluationsCommitments& unshifted, -// PolynomialsEvaluationsCommitments& shifted, -// std::vector u_challenge) -// { -// auto prover_transcript = NativeTranscript::prover_init_empty(); - -// // Execute Prover protocol -// auto prover_opening_claim = ZeroMorphProver::prove(N, -// RefVector(unshifted.polynomials), // unshifted -// RefVector(shifted.polynomials), // to-be shifted -// RefVector(unshifted.evaluations), // unshifted -// RefVector(shifted.evaluations), // shifted -// u_challenge, -// this->commitment_key, -// prover_transcript); - -// PCS::compute_opening_proof(this->commitment_key, prover_opening_claim, prover_transcript); - -// auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); - -// auto verifier_opening_claim = ZeroMorphVerifier::verify(N, -// RefVector(unshifted.commitments), // unshifted -// RefVector(shifted.commitments), // to-be-shifted -// RefVector(unshifted.evaluations), // unshifted -// RefVector(shifted.evaluations), // shifted -// u_challenge, -// this->vk()->get_g1_identity(), -// verifier_transcript); -// VerifierAccumulator result; - -// bool verified = false; -// if constexpr (std::same_as>) { - -// result = PCS::reduce_verify(verifier_opening_claim, verifier_transcript); -// verified = this->vk()->pairing_check(result[0], result[1]); -// } else { -// // Execute Verifier protocol with vk -// verified = PCS::reduce_verify(this->vk(), verifier_opening_claim, verifier_transcript); -// } - -// // The prover and verifier manifests should agree -// EXPECT_EQ(prover_transcript->get_manifest(), verifier_transcript->get_manifest()); -// return verified; -// }; - -// bool prove_and_verify_with_concatenation(size_t N, -// PolynomialsEvaluationsCommitments& unshifted, -// PolynomialsEvaluationsCommitments& shifted, -// std::vector u_challenge, -// size_t NUM_CONCATENATED) -// { -// ConcatenationInputs concatenation = concatenation_inputs(u_challenge, NUM_CONCATENATED); - -// auto prover_transcript = NativeTranscript::prover_init_empty(); - -// // Execute Prover protocol -// auto prover_opening_claim = -// ZeroMorphProver::prove(N, -// RefVector(unshifted.polynomials), // unshifted -// RefVector(shifted.polynomials), // to-be-shifted -// RefVector(unshifted.evaluations), // unshifted -// RefVector(shifted.evaluations), // shifted -// u_challenge, -// this->commitment_key, -// prover_transcript, -// RefVector(concatenation.concatenated_polynomials), -// RefVector(concatenation.c_evaluations), -// to_vector_of_ref_vectors(concatenation.concatenation_groups)); -// PCS::compute_opening_proof(this->commitment_key, prover_opening_claim, prover_transcript); - -// auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); - -// auto verifier_opening_claim = -// ZeroMorphVerifier::verify(N, -// RefVector(unshifted.commitments), // unshifted -// RefVector(shifted.commitments), // to-be-shifted -// RefVector(unshifted.evaluations), // unshifted -// RefVector(shifted.evaluations), // shifted -// u_challenge, -// this->vk()->get_g1_identity(), -// verifier_transcript, -// to_vector_of_ref_vectors(concatenation.concatenation_groups_commitments), -// RefVector(concatenation.c_evaluations)); -// VerifierAccumulator result; - -// bool verified = false; -// if constexpr (std::same_as>) { - -// result = PCS::reduce_verify(verifier_opening_claim, verifier_transcript); -// verified = this->vk()->pairing_check(result[0], result[1]); -// } else { -// // Execute Verifier protocol with vk -// verified = PCS::reduce_verify(this->vk(), verifier_opening_claim, verifier_transcript); -// } - -// // The prover and verifier manifests should agree -// EXPECT_EQ(prover_transcript->get_manifest(), verifier_transcript->get_manifest()); -// return verified; -// } -// }; - -// using PCSTypes = ::testing::Types, IPA>; -// TYPED_TEST_SUITE(ZeroMorphTest, PCSTypes); - -// /** -// * @brief Test method for computing q_k given multilinear f -// * @details Given f = f(X_0, ..., X_{d-1}), and (u,v) such that f(u) = v, compute q_k = q_k(X_0, ..., X_{k-1}) such -// that -// * the following identity holds: -// * -// * f(X_0, ..., X_{d-1}) - v = \sum_{k=0}^{d-1} (X_k - u_k)q_k(X_0, ..., X_{k-1}) -// * -// */ -// TYPED_TEST(ZeroMorphTest, QuotientConstruction) -// { -// // Define some useful type aliases -// using Curve = typename TypeParam::Curve; -// using ZeroMorphProver = ZeroMorphProver_; -// using Fr = typename Curve::ScalarField; -// using Polynomial = bb::Polynomial; - -// // Define size parameters -// size_t N = 16; -// size_t log_N = numeric::get_msb(N); - -// // Construct a random multilinear polynomial f, and (u,v) such that f(u) = v. -// Polynomial multilinear_f = Polynomial::random(N); -// std::vector u_challenge = this->random_evaluation_point(log_N); -// Fr v_evaluation = multilinear_f.evaluate_mle(u_challenge); - -// // Compute the multilinear quotients q_k = q_k(X_0, ..., X_{k-1}) -// std::vector quotients = ZeroMorphProver::compute_multilinear_quotients(multilinear_f, u_challenge); - -// // Show that the q_k were properly constructed by showing that the identity holds at a random multilinear -// challenge -// // z, i.e. f(z) - v - \sum_{k=0}^{d-1} (z_k - u_k)q_k(z) = 0 -// std::vector z_challenge = this->random_evaluation_point(log_N); - -// Fr result = multilinear_f.evaluate_mle(z_challenge); -// result -= v_evaluation; -// for (size_t k = 0; k < log_N; ++k) { -// auto q_k_eval = Fr(0); -// if (k == 0) { -// // q_0 = a_0 is a constant polynomial so it's evaluation is simply its constant coefficient -// q_k_eval = quotients[k][0]; -// } else { -// // Construct (u_0, ..., u_{k-1}) -// auto subrange_size = static_cast(k); -// std::vector z_partial(z_challenge.begin(), z_challenge.begin() + subrange_size); -// q_k_eval = quotients[k].evaluate_mle(z_partial); -// } -// // result = result - (z_k - u_k) * q_k(u_0, ..., u_{k-1}) -// result -= (z_challenge[k] - u_challenge[k]) * q_k_eval; -// } - -// EXPECT_EQ(result, 0); -// } - -// /** -// * @brief Test function for constructing batched lifted degree quotient \hat{q} -// * -// */ -// TYPED_TEST(ZeroMorphTest, BatchedLiftedDegreeQuotient) -// { -// // Define some useful type aliases -// using Curve = typename TypeParam::Curve; -// using ZeroMorphProver = ZeroMorphProver_; -// using Fr = typename Curve::ScalarField; -// using Polynomial = bb::Polynomial; - -// const size_t N = 8; - -// // Define some mock q_k with deg(q_k) = 2^k - 1 -// std::vector data_0 = { 1 }; -// std::vector data_1 = { 2, 3 }; -// std::vector data_2 = { 4, 5, 6, 7 }; -// Polynomial q_0(data_0); -// Polynomial q_1(data_1); -// Polynomial q_2(data_2); -// std::vector quotients = { q_0, q_1, q_2 }; - -// auto y_challenge = Fr::random_element(); - -// // Compute batched quotient \hat{q} using the prover method -// auto batched_quotient = ZeroMorphProver::compute_batched_lifted_degree_quotient(quotients, y_challenge, N); - -// // Now explicitly define q_k_lifted = X^{N-2^k} * q_k and compute the expected batched result -// std::array data_0_lifted = { 0, 0, 0, 0, 0, 0, 0, 1 }; -// std::array data_1_lifted = { 0, 0, 0, 0, 0, 0, 2, 3 }; -// std::array data_2_lifted = { 0, 0, 0, 0, 4, 5, 6, 7 }; -// Polynomial q_0_lifted(data_0_lifted); -// Polynomial q_1_lifted(data_1_lifted); -// Polynomial q_2_lifted(data_2_lifted); - -// // Explicitly compute \hat{q} -// auto batched_quotient_expected = Polynomial(N); -// batched_quotient_expected += q_0_lifted; -// batched_quotient_expected.add_scaled(q_1_lifted, y_challenge); -// batched_quotient_expected.add_scaled(q_2_lifted, y_challenge * y_challenge); - -// EXPECT_EQ(batched_quotient, batched_quotient_expected); -// } - -// /** -// * @brief Test function for constructing partially evaluated quotient \zeta_x -// * -// */ -// TYPED_TEST(ZeroMorphTest, PartiallyEvaluatedQuotientZeta) -// { -// // Define some useful type aliases -// using Curve = typename TypeParam::Curve; -// using ZeroMorphProver = ZeroMorphProver_; -// using Fr = typename Curve::ScalarField; -// using Polynomial = bb::Polynomial; - -// const size_t N = 8; - -// // Define some mock q_k with deg(q_k) = 2^k - 1 -// std::vector data_0 = { 1 }; -// std::vector data_1 = { 2, 3 }; -// std::vector data_2 = { 4, 5, 6, 7 }; -// Polynomial q_0(data_0); -// Polynomial q_1(data_1); -// Polynomial q_2(data_2); -// std::vector quotients = { q_0, q_1, q_2 }; - -// auto y_challenge = Fr::random_element(); - -// auto batched_quotient = ZeroMorphProver::compute_batched_lifted_degree_quotient(quotients, y_challenge, N); - -// auto x_challenge = Fr::random_element(); - -// // Contruct zeta_x using the prover method -// auto zeta_x = ZeroMorphProver::compute_partially_evaluated_degree_check_polynomial( -// batched_quotient, quotients, y_challenge, x_challenge); - -// // Now construct zeta_x explicitly -// auto zeta_x_expected = Polynomial(N); -// zeta_x_expected += batched_quotient; -// // q_batched - \sum_k q_k * y^k * x^{N - deg(q_k) - 1} -// zeta_x_expected.add_scaled(q_0, -x_challenge.pow(N - 0 - 1)); -// zeta_x_expected.add_scaled(q_1, -y_challenge * x_challenge.pow(N - 1 - 1)); -// zeta_x_expected.add_scaled(q_2, -y_challenge * y_challenge * x_challenge.pow(N - 3 - 1)); - -// EXPECT_EQ(zeta_x, zeta_x_expected); -// } - -// /** -// * @brief Demonstrate formulas for efficiently computing \Phi_k(x) = \sum_{i=0}^{k-1}x^i -// * @details \Phi_k(x) = \sum_{i=0}^{k-1}x^i = (x^{2^k} - 1) / (x - 1) -// * -// */ -// TYPED_TEST(ZeroMorphTest, PhiEvaluation) -// { -// using Curve = typename TypeParam::Curve; -// using Fr = typename Curve::ScalarField; -// const size_t N = 8; -// size_t n = numeric::get_msb(N); - -// // \Phi_n(x) -// { -// auto x_challenge = Fr::random_element(); - -// auto efficient = (x_challenge.pow(1 << n) - 1) / (x_challenge - 1); - -// auto expected = this->Phi(x_challenge, n); - -// EXPECT_EQ(efficient, expected); -// } - -// // \Phi_{n-k-1}(x^{2^{k + 1}}) = (x^{2^n} - 1) / (x^{2^{k + 1}} - 1) -// { -// auto x_challenge = Fr::random_element(); - -// size_t k = 2; - -// // x^{2^{k+1}} -// auto x_pow = x_challenge.pow(1 << (k + 1)); - -// auto efficient = x_challenge.pow(1 << n) - 1; // x^N - 1 -// efficient = efficient / (x_pow - 1); // (x^N - 1) / (x^{2^{k + 1}} - 1) - -// auto expected = this->Phi(x_pow, n - k - 1); -// EXPECT_EQ(efficient, expected); -// } -// } - -// /** -// * @brief Test function for constructing partially evaluated quotient Z_x -// * -// */ -// TYPED_TEST(ZeroMorphTest, PartiallyEvaluatedQuotientZ) -// { -// // Define some useful type aliases -// using Curve = typename TypeParam::Curve; -// using ZeroMorphProver = ZeroMorphProver_; -// using Fr = typename Curve::ScalarField; -// using Polynomial = bb::Polynomial; - -// const size_t N = 8; -// size_t log_N = numeric::get_msb(N); - -// // Construct a random multilinear polynomial f, and (u,v) such that f(u) = v. -// Polynomial multilinear_f = Polynomial::random(N); -// Polynomial multilinear_g = Polynomial::random(N, /* starting index for shift */ 1); -// std::vector u_challenge = this->random_evaluation_point(log_N); -// Fr v_evaluation = multilinear_f.evaluate_mle(u_challenge); -// Fr w_evaluation = multilinear_g.evaluate_mle(u_challenge, /* shift = */ true); - -// auto rho = Fr::random_element(); - -// // compute batched polynomial and evaluation -// auto f_batched = multilinear_f; -// auto g_batched = multilinear_g; -// g_batched *= rho; -// auto v_batched = v_evaluation + rho * w_evaluation; - -// // Define some mock q_k with deg(q_k) = 2^k - 1 -// auto q_0 = Polynomial::random(1 << 0); -// auto q_1 = Polynomial::random(1 << 1); -// auto q_2 = Polynomial::random(1 << 2); -// std::vector quotients = { q_0, q_1, q_2 }; - -// auto x_challenge = Fr::random_element(); - -// // Construct Z_x using the prover method -// auto Z_x = ZeroMorphProver::compute_partially_evaluated_zeromorph_identity_polynomial( -// f_batched, g_batched, quotients, v_batched, u_challenge, x_challenge); - -// // Compute Z_x directly -// // Expand g_batched as it has a virtual 0 -// auto Z_x_expected = g_batched.full(); -// Z_x_expected.add_scaled(f_batched, x_challenge); -// Z_x_expected.at(0) -= v_batched * x_challenge * this->Phi(x_challenge, log_N); -// for (size_t k = 0; k < log_N; ++k) { -// auto x_pow_2k = x_challenge.pow(1 << k); // x^{2^k} -// auto x_pow_2kp1 = x_challenge.pow(1 << (k + 1)); // x^{2^{k+1}} -// // x^{2^k} * \Phi_{n-k-1}(x^{2^{k+1}}) - u_k * \Phi_{n-k}(x^{2^k}) -// auto scalar = x_pow_2k * this->Phi(x_pow_2kp1, log_N - k - 1) - u_challenge[k] * this->Phi(x_pow_2k, log_N - -// k); scalar *= x_challenge; scalar *= Fr(-1); Z_x_expected.add_scaled(quotients[k], scalar); -// } - -// EXPECT_EQ(Z_x, Z_x_expected); -// } - -// /** -// * @brief Test full Prover/Verifier protocol for proving single multilinear evaluation -// * -// */ -// TYPED_TEST(ZeroMorphTest, ProveAndVerifySingle) -// { -// size_t num_unshifted = 1; -// size_t num_shifted = 0; -// auto verified = this->execute_zeromorph_protocol(num_unshifted, num_shifted); -// EXPECT_TRUE(verified); -// } - -// /** -// * @brief Test full Prover/Verifier protocol for proving batched multilinear evaluation with shifts -// * -// */ -// TYPED_TEST(ZeroMorphTest, ProveAndVerifyBatchedWithShifts) -// { -// size_t num_unshifted = 3; -// size_t num_shifted = 2; -// auto verified = this->execute_zeromorph_protocol(num_unshifted, num_shifted); -// EXPECT_TRUE(verified); -// } - -// /** -// * @brief Test full Prover/Verifier protocol for proving single multilinear evaluation -// * -// */ -// TYPED_TEST(ZeroMorphTest, ProveAndVerifyWithConcatenation) -// { -// size_t num_unshifted = 1; -// size_t num_shifted = 0; -// size_t num_concatenated = 3; -// auto verified = this->execute_zeromorph_protocol(num_unshifted, num_shifted, num_concatenated); -// EXPECT_TRUE(verified); -// } -// } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp deleted file mode 100644 index 4ec991706c91..000000000000 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes_recursion/zeromorph.test.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include "barretenberg/commitment_schemes/zeromorph/zeromorph.hpp" -#include "barretenberg/circuit_checker/circuit_checker.hpp" -#include "barretenberg/commitment_schemes/commitment_key.test.hpp" -#include "barretenberg/commitment_schemes/ipa/ipa.hpp" -#include "barretenberg/commitment_schemes/kzg/kzg.hpp" -#include "barretenberg/srs/global_crs.hpp" -#include "barretenberg/stdlib/primitives/curves/bn254.hpp" -#include "barretenberg/stdlib/primitives/curves/grumpkin.hpp" -#include "barretenberg/stdlib/transcript/transcript.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include - -using namespace bb; - -template class ZeroMorphRecursionTest : public CommitmentTest {}; - -numeric::RNG& engine = numeric::get_debug_randomness(); - -/** - * @brief Test full Prover/Verifier protocol for proving single multilinear evaluation - * - */ -TEST(ZeroMorphRecursionTest, ProveAndVerifySingle) -{ - // Define some useful type aliases - using Builder = UltraCircuitBuilder; - using Curve = typename stdlib::bn254; - using NativeCurve = typename Curve::NativeCurve; - using Commitment = typename Curve::AffineElement; - using NativeCommitment = typename Curve::AffineElementNative; - using NativeCurve = typename Curve::NativeCurve; - using NativePCS = std::conditional_t, KZG, IPA>; - using CommitmentKey = typename NativePCS::CK; - using ZeroMorphProver = ZeroMorphProver_; - using Fr = typename Curve::ScalarField; - using NativeFr = typename Curve::NativeCurve::ScalarField; - using Polynomial = bb::Polynomial; - using ZeroMorphVerifier = ZeroMorphVerifier_; - using Transcript = bb::BaseTranscript>; - - constexpr size_t N = 8; - constexpr size_t LOG_N = 3; - constexpr size_t NUM_UNSHIFTED = 2; - constexpr size_t NUM_SHIFTED = 1; - - srs::init_crs_factory(bb::srs::get_ignition_crs_path()); - std::vector u_challenge(LOG_N); - for (size_t idx = 0; idx < LOG_N; ++idx) { - u_challenge[idx] = NativeFr::random_element(&engine); - }; - - // Construct some random multilinear polynomials f_i and their evaluations v_i = f_i(u) - std::vector f_polynomials; // unshifted polynomials - std::vector v_evaluations; - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_polynomials.emplace_back(Polynomial::random(N, /* starting index for shift */ 1)); - v_evaluations.emplace_back(f_polynomials[i].evaluate_mle(u_challenge)); - } - // Construct some "shifted" multilinear polynomials h_i as the left-shift-by-1 of f_i - std::vector g_polynomials; // to-be-shifted polynomials - std::vector h_polynomials; // shifts of the to-be-shifted polynomials - std::vector w_evaluations; - if constexpr (NUM_SHIFTED > 0) { - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_polynomials.emplace_back(f_polynomials[i]); - h_polynomials.emplace_back(g_polynomials[i].shifted()); - w_evaluations.emplace_back(h_polynomials[i].evaluate_mle(u_challenge)); - } - } - - // Compute commitments [f_i] - std::vector f_commitments; - auto commitment_key = std::make_shared(1024); - for (size_t i = 0; i < NUM_UNSHIFTED; ++i) { - f_commitments.emplace_back(commitment_key->commit(f_polynomials[i])); - } - - // Construct container of commitments of the "to-be-shifted" polynomials [g_i] (= [f_i]) - std::vector g_commitments; - for (size_t i = 0; i < NUM_SHIFTED; ++i) { - g_commitments.emplace_back(f_commitments[i]); - } - - // Initialize an empty NativeTranscript - auto prover_transcript = NativeTranscript::prover_init_empty(); - - // Execute Prover protocol - ZeroMorphProver::prove(N, - RefVector(f_polynomials), - RefVector(g_polynomials), - RefVector(v_evaluations), - RefVector(w_evaluations), - u_challenge, - commitment_key, - prover_transcript); - - Builder builder; - StdlibProof stdlib_proof = bb::convert_native_proof_to_stdlib(&builder, prover_transcript->proof_data); - auto stdlib_verifier_transcript = std::make_shared(stdlib_proof); - [[maybe_unused]] auto _ = stdlib_verifier_transcript->template receive_from_prover("Init"); - - // Execute Verifier protocol without the need for vk prior the final check - const auto commitments_to_witnesses = [&builder](const auto& commitments) { - std::vector commitments_in_biggroup(commitments.size()); - std::transform(commitments.begin(), - commitments.end(), - commitments_in_biggroup.begin(), - [&builder](const auto& native_commitment) { - return Commitment::from_witness(&builder, native_commitment); - }); - return commitments_in_biggroup; - }; - const auto elements_to_witness = [&](const auto& elements) { - std::vector elements_in_circuit(elements.size()); - std::transform(elements.begin(), - elements.end(), - elements_in_circuit.begin(), - [&builder](const auto& native_element) { return Fr::from_witness(&builder, native_element); }); - return elements_in_circuit; - }; - auto stdlib_f_commitments = commitments_to_witnesses(f_commitments); - auto stdlib_g_commitments = commitments_to_witnesses(g_commitments); - auto stdlib_v_evaluations = elements_to_witness(v_evaluations); - auto stdlib_w_evaluations = elements_to_witness(w_evaluations); - - std::vector u_challenge_in_circuit(CONST_PROOF_SIZE_LOG_N); - std::fill_n(u_challenge_in_circuit.begin(), CONST_PROOF_SIZE_LOG_N, Fr::from_witness(&builder, 0)); - u_challenge_in_circuit[0] = Fr::from_witness(&builder, u_challenge[0]); - - [[maybe_unused]] auto opening_claim = ZeroMorphVerifier::verify(Fr::from_witness(&builder, N), - RefVector(stdlib_f_commitments), // unshifted - RefVector(stdlib_g_commitments), // to-be-shifted - RefVector(stdlib_v_evaluations), // unshifted - RefVector(stdlib_w_evaluations), // shifted - u_challenge_in_circuit, - Commitment::one(&builder), - stdlib_verifier_transcript); - EXPECT_TRUE(CircuitChecker::check(builder)); -}