diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp index 3828a009b6b2..ccfbbb422801 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/gemini/gemini_impl.hpp @@ -53,8 +53,8 @@ std::vector::Claim> GeminiProver_::prove( bool has_zk) { - size_t log_n = numeric::get_msb(static_cast(circuit_size)); - size_t n = 1 << log_n; + const size_t log_n = numeric::get_msb(static_cast(circuit_size)); + const size_t n = 1 << log_n; // Compute batched polynomials Polynomial batched_unshifted(n); @@ -66,10 +66,8 @@ std::vector::Claim> GeminiProver_::prove( transcript->send_to_verifier("Gemini:masking_poly_comm", commitment_key->commit(batched_unshifted)); // In the provers, the size of multilinear_challenge is CONST_PROOF_SIZE_LOG_N, but we need to evaluate the // hiding polynomial as multilinear in log_n variables - std::vector multilinear_challenge_resized(multilinear_challenge.begin(), multilinear_challenge.end()); - multilinear_challenge_resized.resize(log_n); transcript->send_to_verifier("Gemini:masking_poly_eval", - batched_unshifted.evaluate_mle(multilinear_challenge_resized)); + batched_unshifted.evaluate_mle(multilinear_challenge.subspan(0, log_n))); } // Get the batching challenge diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp index 330759436618..714be37b7537 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/shplonk/shplemini.hpp @@ -169,7 +169,7 @@ template class ShpleminiVerifier_ { if (has_zk) { hiding_polynomial_commitment = transcript->template receive_from_prover("Gemini:masking_poly_comm"); - batched_evaluation += transcript->template receive_from_prover("Gemini:masking_poly_eval"); + batched_evaluation = transcript->template receive_from_prover("Gemini:masking_poly_eval"); } // Get the challenge ρ to batch commitments to multilinear polynomials and their shifts @@ -399,7 +399,7 @@ template class ShpleminiVerifier_ { Fr current_batching_challenge = Fr(1); if (has_zk) { - // ρ⁰ is used to batch the hiding polynomial + // ρ⁰ is used to batch the hiding polynomial which has already been added to the commitments vector current_batching_challenge *= multivariate_batching_challenge; } @@ -635,12 +635,12 @@ template class ShpleminiVerifier_ { // need to keep track of the contribution to the constant term Fr& constant_term = scalars.back(); - // add Libra commitments to the vector of commitments; compute corresponding scalars and the correction to - // the constant term + // add Libra commitments to the vector of commitments for (size_t idx = 0; idx < libra_commitments.size(); idx++) { commitments.push_back(libra_commitments[idx]); } + // compute corresponding scalars and the correction to the constant term std::array denominators; std::array batching_scalars; // compute Shplonk denominators and invert them diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp index 45b72b21ba6a..9929608048d0 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/honk_contract.hpp @@ -663,17 +663,39 @@ function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point mem return point; } + function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G1 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G1 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + bool decodedResult = abi.decode(result, (bool)); + return success && decodedResult; + } + library RelationsLib { Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) function accumulateRelationEvaluations( - Honk.Proof memory proof, + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, Honk.RelationParameters memory rp, Fr[NUMBER_OF_ALPHAS] memory alphas, Fr powPartialEval ) internal pure returns (Fr accumulator) { - Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations = proof.sumcheckEvaluations; Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; // Accumulate all relations in Ultra Honk - each with varying number of subrelations @@ -1351,6 +1373,72 @@ library RelationsLib { } } +struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; +} + +library CommitmentSchemeLib { + using FrLib for Fr; + + function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { + squares[0] = r; + for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + squares[i] = squares[i - 1].sqr(); + } + } + + function computeInvertedGeminiDenominators( + Fr shplonkZ, + Fr[CONST_PROOF_SIZE_LOG_N] memory eval_challenge_powers, + uint256 logSize + ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N + 1] memory inverse_vanishing_evals) { + Fr eval_challenge = shplonkZ; + inverse_vanishing_evals[0] = (eval_challenge - eval_challenge_powers[0]).invert(); + + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { + Fr round_inverted_denominator = Fr.wrap(0); + if (i <= logSize + 1) { + round_inverted_denominator = (eval_challenge + eval_challenge_powers[i]).invert(); + } + inverse_vanishing_evals[i + 1] = round_inverted_denominator; + } + } + + function computeGeminiBatchedUnivariateEvaluation( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr a_0_pos) { + for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + Fr evalNeg = geminiEvaluations[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - evalNeg * (challengePower * (Fr.wrap(1) - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (Fr.wrap(1) - u) + u).invert(); + + bool is_dummy_round = (i > logSize); + if (!is_dummy_round) { + batchedEvalAccumulator = batchedEvalRoundAcc; + } + } + + a_0_pos = batchedEvalAccumulator; + } +} interface IVerifier { function verify(bytes calldata _proof, bytes32[] calldata _publicInputs) external view returns (bool); @@ -1429,8 +1517,6 @@ abstract contract BaseHonkVerifier is IVerifier { publicInputDelta = FrLib.div(numerator, denominator); } - uint256 constant ROUND_TARGET = 0; - function verifySumcheck(Honk.Proof memory proof, Transcript memory tp) internal view returns (bool verified) { Fr roundTarget; Fr powPartialEvaluation = Fr.wrap(1); @@ -1445,12 +1531,12 @@ abstract contract BaseHonkVerifier is IVerifier { // Update the round target for the next rounf roundTarget = computeNextTargetSum(roundUnivariate, roundChallenge); - powPartialEvaluation = partiallyEvaluatePOW(tp, powPartialEvaluation, roundChallenge, round); + powPartialEvaluation = partiallyEvaluatePOW(tp.gateChallenges[round], powPartialEvaluation, roundChallenge); } // Last round Fr grandHonkRelationSum = - RelationsLib.accumulateRelationEvaluations(proof, tp.relationParameters, tp.alphas, powPartialEvaluation); + RelationsLib.accumulateRelationEvaluations(proof.sumcheckEvaluations, tp.relationParameters, tp.alphas, powPartialEvaluation); verified = (grandHonkRelationSum == roundTarget); } @@ -1520,29 +1606,15 @@ abstract contract BaseHonkVerifier is IVerifier { } // Univariate evaluation of the monomial ((1-X_l) + X_l.B_l) at the challenge point X_l=u_l - function partiallyEvaluatePOW(Transcript memory tp, Fr currentEvaluation, Fr roundChallenge, uint256 round) + function partiallyEvaluatePOW(Fr gateChallenge, Fr currentEvaluation, Fr roundChallenge) internal pure returns (Fr newEvaluation) { - Fr univariateEval = Fr.wrap(1) + (roundChallenge * (tp.gateChallenges[round] - Fr.wrap(1))); + Fr univariateEval = Fr.wrap(1) + (roundChallenge * (gateChallenge - Fr.wrap(1))); newEvaluation = currentEvaluation * univariateEval; } - // Avoid stack too deep - struct ShpleminiIntermediates { - // i-th unshifted commitment is multiplied by −ρⁱ and the unshifted_scalar ( 1/(z−r) + ν/(z+r) ) - Fr unshiftedScalar; - // i-th shifted commitment is multiplied by −ρⁱ⁺ᵏ and the shifted_scalar r⁻¹ ⋅ (1/(z−r) − ν/(z+r)) - Fr shiftedScalar; - // Scalar to be multiplied by [1]₁ - Fr constantTermAccumulator; - // Accumulator for powers of rho - Fr batchingChallenge; - // Linear combination of multilinear (sumcheck) evaluations and powers of rho - Fr batchedEvaluation; - } - function verifyShplemini(Honk.Proof memory proof, Honk.VerificationKey memory vk, Transcript memory tp) internal view @@ -1551,14 +1623,14 @@ abstract contract BaseHonkVerifier is IVerifier { ShpleminiIntermediates memory mem; // stack // - Compute vector (r, r², ... , r²⁽ⁿ⁻¹⁾), where n = log_circuit_size - Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = computeSquares(tp.geminiR); + Fr[CONST_PROOF_SIZE_LOG_N] memory powers_of_evaluation_challenge = CommitmentSchemeLib.computeSquares(tp.geminiR); // Arrays hold values that will be linearly combined for the gemini and shplonk batch openings Fr[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory scalars; Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory commitments; Fr[CONST_PROOF_SIZE_LOG_N + 1] memory inverse_vanishing_evals = - computeInvertedGeminiDenominators(tp, powers_of_evaluation_challenge); + CommitmentSchemeLib.computeInvertedGeminiDenominators(tp.shplonkZ, powers_of_evaluation_challenge, logN); mem.unshiftedScalar = inverse_vanishing_evals[0] + (tp.shplonkNu * inverse_vanishing_evals[1]); mem.shiftedScalar = @@ -1567,33 +1639,6 @@ abstract contract BaseHonkVerifier is IVerifier { scalars[0] = Fr.wrap(1); commitments[0] = convertProofPoint(proof.shplonkQ); - /* Batch multivariate opening claims, shifted and unshifted - * The vector of scalars is populated as follows: - * \f[ - * \left( - * - \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), - * \ldots, - * - \rho^{i+k-1} \times \left(\frac{1}{z-r} + \nu \times \frac{1}{z+r}\right), - * - \rho^{i+k} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right), - * \ldots, - * - \rho^{k+m-1} \times \frac{1}{r} \times \left(\frac{1}{z-r} - \nu \times \frac{1}{z+r}\right) - * \right) - * \f] - * - * The following vector is concatenated to the vector of commitments: - * \f[ - * f_0, \ldots, f_{m-1}, f_{\text{shift}, 0}, \ldots, f_{\text{shift}, k-1} - * \f] - * - * Simultaneously, the evaluation of the multilinear polynomial - * \f[ - * \sum \rho^i \cdot f_i + \sum \rho^{i+k} \cdot f_{\text{shift}, i} - * \f] - * at the challenge point \f$ (u_0,\ldots, u_{n-1}) \f$ is computed. - * - * This approach minimizes the number of iterations over the commitments to multilinear polynomials - * and eliminates the need to store the powers of \f$ \rho \f$. - */ mem.batchingChallenge = Fr.wrap(1); mem.batchedEvaluation = Fr.wrap(0); @@ -1654,28 +1699,6 @@ abstract contract BaseHonkVerifier is IVerifier { commitments[39] = convertProofPoint(proof.w4); commitments[40] = convertProofPoint(proof.zPerm); - /* Batch gemini claims from the prover - * place the commitments to gemini aᵢ to the vector of commitments, compute the contributions from - * aᵢ(−r²ⁱ) for i=1, … , n−1 to the constant term accumulator, add corresponding scalars - * - * 1. Moves the vector - * \f[ - * \left( \text{com}(A_1), \text{com}(A_2), \ldots, \text{com}(A_{n-1}) \right) - * \f] - * to the 'commitments' vector. - * - * 2. Computes the scalars: - * \f[ - * \frac{\nu^{2}}{z + r^2}, \frac{\nu^3}{z + r^4}, \ldots, \frac{\nu^{n-1}}{z + r^{2^{n-1}}} - * \f] - * and places them into the 'scalars' vector. - * - * 3. Accumulates the summands of the constant term: - * \f[ - * \sum_{i=2}^{n-1} \frac{\nu^{i} \cdot A_i(-r^{2^i})}{z + r^{2^i}} - * \f] - * and adds them to the 'constant_term_accumulator'. - */ mem.constantTermAccumulator = Fr.wrap(0); mem.batchingChallenge = tp.shplonkNu.sqr(); @@ -1697,8 +1720,12 @@ abstract contract BaseHonkVerifier is IVerifier { // Add contributions from A₀(r) and A₀(-r) to constant_term_accumulator: // Compute evaluation A₀(r) - Fr a_0_pos = computeGeminiBatchedUnivariateEvaluation( - tp, mem.batchedEvaluation, proof.geminiAEvaluations, powers_of_evaluation_challenge + Fr a_0_pos = CommitmentSchemeLib.computeGeminiBatchedUnivariateEvaluation( + tp.sumCheckUChallenges, + mem.batchedEvaluation, + proof.geminiAEvaluations, + powers_of_evaluation_challenge, + logN ); mem.constantTermAccumulator = mem.constantTermAccumulator + (a_0_pos * inverse_vanishing_evals[0]); @@ -1720,56 +1747,6 @@ abstract contract BaseHonkVerifier is IVerifier { return pairing(P_0, P_1); } - function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { - squares[0] = r; - for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { - squares[i] = squares[i - 1].sqr(); - } - } - - function computeInvertedGeminiDenominators( - Transcript memory tp, - Fr[CONST_PROOF_SIZE_LOG_N] memory eval_challenge_powers - ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N + 1] memory inverse_vanishing_evals) { - Fr eval_challenge = tp.shplonkZ; - inverse_vanishing_evals[0] = (eval_challenge - eval_challenge_powers[0]).invert(); - - for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { - Fr round_inverted_denominator = Fr.wrap(0); - if (i <= logN + 1) { - round_inverted_denominator = (eval_challenge + eval_challenge_powers[i]).invert(); - } - inverse_vanishing_evals[i + 1] = round_inverted_denominator; - } - } - - function computeGeminiBatchedUnivariateEvaluation( - Transcript memory tp, - Fr batchedEvalAccumulator, - Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, - Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers - ) internal view returns (Fr a_0_pos) { - for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { - Fr challengePower = geminiEvalChallengePowers[i - 1]; - Fr u = tp.sumCheckUChallenges[i - 1]; - Fr evalNeg = geminiEvaluations[i - 1]; - - Fr batchedEvalRoundAcc = ( - (challengePower * batchedEvalAccumulator * Fr.wrap(2)) - - evalNeg * (challengePower * (Fr.wrap(1) - u) - u) - ); - // Divide by the denominator - batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (Fr.wrap(1) - u) + u).invert(); - - bool is_dummy_round = (i > logN); - if (!is_dummy_round) { - batchedEvalAccumulator = batchedEvalRoundAcc; - } - } - - a_0_pos = batchedEvalAccumulator; - } - // This implementation is the same as above with different constants function batchMul( Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory base, @@ -1810,29 +1787,6 @@ abstract contract BaseHonkVerifier is IVerifier { mstore(add(result, 0x20), mload(add(free, 0x20))) } } - - function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) internal view returns (bool) { - bytes memory input = abi.encodePacked( - rhs.x, - rhs.y, - // Fixed G1 point - uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), - uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), - uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), - uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), - lhs.x, - lhs.y, - // G1 point from VK - uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), - uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), - uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), - uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) - ); - - (bool success, bytes memory result) = address(0x08).staticcall(input); - bool decodedResult = abi.decode(result, (bool)); - return success && decodedResult; - } } contract HonkVerifier is BaseHonkVerifier(N, LOG_N, NUMBER_OF_PUBLIC_INPUTS) { diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 8166d607aca2..2ba914004466 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -153,8 +153,8 @@ class ECCVMTranscriptTests : public ::testing::Test { round++; - manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); manifest_expected.add_entry(round, "Sumcheck:evaluations", frs_per_evals); + manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); manifest_expected.add_entry(round, "Libra:big_sum_commitment", frs_per_G); manifest_expected.add_entry(round, "Libra:quotient_commitment", frs_per_G); manifest_expected.add_entry(round, "Gemini:masking_poly_comm", frs_per_G); diff --git a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp index 35092b67aebd..0dc5e962210e 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/flavor.hpp @@ -440,8 +440,6 @@ template concept IsFoldingFlavor = IsAnyOf, MegaZKRecursiveFlavor_, MegaZKRecursiveFlavor_>; -template -concept FlavorHasZK = T::HasZK; template inline std::string flavor_get_label(Container&& container, const Element& element) { diff --git a/barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt index 7b91d9c40c41..6c2cc6b15324 100644 --- a/barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/solidity_helpers/CMakeLists.txt @@ -5,14 +5,14 @@ if (NOT(FUZZING)) add_executable(honk_solidity_key_gen honk_key_gen.cpp) target_link_libraries( - honk_solidity_key_gen + honk_solidity_key_gen stdlib_solidity_helpers ) add_executable(honk_solidity_proof_gen honk_proof_gen.cpp) target_link_libraries( - honk_solidity_proof_gen + honk_solidity_proof_gen stdlib_solidity_helpers ) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp index 3be2eb346a55..dc2194d2405c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/decider_recursive_verifier.cpp @@ -27,16 +27,16 @@ std::array DeciderRecursiveVerifier_:: auto sumcheck = Sumcheck( static_cast(accumulator->verification_key->log_circuit_size), transcript, accumulator->target_sum); - auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = + SumcheckOutput output = sumcheck.verify(accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges); // Execute Shplemini rounds. const auto opening_claim = Shplemini::compute_batch_opening_claim(accumulator->verification_key->circuit_size, commitments.get_unshifted(), commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, + output.claimed_evaluations.get_unshifted(), + output.claimed_evaluations.get_shifted(), + output.challenge, Commitment::one(builder), transcript, Flavor::REPEATED_COMMITMENTS, diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp index 058a12342909..466da5eca3aa 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_verifier/ultra_recursive_verifier.cpp @@ -107,7 +107,6 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ // Receive commitments to Libra masking polynomials std::array libra_commitments = {}; - FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { libra_commitments[0] = transcript->template receive_from_prover("Libra:concatenation_commitment"); } @@ -116,7 +115,6 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ // For MegaZKFlavor: the sumcheck output contains claimed evaluations of the Libra polynomials if constexpr (Flavor::HasZK) { - libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); } @@ -135,7 +133,7 @@ UltraRecursiveVerifier_::Output UltraRecursiveVerifier_::verify_ Flavor::HasZK, &consistency_checked, libra_commitments, - libra_evaluation); + sumcheck_output.claimed_libra_evaluation); auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp index afd1cb3a6630..e702da6fda82 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck.hpp @@ -269,7 +269,7 @@ template class SumcheckProver { const RelationSeparator alpha, const std::vector& gate_challenges, ZKData& zk_sumcheck_data) - requires FlavorHasZK + requires Flavor::HasZK { bb::GateSeparatorPolynomial gate_separators(gate_challenges, multivariate_d); @@ -341,22 +341,22 @@ template class SumcheckProver { FF round_challenge = transcript->template get_challenge("Sumcheck:u_" + std::to_string(idx)); multivariate_challenge.emplace_back(round_challenge); } + + // Claimed evaluations of Prover polynomials are extracted and added to the transcript. When Flavor has ZK, the + // evaluations of all witnesses are masked. + ClaimedEvaluations multivariate_evaluations; + multivariate_evaluations = extract_claimed_evaluations(partially_evaluated_polynomials); + transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all()); + // The evaluations of Libra uninvariates at \f$ g_0(u_0), \ldots, g_{d-1} (u_{d-1}) \f$ are added to the // transcript. FF libra_evaluation{ 0 }; - - for (auto& libra_eval : zk_sumcheck_data.libra_evaluations) { + for (const auto& libra_eval : zk_sumcheck_data.libra_evaluations) { libra_evaluation += libra_eval; } libra_evaluation += zk_sumcheck_data.constant_term; - std::string libra_evaluation_label = "Libra:claimed_evaluation"; - transcript->send_to_verifier(libra_evaluation_label, libra_evaluation); + transcript->send_to_verifier("Libra:claimed_evaluation", libra_evaluation); - // Claimed evaluations of Prover polynomials are extracted and added to the transcript. When Flavor has ZK, the - // evaluations of all witnesses are masked. - ClaimedEvaluations multivariate_evaluations; - multivariate_evaluations = extract_claimed_evaluations(partially_evaluated_polynomials); - transcript->send_to_verifier("Sumcheck:evaluations", multivariate_evaluations.get_all()); // The sum of the Libra constant term and the evaluations of Libra univariates at corresponding sumcheck // challenges is included in the Sumcheck Output return SumcheckOutput{ multivariate_challenge, multivariate_evaluations, libra_evaluation }; @@ -606,20 +606,16 @@ template class SumcheckVerifier { } FF libra_challenge; - FF libra_total_sum; if constexpr (Flavor::HasZK) { - // get the claimed sum of libra masking multivariate over the hypercube - libra_total_sum = transcript->template receive_from_prover("Libra:Sum"); - // get the challenge for the ZK Sumcheck claim + // If running zero-knowledge sumcheck the target total sum is corrected by the claimed sum of libra masking + // multivariate over the hypercube + FF libra_total_sum = transcript->template receive_from_prover("Libra:Sum"); libra_challenge = transcript->template get_challenge("Libra:Challenge"); + round.target_total_sum += libra_total_sum * libra_challenge; } + std::vector multivariate_challenge; multivariate_challenge.reserve(multivariate_d); - // if Flavor has ZK, the target total sum is corrected by Libra total sum multiplied by the Libra - // challenge - if constexpr (Flavor::HasZK) { - round.target_total_sum += libra_total_sum * libra_challenge; - }; for (size_t round_idx = 0; round_idx < CONST_PROOF_SIZE_LOG_N; round_idx++) { // Obtain the round univariate from the transcript std::string round_univariate_label = "Sumcheck:univariate_" + std::to_string(round_idx); @@ -655,13 +651,6 @@ template class SumcheckVerifier { } } // Extract claimed evaluations of Libra univariates and compute their sum multiplied by the Libra challenge - FF libra_evaluation{ 0 }; - FF full_libra_purported_value = FF(0); - if constexpr (Flavor::HasZK) { - libra_evaluation = transcript->template receive_from_prover("Libra:claimed_evaluation"); - full_libra_purported_value += libra_evaluation; - full_libra_purported_value *= libra_challenge; - }; // Final round ClaimedEvaluations purported_evaluations; auto transcript_evaluations = @@ -669,35 +658,39 @@ template class SumcheckVerifier { for (auto [eval, transcript_eval] : zip_view(purported_evaluations.get_all(), transcript_evaluations)) { eval = transcript_eval; } + + // Evaluate the Honk relation at the point (u_0, ..., u_{d-1}) using claimed evaluations of prover polynomials. + // In ZK Flavors, the evaluation is corrected by full_libra_purported_value + FF full_honk_purported_value = round.compute_full_relation_purported_value( + purported_evaluations, relation_parameters, gate_separators, alpha); + // For ZK Flavors: the evaluation of the Row Disabling Polynomial at the sumcheck challenge - FF correcting_factor{ 1 }; + FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { - RowDisablingPolynomial row_disabler = RowDisablingPolynomial(); - correcting_factor = row_disabler.evaluate_at_challenge(multivariate_challenge, multivariate_d); + libra_evaluation = transcript->template receive_from_prover("Libra:claimed_evaluation"); + FF correcting_factor = + RowDisablingPolynomial::evaluate_at_challenge(multivariate_challenge, multivariate_d); + full_honk_purported_value = + full_honk_purported_value * correcting_factor + libra_evaluation * libra_challenge; + if constexpr (IsECCVMRecursiveFlavor) { + // TODO(https://github.com/AztecProtocol/barretenberg/issues/1197) + full_honk_purported_value.self_reduce(); + } } - // Evaluate the Honk relation at the point (u_0, ..., u_{d-1}) using claimed evaluations of prover polynomials. - // In ZK Flavors, the evaluation is corrected by full_libra_purported_value - FF full_honk_purported_value = round.compute_full_relation_purported_value(purported_evaluations, - relation_parameters, - gate_separators, - alpha, - full_libra_purported_value, - correcting_factor); - bool final_check(false); //! [Final Verification Step] if constexpr (IsRecursiveFlavor) { - final_check = (full_honk_purported_value.get_value() == round.target_total_sum.get_value()); + verified = verified && (full_honk_purported_value.get_value() == round.target_total_sum.get_value()); } else { - final_check = (full_honk_purported_value == round.target_total_sum); - } - verified = final_check && verified; - // For ZK Flavors: the evaluations of Libra univariates are included in the Sumcheck Output - if constexpr (!Flavor::HasZK) { - return SumcheckOutput{ multivariate_challenge, purported_evaluations, verified }; - } else { - return SumcheckOutput{ multivariate_challenge, purported_evaluations, libra_evaluation, verified }; + verified = verified && (full_honk_purported_value == round.target_total_sum); } + + return SumcheckOutput{ + multivariate_challenge, + purported_evaluations, + libra_evaluation, + verified, + }; }; }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp index ea0c014a6153..a2534bd68d07 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_output.hpp @@ -10,35 +10,20 @@ namespace bb { * @brief Contains the evaluations of multilinear polynomials \f$ P_1, \ldots, P_N\f$ at the challenge point \f$\vec u * =(u_0,\ldots, u_{d-1})\f$. These are computed by \ref bb::SumcheckProver< Flavor > "Sumcheck Prover" and need to be * checked using Shplemini. - */ -template struct SumcheckOutput { - using FF = typename Flavor::FF; - using ClaimedEvaluations = typename Flavor::AllValues; - // \f$ \vec u = (u_0, ..., u_{d-1}) \f$ - std::vector challenge; - // Evaluations at \f$ \vec u \f$ of the polynomials used in Sumcheck - ClaimedEvaluations claimed_evaluations; - // Whether or not the evaluations of multilinear polynomials \f$ P_1, \ldots, P_N \f$ and final Sumcheck evaluation - // have been confirmed - std::optional verified = false; // optional b/c this struct is shared by the Prover/Verifier -}; -/** - * @brief A modification of SumcheckOutput required by ZK Flavors where a vector of evaluations of Libra univariates is - * included. - * * @tparam Flavor */ -template struct SumcheckOutput>> { +template struct SumcheckOutput { using FF = typename Flavor::FF; using ClaimedEvaluations = typename Flavor::AllValues; // \f$ \vec u = (u_0, ..., u_{d-1}) \f$ std::vector challenge; // Evaluations at \f$ \vec u \f$ of the polynomials used in Sumcheck ClaimedEvaluations claimed_evaluations; - // For ZK Flavors: the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges - FF claimed_libra_evaluation; + // For ZK Flavors: the sum of the Libra constant term and Libra univariates evaluated at Sumcheck challenges, + // otherwise remains the default value 0 + FF claimed_libra_evaluation = 0; + std::optional verified = false; // Optional b/c this struct is shared by the Prover/Verifier // Whether or not the evaluations of multilinear polynomials \f$ P_1, \ldots, P_N \f$ and final Sumcheck evaluation // have been confirmed - std::optional verified = false; // Optional b/c this struct is shared by the Prover/Verifier }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp index 092ba3ca9415..f1c81c62e3f6 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/sumcheck_round.hpp @@ -598,9 +598,7 @@ template class SumcheckVerifierRound { FF compute_full_relation_purported_value(ClaimedEvaluations purported_evaluations, const bb::RelationParameters& relation_parameters, const bb::GateSeparatorPolynomial& gate_sparators, - const RelationSeparator alpha, - const FF full_libra_purported_value = FF{ 0 }, - FF correcting_factor = FF{ 1 }) + const RelationSeparator alpha) { // The verifier should never skip computation of contributions from any relation Utils::template accumulate_relation_evaluations_without_skipping<>( @@ -609,12 +607,6 @@ template class SumcheckVerifierRound { FF running_challenge{ 1 }; FF output{ 0 }; Utils::scale_and_batch_elements(relation_evaluations, alpha, running_challenge, output); - if constexpr (Flavor::HasZK) { - output = output * correcting_factor + full_libra_purported_value; - if constexpr (IsECCVMRecursiveFlavor) { - output.self_reduce(); - } - }; return output; } }; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp index 87891d71e9d7..21065dd96e83 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/decider_verifier.cpp @@ -54,9 +54,7 @@ template bool DeciderVerifier_::verify() sumcheck.verify(accumulator->relation_parameters, accumulator->alphas, accumulator->gate_challenges); // For MegaZKFlavor: the sumcheck output contains claimed evaluations of the Libra polynomials - FF libra_evaluation{ 0 }; if constexpr (Flavor::HasZK) { - libra_evaluation = std::move(sumcheck_output.claimed_libra_evaluation); libra_commitments[1] = transcript->template receive_from_prover("Libra:big_sum_commitment"); libra_commitments[2] = transcript->template receive_from_prover("Libra:quotient_commitment"); } @@ -80,7 +78,7 @@ template bool DeciderVerifier_::verify() Flavor::HasZK, &consistency_checked, libra_commitments, - libra_evaluation); + sumcheck_output.claimed_libra_evaluation); const auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); bool verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); return sumcheck_output.verified.value() && verified && consistency_checked; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp index e47333d43687..17c558b1c85c 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_transcript.test.cpp @@ -110,13 +110,10 @@ template class MegaTranscriptTests : public ::testing::Test { round++; } - if constexpr (Flavor::HasZK) { - manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); - } - manifest_expected.add_entry(round, "Sumcheck:evaluations", frs_per_evals); if constexpr (Flavor::HasZK) { + manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); manifest_expected.add_entry(round, "Libra:big_sum_commitment", frs_per_G); manifest_expected.add_entry(round, "Libra:quotient_commitment", frs_per_G); manifest_expected.add_entry(round, "Gemini:masking_poly_comm", frs_per_G); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp index f313ea074b7e..2f61e40aa92b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp @@ -109,13 +109,10 @@ template class UltraTranscriptTests : public ::testing::Test { round++; } - if constexpr (Flavor::HasZK) { - manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); - } - manifest_expected.add_entry(round, "Sumcheck:evaluations", frs_per_evals); if constexpr (Flavor::HasZK) { + manifest_expected.add_entry(round, "Libra:claimed_evaluation", frs_per_Fr); manifest_expected.add_entry(round, "Libra:big_sum_commitment", frs_per_G); manifest_expected.add_entry(round, "Libra:quotient_commitment", frs_per_G); manifest_expected.add_entry(round, "Gemini:masking_poly_comm", frs_per_G); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/recursive_verifier.cpp index 4c88da4c3ebe..d1766b839b13 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/recursive_verifier.cpp @@ -118,44 +118,44 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: // No need to constrain that sumcheck_verified is true as this is guaranteed by the implementation of // when called over a "circuit field" types. - auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = - sumcheck.verify(relation_parameters, alpha, gate_challenges); + SumcheckOutput output = sumcheck.verify(relation_parameters, alpha, gate_challenges); - vinfo("verified sumcheck: ", (sumcheck_verified.has_value() && sumcheck_verified.value())); + vinfo("verified sumcheck: ", (output.verified.has_value() && output.verified.value())); // Public columns evaluation checks - std::vector mle_challenge(multivariate_challenge.begin(), - multivariate_challenge.begin() + static_cast(log_circuit_size)); + std::vector mle_challenge(output.challenge.begin(), + output.challenge.begin() + static_cast(log_circuit_size)); FF main_kernel_inputs_evaluation = evaluate_public_input_column(public_inputs[0], mle_challenge); - main_kernel_inputs_evaluation.assert_equal(claimed_evaluations.main_kernel_inputs, + main_kernel_inputs_evaluation.assert_equal(output.claimed_evaluations.main_kernel_inputs, "main_kernel_inputs_evaluation failed"); FF main_kernel_value_out_evaluation = evaluate_public_input_column(public_inputs[1], mle_challenge); - main_kernel_value_out_evaluation.assert_equal(claimed_evaluations.main_kernel_value_out, + main_kernel_value_out_evaluation.assert_equal(output.claimed_evaluations.main_kernel_value_out, "main_kernel_value_out_evaluation failed"); FF main_kernel_side_effect_out_evaluation = evaluate_public_input_column(public_inputs[2], mle_challenge); - main_kernel_side_effect_out_evaluation.assert_equal(claimed_evaluations.main_kernel_side_effect_out, + main_kernel_side_effect_out_evaluation.assert_equal(output.claimed_evaluations.main_kernel_side_effect_out, "main_kernel_side_effect_out_evaluation failed"); FF main_kernel_metadata_out_evaluation = evaluate_public_input_column(public_inputs[3], mle_challenge); - main_kernel_metadata_out_evaluation.assert_equal(claimed_evaluations.main_kernel_metadata_out, + main_kernel_metadata_out_evaluation.assert_equal(output.claimed_evaluations.main_kernel_metadata_out, "main_kernel_metadata_out_evaluation failed"); FF main_calldata_evaluation = evaluate_public_input_column(public_inputs[4], mle_challenge); - main_calldata_evaluation.assert_equal(claimed_evaluations.main_calldata, "main_calldata_evaluation failed"); + main_calldata_evaluation.assert_equal(output.claimed_evaluations.main_calldata, "main_calldata_evaluation failed"); FF main_returndata_evaluation = evaluate_public_input_column(public_inputs[5], mle_challenge); - main_returndata_evaluation.assert_equal(claimed_evaluations.main_returndata, "main_returndata_evaluation failed"); + main_returndata_evaluation.assert_equal(output.claimed_evaluations.main_returndata, + "main_returndata_evaluation failed"); // Execute Shplemini rounds. auto opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted(), commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, + output.claimed_evaluations.get_unshifted(), + output.claimed_evaluations.get_shifted(), + output.challenge, Commitment::one(builder), transcript); auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); diff --git a/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp b/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp index 0f025c6ed8b4..a9d581a53e01 100644 --- a/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/vm/avm/generated/verifier.cpp @@ -85,46 +85,45 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = - sumcheck.verify(relation_parameters, alpha, gate_challenges); + SumcheckOutput output = sumcheck.verify(relation_parameters, alpha, gate_challenges); // If Sumcheck did not verify, return false - if (!sumcheck_verified.has_value() || !sumcheck_verified.value()) { + if (!output.verified.has_value() || !output.verified.value()) { vinfo("Sumcheck verification failed"); return false; } // Public columns evaluation checks - std::vector mle_challenge(multivariate_challenge.begin(), - multivariate_challenge.begin() + static_cast(log_circuit_size)); + std::vector mle_challenge(output.challenge.begin(), + output.challenge.begin() + static_cast(log_circuit_size)); FF main_kernel_inputs_evaluation = evaluate_public_input_column(public_inputs[0], mle_challenge); - if (main_kernel_inputs_evaluation != claimed_evaluations.main_kernel_inputs) { + if (main_kernel_inputs_evaluation != output.claimed_evaluations.main_kernel_inputs) { vinfo("main_kernel_inputs_evaluation failed"); return false; } FF main_kernel_value_out_evaluation = evaluate_public_input_column(public_inputs[1], mle_challenge); - if (main_kernel_value_out_evaluation != claimed_evaluations.main_kernel_value_out) { + if (main_kernel_value_out_evaluation != output.claimed_evaluations.main_kernel_value_out) { vinfo("main_kernel_value_out_evaluation failed"); return false; } FF main_kernel_side_effect_out_evaluation = evaluate_public_input_column(public_inputs[2], mle_challenge); - if (main_kernel_side_effect_out_evaluation != claimed_evaluations.main_kernel_side_effect_out) { + if (main_kernel_side_effect_out_evaluation != output.claimed_evaluations.main_kernel_side_effect_out) { vinfo("main_kernel_side_effect_out_evaluation failed"); return false; } FF main_kernel_metadata_out_evaluation = evaluate_public_input_column(public_inputs[3], mle_challenge); - if (main_kernel_metadata_out_evaluation != claimed_evaluations.main_kernel_metadata_out) { + if (main_kernel_metadata_out_evaluation != output.claimed_evaluations.main_kernel_metadata_out) { vinfo("main_kernel_metadata_out_evaluation failed"); return false; } FF main_calldata_evaluation = evaluate_public_input_column(public_inputs[4], mle_challenge); - if (main_calldata_evaluation != claimed_evaluations.main_calldata) { + if (main_calldata_evaluation != output.claimed_evaluations.main_calldata) { vinfo("main_calldata_evaluation failed"); return false; } FF main_returndata_evaluation = evaluate_public_input_column(public_inputs[5], mle_challenge); - if (main_returndata_evaluation != claimed_evaluations.main_returndata) { + if (main_returndata_evaluation != output.claimed_evaluations.main_returndata) { vinfo("main_returndata_evaluation failed"); return false; } @@ -133,9 +132,9 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = - sumcheck.verify(relation_parameters, alpha, gate_challenges); + SumcheckOutput output = sumcheck.verify(relation_parameters, alpha, gate_challenges); // If Sumcheck did not verify, return false - if (!sumcheck_verified.has_value() || !sumcheck_verified.value()) { + if (!output.verified.has_value() || !output.verified.value()) { vinfo("Sumcheck verification failed"); return false; } // Public columns evaluation checks - std::vector mle_challenge(multivariate_challenge.begin(), - multivariate_challenge.begin() + static_cast(log_circuit_size)); + std::vector mle_challenge(output.challenge.begin(), + output.challenge.begin() + static_cast(log_circuit_size)); FF execution_input_evaluation = evaluate_public_input_column(public_inputs[0], mle_challenge); - if (execution_input_evaluation != claimed_evaluations.execution_input) { + if (execution_input_evaluation != output.claimed_evaluations.execution_input) { vinfo("execution_input_evaluation failed"); return false; } @@ -108,9 +107,9 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector 0; --i) { - Fr challengePower = geminiEvalChallengePowers[i - 1]; - Fr u = tp.sumCheckUChallenges[i - 1]; - Fr evalNeg = geminiEvaluations[i - 1]; - - Fr batchedEvalRoundAcc = ( - (challengePower * batchedEvalAccumulator * Fr.wrap(2)) - - evalNeg * (challengePower * (Fr.wrap(1) - u) - u) - ); - // Divide by the denominator - batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (Fr.wrap(1) - u) + u).invert(); - - bool is_dummy_round = (i > logN); - if (!is_dummy_round) { - batchedEvalAccumulator = batchedEvalRoundAcc; - } - } - - a_0_pos = batchedEvalAccumulator; - } - // This implementation is the same as above with different constants function batchMul( Honk.G1Point[NUMBER_OF_ENTITIES + CONST_PROOF_SIZE_LOG_N + 2] memory base, @@ -476,27 +419,4 @@ abstract contract BaseHonkVerifier is IVerifier { mstore(add(result, 0x20), mload(add(free, 0x20))) } } - - function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) internal view returns (bool) { - bytes memory input = abi.encodePacked( - rhs.x, - rhs.y, - // Fixed G1 point - uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), - uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), - uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), - uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), - lhs.x, - lhs.y, - // G1 point from VK - uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), - uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), - uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), - uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) - ); - - (bool success, bytes memory result) = address(0x08).staticcall(input); - bool decodedResult = abi.decode(result, (bool)); - return success && decodedResult; - } } diff --git a/barretenberg/sol/src/honk/CommitmentScheme.sol b/barretenberg/sol/src/honk/CommitmentScheme.sol new file mode 100644 index 000000000000..44958d6e4df3 --- /dev/null +++ b/barretenberg/sol/src/honk/CommitmentScheme.sol @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024 Aztec Labs +pragma solidity >=0.8.21; + +import {IVerifier} from "../interfaces/IVerifier.sol"; +import { + Honk, + WIRE, + NUMBER_OF_ENTITIES, + NUMBER_OF_SUBRELATIONS, + NUMBER_OF_ALPHAS, + NUMBER_UNSHIFTED, + BATCHED_RELATION_PARTIAL_LENGTH, + CONST_PROOF_SIZE_LOG_N +} from "./HonkTypes.sol"; + +import {ecMul, ecAdd, ecSub, negateInplace, convertProofPoint} from "./utils.sol"; + +// Field arithmetic libraries - prevent littering the code with modmul / addmul +import {MODULUS as P, MINUS_ONE, Fr, FrLib} from "./Fr.sol"; + +library CommitmentSchemeLib { + using FrLib for Fr; + + // Avoid stack too deep + struct ShpleminiIntermediates { + Fr unshiftedScalar; + Fr shiftedScalar; + // Scalar to be multiplied by [1]₁ + Fr constantTermAccumulator; + // Accumulator for powers of rho + Fr batchingChallenge; + // Linear combination of multilinear (sumcheck) evaluations and powers of rho + Fr batchedEvaluation; + } + + function computeSquares(Fr r) internal pure returns (Fr[CONST_PROOF_SIZE_LOG_N] memory squares) { + squares[0] = r; + for (uint256 i = 1; i < CONST_PROOF_SIZE_LOG_N; ++i) { + squares[i] = squares[i - 1].sqr(); + } + } + + function computeInvertedGeminiDenominators( + Fr shplonkZ, + Fr[CONST_PROOF_SIZE_LOG_N] memory eval_challenge_powers, + uint256 logSize + ) internal view returns (Fr[CONST_PROOF_SIZE_LOG_N + 1] memory inverse_vanishing_evals) { + Fr eval_challenge = shplonkZ; + inverse_vanishing_evals[0] = (eval_challenge - eval_challenge_powers[0]).invert(); + + for (uint256 i = 0; i < CONST_PROOF_SIZE_LOG_N; ++i) { + Fr round_inverted_denominator = Fr.wrap(0); + if (i <= logSize + 1) { + round_inverted_denominator = (eval_challenge + eval_challenge_powers[i]).invert(); + } + inverse_vanishing_evals[i + 1] = round_inverted_denominator; + } + } + + function computeGeminiBatchedUnivariateEvaluation( + Fr[CONST_PROOF_SIZE_LOG_N] memory sumcheckUChallenges, + Fr batchedEvalAccumulator, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvaluations, + Fr[CONST_PROOF_SIZE_LOG_N] memory geminiEvalChallengePowers, + uint256 logSize + ) internal view returns (Fr a_0_pos) { + for (uint256 i = CONST_PROOF_SIZE_LOG_N; i > 0; --i) { + Fr challengePower = geminiEvalChallengePowers[i - 1]; + Fr u = sumcheckUChallenges[i - 1]; + Fr evalNeg = geminiEvaluations[i - 1]; + + Fr batchedEvalRoundAcc = ( + (challengePower * batchedEvalAccumulator * Fr.wrap(2)) + - evalNeg * (challengePower * (Fr.wrap(1) - u) - u) + ); + // Divide by the denominator + batchedEvalRoundAcc = batchedEvalRoundAcc * (challengePower * (Fr.wrap(1) - u) + u).invert(); + + bool is_dummy_round = (i > logSize); + if (!is_dummy_round) { + batchedEvalAccumulator = batchedEvalRoundAcc; + } + } + + a_0_pos = batchedEvalAccumulator; + } +} diff --git a/barretenberg/sol/src/honk/Relations.sol b/barretenberg/sol/src/honk/Relations.sol index 23eab4ba5e24..f900d884fe28 100644 --- a/barretenberg/sol/src/honk/Relations.sol +++ b/barretenberg/sol/src/honk/Relations.sol @@ -9,7 +9,6 @@ import { NUMBER_OF_SUBRELATIONS, NUMBER_OF_ALPHAS, NUMBER_UNSHIFTED, - BATCHED_RELATION_PARTIAL_LENGTH, CONST_PROOF_SIZE_LOG_N } from "./HonkTypes.sol"; @@ -22,12 +21,11 @@ library RelationsLib { Fr internal constant GRUMPKIN_CURVE_B_PARAMETER_NEGATED = Fr.wrap(17); // -(-17) function accumulateRelationEvaluations( - Honk.Proof memory proof, + Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations, Honk.RelationParameters memory rp, Fr[NUMBER_OF_ALPHAS] memory alphas, Fr powPartialEval ) internal pure returns (Fr accumulator) { - Fr[NUMBER_OF_ENTITIES] memory purportedEvaluations = proof.sumcheckEvaluations; Fr[NUMBER_OF_SUBRELATIONS] memory evaluations; // Accumulate all relations in Ultra Honk - each with varying number of subrelations diff --git a/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol index 1c246dc4d6b1..bc44d995bc45 100644 --- a/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/Add2HonkVerificationKey.sol @@ -67,20 +67,20 @@ library Add2HonkVerificationKey { y: uint256(0x205f76eebda12f565c98c775c4e4f3534b5dcc29e57eed899b1a1a880534dcb9) }), s1: Honk.G1Point({ - x: uint256(0x2183ad847a1249f41cbd3a87f40c2f430eec8e15078ebf4294072495293f623a), - y: uint256(0x18f03d44febf5942b0325bd60625eb1d407adb20bdc51e770aa1f4ca1daf767c) + x: uint256(0x1a381262d2dc0ae06ad9a9b5ac16f1f997257a7219a5921a0c0905508174989b), + y: uint256(0x1a878a8000c10fa1377f4fa9fdef83fc4fa9fedda2536161dc32147405fc22a7) }), s2: Honk.G1Point({ - x: uint256(0x2d6764e48b62f11fa745090dbc582712f8a0a16ef81cc7da6fba8b1ec52d23a1), - y: uint256(0x0289e7980be1c71d3e91a117b1d062b27bf4d711e9ab3a8ee82a64eaf4c5ac45) + x: uint256(0x10b24427cfff3545af88e5ee9615a3d2aaed00a2673ddb52287f1c24d90551c3), + y: uint256(0x0cf6d3d8c5ce627691b89f51ba7ecfbe5e77cf972c1249134ce1cf86350047d9) }), s3: Honk.G1Point({ - x: uint256(0x16e299d4076387afc2add98ca386b3ff7ef29b7e87bb492a02e820b6404da3de), - y: uint256(0x2b11799049c80302774a11e05c57c8f614aecbc1c9a524e48328466195f35eaf) + x: uint256(0x014b56423aa6d8c7e5c2bf538201308e4b915f33262b80f7285dc7ec81612cb2), + y: uint256(0x114f17ae78a4cc5dea6694aaf454943a9daddcf81e8baf6986fa48bc16a17a55) }), s4: Honk.G1Point({ - x: uint256(0x27c8607e808c4a94be60e9fa6e4263ab2d4b41bd866add287affd942f5879b79), - y: uint256(0x25584de7b2b270f792e86e4ca403dc6fbf31f16b1da4d3f95ed9b8231e1a7e31) + x: uint256(0x2f0af830499e97b9fef4ce15d68553a257d311d455a84edd9191cbdec7294661), + y: uint256(0x1504661e6d39e647dbbccdefdecea76f650c55e7f5ecfa5565fc204c04f18afc) }), t1: Honk.G1Point({ x: uint256(0x1fb7c5d789d32e42a08e41296286139f603c7607ce186d0cce6e472dfe021473), @@ -99,20 +99,20 @@ library Add2HonkVerificationKey { y: uint256(0x1cb1414f7b9f8edb7c7a0d61f66e24e632a4050d9b3be0d6c35109aa99693039) }), id1: Honk.G1Point({ - x: uint256(0x2e286f771211f7466ea24e64484140bd5bcdcc759e88c2f4b2cc2fda221fb9c9), - y: uint256(0x21b150b35832343dd3988a32e15c404915b0cebfb762e47ad0a7ce18004bac27) + x: uint256(0x27a8eb48eb6b61e859bf2bfedea318164d066fe86a792d8d679d5246bdf2cf62), + y: uint256(0x1d9faaf08b8c91576372835839466c7e90a0d768cb3a49f41f602a5728c9108f) }), id2: Honk.G1Point({ - x: uint256(0x18eff4656b9f83aaf418fb251334d580bc6d247b19bb2438d4c4e71ffc3db1df), - y: uint256(0x1f859be892b830da65325a465f711a12a0b777997bbbfa5baebcb9f9a0eae3f1) + x: uint256(0x04a6f7b9877eaa5ae39bc13031af59a4a13c9c17a6788358a4aa2670017273ac), + y: uint256(0x17d2498a8dc9d84c36008e2c7f80d4cd91ca53e79064a4166d688d7d21623bf8) }), id3: Honk.G1Point({ - x: uint256(0x0a0ae72496a2b188d803fb33078c15cbd3d6874f3d1dd71eeb6ff7d8f4542ed5), - y: uint256(0x15314a39e87cc4d8274dc773f73f20ec712c0fc7216fc00b016fadca84dbf785) + x: uint256(0x16dfa43dce22231fdb946fb826bd95164bedc81eb7ab6b033841eb090e5450c9), + y: uint256(0x1d34de9ee00b0afd598ce51f4847506a8d9e1fda246f359fe2bc2a68c9faab32) }), id4: Honk.G1Point({ - x: uint256(0x2493c99a3d068b03f8f2b8d28b57cea3ee22dd60456277b86c32a18982dcb185), - y: uint256(0x1ded39c4c8366469843cd63f09ecacf6c3731486320082c20ec71bbdc92196c1) + x: uint256(0x26b7351976b4911c0fb008b70ed0edb10681b227234000deaf8064ecccdd5d00), + y: uint256(0x0e3f02f9444912dc14e554a8f0a5d63958fb3e7f8a28043a7b7ac00cb9ab2f3a) }), lagrangeFirst: Honk.G1Point({ x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), diff --git a/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol index fe39ba379287..fc67243f71fe 100644 --- a/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/BlakeHonkVerificationKey.sol @@ -67,20 +67,20 @@ library BlakeHonkVerificationKey { y: uint256(0x0335bb595984ad38686009bca08f5f420e3b4cf888fad5af4a99eca08190a315) }), s1: Honk.G1Point({ - x: uint256(0x259bede7c068653c0e2a16bd986e1ca97757315d3b973a494c6ca022cea60447), - y: uint256(0x2a93cb60e983030c470c044e1f156a25fe5e1941d38f4d8c91594e0eaa8858ae) + x: uint256(0x06ddfa4a7b1056d4796b8daae22b22d179be19eab51caf58fdea4425e327bffb), + y: uint256(0x1adc62a82085ad11e6ab1f246509c85228438a7d23bd2fa6b4d3c46d1c626d2e) }), s2: Honk.G1Point({ - x: uint256(0x11df397e5ad916749343c5be9797f2b6e3c0450714a1d5fa8a3f55ef32586940), - y: uint256(0x046a6da96359bd452f9f3c3ccc15b9f59c26bab349a02faa1f1d34517282ef6c) + x: uint256(0x000f6099cfd504c40c2c24656c391bfc51c73ce2be781422a4a1b281e540a5a2), + y: uint256(0x1312647f01ecd83e72b6b055a5c16e58d2ea8ba9fc2d107ff6f57a8096068d52) }), s3: Honk.G1Point({ - x: uint256(0x1ed35d2fd753212e17554522ac3d692ae25cb581f54adf02f99a5d6f71969d5d), - y: uint256(0x08352d3f6a0fb619cfd1a960514fe3394d9018f0388f631df9f5af9fcfd0efbe) + x: uint256(0x0d09604e64624e996b39f41a97666ca43c84d0044f9e2ddf2c464346fd1a79ad), + y: uint256(0x01f25a9671aeee824845248487796bce33d1882d34bd311f2065b90a58585a25) }), s4: Honk.G1Point({ - x: uint256(0x15365aa0c1d6bce15408f45f0251c9472f78297ec2cc5ab508f5c568980a893d), - y: uint256(0x2385c2920ad544f0be29c68152bc7ae98031aee831ddad561a45a95b31ae6ef5) + x: uint256(0x24b7a84a8bca763fa829d74c5648a3086f254ba44617a68c523518141a70a023), + y: uint256(0x0d722dffa2ba5793f809dcedb8e9607a418f1916252500249488b472f75424a9) }), t1: Honk.G1Point({ x: uint256(0x25bdb78d4e315a031ab7b6cb0dfdee32d86f4845ef1f837cdafa6c45f9ccae56), @@ -99,20 +99,20 @@ library BlakeHonkVerificationKey { y: uint256(0x2816e550d752b97bd0a5c2ed5369a652088981b3e92e3d6238b0c63b203aa3f4) }), id1: Honk.G1Point({ - x: uint256(0x2a2b95a34bb20d564d0b1ba33afdfe5ad95a8128ddfd8faec40b7bc2faf642e2), - y: uint256(0x1355384c7b2deba5fb394e25d297d5f37ccfaacfacd57aac61259bc1e87ea6ed) + x: uint256(0x1fcf5d681957dbfe3cc83d91afc9f58956a4a743395de96c4dd971858e1128f1), + y: uint256(0x15cd26a1f339bc2144d4906fc1aa494f9d1f4cf4e5ed93f143b5f48e4ef24434) }), id2: Honk.G1Point({ - x: uint256(0x279ce3dbe9564e5fd66014fbedb03f538e23b5effe8bf1c3ca394eba651d25fc), - y: uint256(0x0d130ad41878eba2d8da55ed688de58a3b8edf7b237e4ead56deebd56d11344c) + x: uint256(0x10856b890427164f8a4c626b232e0430d7da56dc74020993b1c9159081062a0f), + y: uint256(0x089faa89fe5a8144d88bb2b79a0bc64ef3ca77c6aee6ab195d9054d35f1de1af) }), id3: Honk.G1Point({ - x: uint256(0x1f3ca856540e150992ef85a64d5bb2ddc643a53f15dad567e08fc5a61307a2c3), - y: uint256(0x0f44b87f30b55235f069ad5d06f23915c19bf6194c0e6f54e2a4b41ef357e214) + x: uint256(0x0565a613b8cfcc14428b2b41622dd71f7fe993465e049c2951c5e4ff6ebb3219), + y: uint256(0x129f7fb53ad869c2bbe4a3b71ef37782d715e1c24b1613a90f5abd728cf7d3c5) }), id4: Honk.G1Point({ - x: uint256(0x2b85159a22ab90cb83642950f0240a403dac1dc50a970d1113be0cf8a8b5d63d), - y: uint256(0x1287b2e8e4ee3f0a9afbf798230ea32388a6e90924f13d7c78d5aed275095c79) + x: uint256(0x207b2e1adc325185880e218cd24d85e691fc04b7a3d11420b7b0c6355b3b8ef2), + y: uint256(0x2087f0e9a1eb5f7ee73dd9ab11193cf4f74a65e29d3797f1a4949382cd723e1f) }), lagrangeFirst: Honk.G1Point({ x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), diff --git a/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol b/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol index bd19e3682490..c24986bd96f4 100644 --- a/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol +++ b/barretenberg/sol/src/honk/keys/EcdsaHonkVerificationKey.sol @@ -67,20 +67,20 @@ library EcdsaHonkVerificationKey { y: uint256(0x2c5af44525879b9580e7687e6a93dd55fd6aa9251d90a5c2c4fc0ea971e1448b) }), s1: Honk.G1Point({ - x: uint256(0x1d9253a09df46bec5da04d4ef7839fd41bd2e97ae43ccfa143dc0d657fa85553), - y: uint256(0x12eba500137049f38ecfef8f8a8f061abfedbf4f832169375aafd290b8920667) + x: uint256(0x00b71575a57ba720e898927b0016053070edbf98f2a728b8fc2603da2a956d6b), + y: uint256(0x2c0c228f484a09b78d65d8ff8ceb4ea876d13f0269ee5b0e5dc54a3373c09bdc) }), s2: Honk.G1Point({ - x: uint256(0x108fa66ffac071a9a79c3798a54074139931be05a5b8c88596e354ff0c7977b9), - y: uint256(0x2ee653942fe48118b22616ff96b698dc5232a49ae5aaf33196af01d8cd783895) + x: uint256(0x2812ff69d1e7205d246f4e1b27e4ad97e6825cbc6b8d94c7f4afc4a8d41f256a), + y: uint256(0x29f88d4e5ff8d7304524f87f6a0fdf44eb36999e8592443764738204af151134) }), s3: Honk.G1Point({ - x: uint256(0x0e5e0e66b8d82ab97c3a4101da87d1457dfe38d8d781cd54d6a51fc4ed80fb5f), - y: uint256(0x1247d037ee1a73c1772120a83c697906102abd709365442c3057ad2f640e015f) + x: uint256(0x0889a6f2d947079d84b1cc1c90646b763e436020ca560ed5f9a31a515f1ff75f), + y: uint256(0x0f8c22955fec144d6946d978eea7a404700cd973b09b1e97863a225e93f69d0b) }), s4: Honk.G1Point({ - x: uint256(0x1cf115e956940f5beeb730452473c79f981e974cc1fd2dd4811f4de693860f24), - y: uint256(0x1a64f5ff7c28626ff23e5ae82e45f30158fc7dfd23487ad97ea9bb8b5b66e18d) + x: uint256(0x24738d8ce55b0475f1dafe411756e60fb20594fcb362d251a8b19c97539c83f6), + y: uint256(0x24ff3e562dbf315eda4d1aca54b46e34e7813894ddd7ff2adc4a584dca0b1456) }), t1: Honk.G1Point({ x: uint256(0x2467210c5e67f86104a38488eff67d1252b8dc1de9c1f589ff66bfd5a4de1ed6), @@ -99,20 +99,20 @@ library EcdsaHonkVerificationKey { y: uint256(0x01598d24dc1b7a351ac26c8ca4d1d7539ef9b9252f7e664648f36adc1deed9ca) }), id1: Honk.G1Point({ - x: uint256(0x1a0412e7de1e53ce0c0ccefc666cac1ae83945594a7aaf807e964415a11f00db), - y: uint256(0x2526a8a84a5f7d557379a155d0a8d9dade32a096cd81914029722c685fe420a9) + x: uint256(0x2ff83a26235c36a8ef7d2b5d60c94625cf0c6a8b7cb58c6bbc3279553d2c2a00), + y: uint256(0x0abd08db895dc02deb80c3a652726cd860f2c296c87c1a7ce06c7000f42dad0e) }), id2: Honk.G1Point({ - x: uint256(0x2158c8dcf92c304cd203397b9868e636c7bde65e68883364c458f067acb8c2b4), - y: uint256(0x08ba19108eabee284eccb6e86b4a8837fb36841af7da73e7979eea7d4f2dbe0b) + x: uint256(0x2e5c0ffba0e108dc6d15b50ad578bba829d956d77d10c1cb65355e536583c6bb), + y: uint256(0x14e7113a559d76c8aa2834f69aa8ebf9e89273753b590bbe1e7d331a9d4e55df) }), id3: Honk.G1Point({ - x: uint256(0x211a0d1167642ab55fa62b879782796fb8cd2809c658b45f62d528b5d5b34311), - y: uint256(0x05dab9a3e4d2f01fb9d44a9aefd0fc4565111bb73d25417bc00e0f7969b5e9a0) + x: uint256(0x1ef45b584cf8f71846ef653d030919c53c4d6ba746a02381161f867c5c19a4c7), + y: uint256(0x19f0cb5b94f4497352b81a1b6232fbb365af9e922cf54be78936a022ca7175a3) }), id4: Honk.G1Point({ - x: uint256(0x0a53a26d1390a734dd02a7b004ef88102974600e3baa15ec2e461c79ff9b8ca2), - y: uint256(0x21c24911108ee0462b6033b27d7a6acf2c85cf766eaada84575d92e98c103446) + x: uint256(0x2f9e04d881e2ba569b6dfb991db9620f682bcdd7b07ef610fba9ffea33ce44f3), + y: uint256(0x2da928074631459f8387befc89912d7c4d0c91538106a6dd5f3ff639bd890f35) }), lagrangeFirst: Honk.G1Point({ x: uint256(0x0000000000000000000000000000000000000000000000000000000000000001), diff --git a/barretenberg/sol/src/honk/utils.sol b/barretenberg/sol/src/honk/utils.sol index 33710be7e15e..52a9806a659e 100644 --- a/barretenberg/sol/src/honk/utils.sol +++ b/barretenberg/sol/src/honk/utils.sol @@ -126,3 +126,26 @@ function negateInplace(Honk.G1Point memory point) pure returns (Honk.G1Point mem point.y = (Q - point.y) % Q; return point; } + +function pairing(Honk.G1Point memory rhs, Honk.G1Point memory lhs) view returns (bool) { + bytes memory input = abi.encodePacked( + rhs.x, + rhs.y, + // Fixed G1 point + uint256(0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2), + uint256(0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed), + uint256(0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b), + uint256(0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa), + lhs.x, + lhs.y, + // G1 point from VK + uint256(0x260e01b251f6f1c7e7ff4e580791dee8ea51d87a358e038b4efe30fac09383c1), + uint256(0x0118c4d5b837bcc2bc89b5b398b5974e9f5944073b32078b7e231fec938883b0), + uint256(0x04fc6369f7110fe3d25156c1bb9a72859cf2a04641f99ba4ee413c80da6a5fe4), + uint256(0x22febda3c0c0632a56475b4214e5615e11e6dd3f96e6cea2854a87d4dacc5e55) + ); + + (bool success, bytes memory result) = address(0x08).staticcall(input); + bool decodedResult = abi.decode(result, (bool)); + return success && decodedResult; +} diff --git a/bb-pilcom/bb-pil-backend/templates/recursive_verifier.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/recursive_verifier.cpp.hbs index 06a3cfc57de0..6e8f8b358298 100644 --- a/bb-pilcom/bb-pil-backend/templates/recursive_verifier.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/recursive_verifier.cpp.hbs @@ -118,18 +118,17 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: // No need to constrain that sumcheck_verified is true as this is guaranteed by the implementation of // when called over a "circuit field" types. - auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = - sumcheck.verify(relation_parameters, alpha, gate_challenges); + SumcheckOutput output = sumcheck.verify(relation_parameters, alpha, gate_challenges); - vinfo("verified sumcheck: ", (sumcheck_verified.has_value() && sumcheck_verified.value())); + vinfo("verified sumcheck: ", (output.verified.has_value() && output.verified.value())); // Public columns evaluation checks - std::vector mle_challenge(multivariate_challenge.begin(), - multivariate_challenge.begin() + static_cast(log_circuit_size)); + std::vector mle_challenge(output.challenge.begin(), + output.challenge.begin() + static_cast(log_circuit_size)); {{#each public_cols}} FF {{col}}_evaluation = evaluate_public_input_column(public_inputs[{{idx}}], mle_challenge); - {{col}}_evaluation.assert_equal(claimed_evaluations.{{col}}, + {{col}}_evaluation.assert_equal(output.claimed_evaluations.{{col}}, "{{col}}_evaluation failed"); {{/each}} @@ -138,9 +137,9 @@ AvmRecursiveVerifier_::AggregationObject AvmRecursiveVerifier_:: auto opening_claim = Shplemini::compute_batch_opening_claim(circuit_size, commitments.get_unshifted(), commitments.get_to_be_shifted(), - claimed_evaluations.get_unshifted(), - claimed_evaluations.get_shifted(), - multivariate_challenge, + output.claimed_evaluations.get_unshifted(), + output.claimed_evaluations.get_shifted(), + output.challenge, Commitment::one(builder), transcript); auto pairing_points = PCS::reduce_verify_batch_opening_claim(opening_claim, transcript); diff --git a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs index 405579fc601e..32edcc259836 100644 --- a/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs +++ b/bb-pilcom/bb-pil-backend/templates/verifier.cpp.hbs @@ -85,22 +85,21 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vectortemplate get_challenge("Sumcheck:gate_challenge_" + std::to_string(idx)); } - auto [multivariate_challenge, claimed_evaluations, sumcheck_verified] = - sumcheck.verify(relation_parameters, alpha, gate_challenges); + SumcheckOutput output = sumcheck.verify(relation_parameters, alpha, gate_challenges); // If Sumcheck did not verify, return false - if (!sumcheck_verified.has_value() || !sumcheck_verified.value()) { + if (!output.verified.has_value() || !output.verified.value()) { vinfo("Sumcheck verification failed"); return false; } // Public columns evaluation checks - std::vector mle_challenge(multivariate_challenge.begin(), - multivariate_challenge.begin() + static_cast(log_circuit_size)); + std::vector mle_challenge(output.challenge.begin(), + output.challenge.begin() + static_cast(log_circuit_size)); {{#each public_cols}} FF {{col}}_evaluation = evaluate_public_input_column(public_inputs[{{idx}}], mle_challenge); - if ({{col}}_evaluation != claimed_evaluations.{{col}}) { + if ({{col}}_evaluation != output.claimed_evaluations.{{col}}) { vinfo("{{col}}_evaluation failed"); return false; } @@ -110,9 +109,9 @@ bool AvmVerifier::verify_proof(const HonkProof& proof, const std::vector