From 804647e94a4cb2164f26480baa43d2403c6e8bb5 Mon Sep 17 00:00:00 2001 From: Cody Gunton Date: Mon, 19 Dec 2022 17:53:50 -0500 Subject: [PATCH] Transfer Honk PoC work (#6) * Patch of src/aztec applied. Patch was generated on aztec2-internal by running the command `git diff --relative=barretenberg a036fb7c1..72704faec -- src/aztec/` from within barretenberg/. * Update .circleci/config.yml * Patch of src/aztec/plonk applied. Wasn't applied before? * Temporarily ignore code-workspace file and .clangd * Fix gcc compilation. --- barretenberg/.circleci/config.yml | 14 + barretenberg/.gitignore | 2 + barretenberg/cpp/.gitignore | 6 +- .../cmake/toolchains/x86_64-linux-gcc.cmake | 4 +- .../cmake/toolchains/x86_64-linux-gcc10.cmake | 4 +- barretenberg/cpp/src/aztec/CMakeLists.txt | 2 + .../cpp/src/aztec/honk/CMakeLists.txt | 1 + .../commitment_scheme/commitment_scheme.hpp | 101 ++++++ .../aztec/honk/commitment_scheme/gemini.hpp | 0 .../honk/commitment_scheme/kate/kate.hpp | 253 ++++++++++++++ .../honk/commitment_scheme/kate/kate.test.cpp | 298 ++++++++++++++++ .../kate/kate_commitment_scheme_data.hpp | 79 +++++ .../aztec/honk/commitment_scheme/shplonk.hpp | 0 .../aztec/honk/proof_system/honk_prover.cpp | 191 +++++++++++ .../aztec/honk/proof_system/honk_prover.hpp | 65 ++++ .../honk/proof_system/honk_prover.test.cpp | 30 ++ .../cpp/src/aztec/honk/sumcheck/sumcheck.hpp | 35 ++ .../aztec/honk/sumcheck/sumcheck_round.hpp | 317 +++++++++++++++++ .../honk/sumcheck/sumcheck_round.test.cpp | 321 ++++++++++++++++++ .../sumcheck_types/arithmetic_constraint.hpp | 71 ++++ .../sumcheck_types/barycentric_data.hpp | 145 ++++++++ .../sumcheck_types/challenge_container.hpp | 24 ++ .../sumcheck/sumcheck_types/constraint.hpp | 16 + .../sumcheck_types/constraint.test.cpp | 198 +++++++++++ .../sumcheck_types/constraint_manager.hpp | 25 ++ .../constraint_manager.test.cpp | 43 +++ .../grand_product_computation_constraint.hpp | 214 ++++++++++++ ...rand_product_initialization_constraint.hpp | 51 +++ .../sumcheck/sumcheck_types/multivariates.hpp | 134 ++++++++ .../sumcheck_types/multivariates.test.cpp | 134 ++++++++ .../sumcheck/sumcheck_types/univariate.hpp | 261 ++++++++++++++ .../sumcheck_types/univariate.test.cpp | 213 ++++++++++++ .../src/aztec/honk/sumcheck/transcript.hpp | 10 + .../cpp/src/aztec/plonk/CMakeLists.txt | 2 +- .../aztec/plonk/composer/composer_base.cpp | 2 +- .../plonk/composer/standard_composer.test.cpp | 2 +- .../plonk/composer/turbo_composer.test.cpp | 2 +- .../commitment_scheme/commitment_scheme.hpp | 2 +- .../commitment_scheme.test.cpp | 2 +- .../plonk/proof_system/prover/prover.cpp | 2 +- .../plonk/proof_system/prover/prover.hpp | 4 +- .../proof_system/verifier/verifier.test.cpp | 2 +- .../permutation_widget_impl.hpp | 2 +- .../random_widgets/plookup_widget_impl.hpp | 2 +- .../widgets/random_widgets/random_widget.hpp | 2 +- .../transition_widgets/transition_widget.hpp | 4 +- .../cpp/src/aztec/proof_system/CMakeLists.txt | 1 + .../polynomial_cache}/polynomial_cache.cpp | 0 .../polynomial_cache}/polynomial_cache.hpp | 2 +- .../polynomial_cache.test.cpp | 0 .../polynomial_cache}/polynomial_store.hpp | 2 +- .../polynomial_store.test.cpp | 0 .../polynomial_store_mem.cpp | 0 .../polynomial_store_wasm.cpp | 0 .../proof_system/proving_key/proving_key.cpp | 0 .../proof_system/proving_key/proving_key.hpp | 2 +- .../proving_key/proving_key.test.cpp | 2 +- .../proof_system/proving_key/serialize.hpp | 0 .../work_queue}/work_queue.cpp | 0 .../work_queue}/work_queue.hpp | 2 +- .../cpp/src/aztec/rollup/keygen/main.cpp | 2 +- .../rollup/proofs/account/account.test.cpp | 2 +- .../aztec/rollup/proofs/account/c_bind.cpp | 2 +- .../proofs/account/compute_circuit_data.hpp | 2 +- .../rollup/proofs/claim/get_circuit_data.hpp | 2 +- .../rollup/proofs/compute_circuit_data.hpp | 8 +- .../aztec/rollup/proofs/join_split/c_bind.cpp | 2 +- .../proofs/join_split/join_split.test.cpp | 2 +- .../join_split/join_split_js_parity.test.cpp | 2 +- .../proofs/rollup/compute_circuit_data.hpp | 2 +- .../root_rollup/compute_circuit_data.cpp | 2 +- .../cpp/src/aztec/rollup/rollup_cli/main.cpp | 2 +- .../recursion/verifier/verifier.test.cpp | 2 +- .../verifier/verifier_turbo.test.cpp | 2 +- 74 files changed, 3296 insertions(+), 41 deletions(-) create mode 100644 barretenberg/.gitignore create mode 100644 barretenberg/cpp/src/aztec/honk/CMakeLists.txt create mode 100644 barretenberg/cpp/src/aztec/honk/commitment_scheme/commitment_scheme.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/commitment_scheme/gemini.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate.test.cpp create mode 100644 barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate_commitment_scheme_data.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/commitment_scheme/shplonk.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.cpp create mode 100644 barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.test.cpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_round.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_round.test.cpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/arithmetic_constraint.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/barycentric_data.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/challenge_container.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint.test.cpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint_manager.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint_manager.test.cpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/grand_product_computation_constraint.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/grand_product_initialization_constraint.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/multivariates.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/multivariates.test.cpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/univariate.hpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/univariate.test.cpp create mode 100644 barretenberg/cpp/src/aztec/honk/sumcheck/transcript.hpp create mode 100644 barretenberg/cpp/src/aztec/proof_system/CMakeLists.txt rename barretenberg/cpp/src/aztec/{plonk/proof_system/proving_key => proof_system/polynomial_cache}/polynomial_cache.cpp (100%) rename barretenberg/cpp/src/aztec/{plonk/proof_system/proving_key => proof_system/polynomial_cache}/polynomial_cache.hpp (97%) rename barretenberg/cpp/src/aztec/{plonk/proof_system/proving_key => proof_system/polynomial_cache}/polynomial_cache.test.cpp (100%) rename barretenberg/cpp/src/aztec/{plonk/proof_system/proving_key => proof_system/polynomial_cache}/polynomial_store.hpp (96%) rename barretenberg/cpp/src/aztec/{plonk/proof_system/proving_key => proof_system/polynomial_cache}/polynomial_store.test.cpp (100%) rename barretenberg/cpp/src/aztec/{plonk/proof_system/proving_key => proof_system/polynomial_cache}/polynomial_store_mem.cpp (100%) rename barretenberg/cpp/src/aztec/{plonk/proof_system/proving_key => proof_system/polynomial_cache}/polynomial_store_wasm.cpp (100%) rename barretenberg/cpp/src/aztec/{plonk => }/proof_system/proving_key/proving_key.cpp (100%) rename barretenberg/cpp/src/aztec/{plonk => }/proof_system/proving_key/proving_key.hpp (97%) rename barretenberg/cpp/src/aztec/{plonk => }/proof_system/proving_key/proving_key.test.cpp (98%) rename barretenberg/cpp/src/aztec/{plonk => }/proof_system/proving_key/serialize.hpp (100%) rename barretenberg/cpp/src/aztec/{plonk/proof_system/prover => proof_system/work_queue}/work_queue.cpp (100%) rename barretenberg/cpp/src/aztec/{plonk/proof_system/prover => proof_system/work_queue}/work_queue.hpp (97%) diff --git a/barretenberg/.circleci/config.yml b/barretenberg/.circleci/config.yml index 2d9c182fa1ab..a3cf44c06182 100644 --- a/barretenberg/.circleci/config.yml +++ b/barretenberg/.circleci/config.yml @@ -148,6 +148,19 @@ jobs: command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 bb-tests - *save_logs + honk-tests: + docker: + - image: aztecprotocol/alpine-build-image + resource_class: small + steps: + - *checkout + - *setup_env + - run: + name: "Test" + command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 honk_tests + - *save_logs + + stdlib-primitives-tests: docker: - image: aztecprotocol/alpine-build-image @@ -270,6 +283,7 @@ workflows: - x86_64-linux-clang - x86_64-linux-clang-assert - wasm-linux-clang + - honk-tests: *bb_test - barretenberg-tests: *bb_test - stdlib-primitives-tests: *bb_test - stdlib-recursion-turbo-tests: *bb_test diff --git a/barretenberg/.gitignore b/barretenberg/.gitignore new file mode 100644 index 000000000000..b9e58ce089b5 --- /dev/null +++ b/barretenberg/.gitignore @@ -0,0 +1,2 @@ +# to be unignored when we finalize one of these +.vscode/*.code-workspace \ No newline at end of file diff --git a/barretenberg/cpp/.gitignore b/barretenberg/cpp/.gitignore index be056d1bc003..3af23ba15cd3 100644 --- a/barretenberg/cpp/.gitignore +++ b/barretenberg/cpp/.gitignore @@ -1,9 +1,11 @@ +.cache/ build*/ src/wasi-sdk-* -src/aztec/plonk/proof_system/proving_key/fixtures +src/aztec/proof_system/proving_key/fixtures src/aztec/rollup/proofs/*/fixtures srs_db/ignition/transcript* srs_db/lagrange srs_db/coset_lagrange srs_db/modified_lagrange -.vscode \ No newline at end of file +# to be unignored when we agree on clang-tidy rules +.clangd \ No newline at end of file diff --git a/barretenberg/cpp/cmake/toolchains/x86_64-linux-gcc.cmake b/barretenberg/cpp/cmake/toolchains/x86_64-linux-gcc.cmake index d1b2790e8877..bf0027451c7e 100644 --- a/barretenberg/cpp/cmake/toolchains/x86_64-linux-gcc.cmake +++ b/barretenberg/cpp/cmake/toolchains/x86_64-linux-gcc.cmake @@ -1,2 +1,4 @@ set(CMAKE_C_COMPILER "gcc") -set(CMAKE_CXX_COMPILER "g++") \ No newline at end of file +set(CMAKE_CXX_COMPILER "g++") +# TODO(Cody): git rid of this when Adrian's work goes in +add_compile_options(-Wno-uninitialized) \ No newline at end of file diff --git a/barretenberg/cpp/cmake/toolchains/x86_64-linux-gcc10.cmake b/barretenberg/cpp/cmake/toolchains/x86_64-linux-gcc10.cmake index 8ce971f493f4..f7095a1ff79d 100644 --- a/barretenberg/cpp/cmake/toolchains/x86_64-linux-gcc10.cmake +++ b/barretenberg/cpp/cmake/toolchains/x86_64-linux-gcc10.cmake @@ -1,2 +1,4 @@ set(CMAKE_C_COMPILER "gcc-10") -set(CMAKE_CXX_COMPILER "g++-10") \ No newline at end of file +set(CMAKE_CXX_COMPILER "g++-10") +# TODO(Cody): git rid of this when Adrian's work goes in +add_compile_options(-Wno-uninitialized) \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/CMakeLists.txt b/barretenberg/cpp/src/aztec/CMakeLists.txt index bfe595876212..60d28e63f858 100644 --- a/barretenberg/cpp/src/aztec/CMakeLists.txt +++ b/barretenberg/cpp/src/aztec/CMakeLists.txt @@ -31,6 +31,8 @@ add_subdirectory(srs) add_subdirectory(ecc) add_subdirectory(crypto) add_subdirectory(polynomials) +add_subdirectory(proof_system) +add_subdirectory(honk) add_subdirectory(plonk) add_subdirectory(stdlib) add_subdirectory(rollup) diff --git a/barretenberg/cpp/src/aztec/honk/CMakeLists.txt b/barretenberg/cpp/src/aztec/honk/CMakeLists.txt new file mode 100644 index 000000000000..4bf86c447188 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(honk numeric ecc srs plonk proof_system) diff --git a/barretenberg/cpp/src/aztec/honk/commitment_scheme/commitment_scheme.hpp b/barretenberg/cpp/src/aztec/honk/commitment_scheme/commitment_scheme.hpp new file mode 100644 index 000000000000..6ec470e0516a --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/commitment_scheme/commitment_scheme.hpp @@ -0,0 +1,101 @@ +#pragma once +#include + +// TODO: this needs to be a C++20 concept! +// i.e. we don't want to inherit from CommitmentScheme, but rather this thing defines an interface +// that we want multiple classes to conform + +/** + * @brief describes information (minus challenges) required to create a Kate opening proof. + * Conforms to the OpeningSchema concept + * + * @param polynomials Polynomials being opened + * @param shifted_polynomials Shifted polynomials being opened. Should be size ZERO for Kate as shifts are + * represented by modifying the evaluation points + * @param commitments Commitments to the polynomials being opened + * @param variables The set of points that the polynomials are being opened at + * @param evaluations The claimed evaluations of the committed polynomials when evaluated at points described by + * `variables` + * @param evaluations The claimed evaluations of the shifted polynomials. Should be size ZERO for Kate as shfits are + * represented by modifying the evaluation points + * @param n the number of coefficients in our polynomials (assumed all polynomials are of size n) + */ +template struct OpeningSchema { + std::vector polynomials; + std::vector shifted_polynomials; + std::vector commitments; + // 2d vector. First vector = number of variables, second vector = number of point openings for each variable. I + // think we can assume we open all polynomials at all points to keep things simplish... + std::vector> variables; + + // 2d vector. First vector = evaluations for a specific polynomial. Second vector = evaluations for a specific + // polynomial given a specific opening point + std::vector> evaluations; + std::vector> shifted_evaluations; + + const size_t n; +}; + +/** + * @brief describes information (minus challenges) required to verify a Kate opening proof. + * Conforms to the OpeningProof concept + * + * @param commitments Commitments to the polynomials being opened + * @param variables The set of points that the polynomials are being opened at + * @param evaluations The claimed evaluations of the committed polynomials when evaluated at points described by + * `variables` + * @param PI the opening proof group elements. One for every variable + */ +template struct OpeningProof { + std::vector commitments; + // variables we're opening our polynomials at, and their opening proofs + std::vector variables; + // 2d vector. First vector = evaluations for a specific polynomial. Second vector = evaluations for a specific + // polynomial given a specific opening point + std::vector> evaluations; + std::vector PI; +}; + +// namespace commitment_scheme_types +// template class CommitmentScheme { +// public: +// typedef typename CommitmentSchemeData::Fr Fr; +// typedef typename CommitmentSchemeData::Commitment Commitment; +// typedef typename CommitmentSchemeData::SRS SRS; +// typedef typename CommitmentSchemeData::OpeningProof OpeningProof; + +// using ChallengeGenerator = Fr (*)(const std::vector&); + +// static std::vector commit(const std::vector& , std::shared_ptr const&) = 0; + +// struct OpeningSchema { +// std::vector polynomials; +// std::vector shifted_polynomials; +// std::vector commitments; +// // 2d vector. First vector = number of variables, second vector = number of point openings for each variable. + +// // think we can assume we open all polynomials at all points to keep things simplish... +// std::vector> variables; + +// // 2d vector. First vector = evaluations for a specific polynomial. Second vector = evaluations for a +// specific +// // polynomial given a specific opening point +// std::vector> evaluations; +// std::vector> shifted_evaluations; + +// const size_t n; +// }; + +// static virtual OpeningProof batch_open(const OpeningSchema& committed_polynomials, +// std::shared_ptr const& srs, +// ChallengeGenerator& challenge_generator); + +// static virtual bool batch_verify(const OpeningProof& opening_proof, +// std::shared_ptr const& srs, +// ChallengeGenerator& challenge_generator); + +// // virtual AggregatedProof aggregate(const OpeningProof& opening_proof, +// // const AggregatedProof& input_aggregation, +// // std::shared_ptr const& srs, +// // ChallengeGenerator& challenge_generator); +// }; \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/honk/commitment_scheme/gemini.hpp b/barretenberg/cpp/src/aztec/honk/commitment_scheme/gemini.hpp new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate.hpp b/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate.hpp new file mode 100644 index 000000000000..2ddd04395264 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate.hpp @@ -0,0 +1,253 @@ +#pragma once + +#include +#include +#include + +#include "./kate_commitment_scheme_data.hpp" +#include "../commitment_scheme.hpp" + +/** + * @brief Kate commitment scheme class. Conforms to the CommitmentScheme specification (TODO make into a concept) + * + * @tparam CommitmentSchemeData parametrises how we represent the commitment scheme's data structures + * @tparam ChallengeGenerator used to "send" the Verifier data and receive random challenges. Conforms to the + * ChallengeGenerator concept + * + * @details We wish to loosely couple our commitment schemes to any proof system that uses them (e.g. Plonk, Honk!). We + * wish minimise how much knowledge of the challenge generation process is required by the commitment scheme. The + * ChallengeGenerator concept describes the minimal functionality required by the challenge module, its implementation + * details are left to the proof system + */ +template class Kate { + public: + typedef typename CommitmentSchemeData::Fr Fr; + typedef typename CommitmentSchemeData::G1 G1; + typedef typename CommitmentSchemeData::Commitment Commitment; + typedef typename CommitmentSchemeData::SRS SRS; + typedef typename CommitmentSchemeData::VerifierSRS VerifierSRS; + typedef typename CommitmentSchemeData::OpeningProof OpeningProof; + typedef typename CommitmentSchemeData::OpeningSchema OpeningSchema; + + // using ChallengeGenerator = Fr (*)(const std::vector&); + + /** + * @brief Commit to a vector of polynomials + * + * @param polynomials The input polynomials in coefficient form + * @param n The size of each polynomial (we assume all polynomials have the same size) + * @param srs The structured reference string required to compute the opening proof group elements PI + * + * @return a vector of Commitments + */ + static std::vector commit(const std::vector& polynomials, + const size_t n, + std::shared_ptr const& srs) + { + std::vector commitments; + commitments.reserve(polynomials.size()); + + // TODO: need to prevent `pippenger_runtime_state` being constructed each time this method is called. + // Should be a singleton :o + auto pippenger_runtime_state = barretenberg::scalar_multiplication::pippenger_runtime_state(n); + for (auto& poly : polynomials) { + commitments.push_back(barretenberg::scalar_multiplication::pippenger_unsafe( + poly, srs->get_monomials(), n, pippenger_runtime_state)); + } + + return commitments; + } + + /** + * @brief Compute an opening proof for opening multiple polynomials at multiple evaluation points + * + * @param opening_data Data required to compute the opening proof. See OpeningSchema comments for more details + * @param srs The structured reference string required to compute the opening proof group elements PI + * @param challenge_generator Used to 'send' the verifier proof outputs and receive random challenges + * + * @return an OpeningProof, containing information required to verify whether the polynomial evaluationsin + * `opening_data` are correct + * + * @details At this point this method is called, it is assumed that all polynomials have been committed to, + * the points at which the polynomials are being evaluated at have been computed + * and the evaluations of the polynomials at these points have been computed + */ + static OpeningProof batch_open(const OpeningSchema& opening_data, + std::shared_ptr srs, + ChallengeGenerator& challenge_generator) + { + OpeningProof result; + + ASSERT(opening_data.variables.size() == 1); + + // Kate doesn't explicitly use shifted polynomials, instead we open at evaluation point * root of unity + ASSERT(opening_data.shifted_evaluations.size() == 0); + + auto& polynomials = opening_data.polynomials; + auto& variables = opening_data.variables[0]; + const auto n = opening_data.n; + + std::vector flattened_evaluations; + for (const auto& evals : opening_data.evaluations) { + for (const auto& eval : evals) { + flattened_evaluations.push_back(eval); + } + } + const Fr nu = challenge_generator.generate_challenge(flattened_evaluations); + + // reserve some mem for our opening polys + // TODO: use assigned_alloc + std::vector opening_poly_data(n * variables.size()); + for (auto& ele : opening_poly_data) { + ele = 0; + } + std::vector opening_polynomials; + for (size_t k = 0; k < variables.size(); ++k) { + const auto variable = variables[k]; + + // assign opening poly + Fr* opening_poly = &opening_poly_data[k * n]; + opening_polynomials.push_back(opening_poly); + + // compute opening poly numerator + Fr separator_challenge = 1; + Fr opening_poly_eval(0); + for (size_t j = 0; j < polynomials.size(); ++j) { + + const size_t num_evaluations_for_poly = opening_data.evaluations[j].size(); + if (num_evaluations_for_poly <= k) { + continue; + } + Fr* poly = polynomials[j]; + for (size_t i = 0; i < n; ++i) { + opening_poly[i] += poly[i] * separator_challenge; + } + opening_poly_eval += opening_data.evaluations[j][k] * separator_challenge; + + separator_challenge *= nu; + } + + // step 2: divide by (X - z) + Fr divisor = -variable.invert(); + opening_poly[0] = opening_poly[0] - opening_poly_eval; + opening_poly[0] *= divisor; + for (size_t i = 1; i < n; ++i) { + opening_poly[i] -= opening_poly[i - 1]; + opening_poly[i] *= divisor; + } + } + + result.PI = commit(opening_polynomials, n, srs); + result.commitments = opening_data.commitments; + result.evaluations = opening_data.evaluations; + result.variables = variables; + return result; + } + + /** + * @brief Verify the correctness of an OpeningProof + * + * @param opening_proof A proof of correctness! See OpeningProof comments for more details + * @param srs The structured reference string required to compute the opening proof group elements PI + * @param challenge_generator Used to 'send' the verifier proof outputs and receive random challenges + * + * @return true/false depending on if the proof verifies + */ + static bool batch_verify(const OpeningProof& opening_proof, + std::shared_ptr const& srs, + ChallengeGenerator& challenge_generator) + { + // convenience variables - reference methods of `opening_proof` so we don't have to constantly type + // `opening_proof.` everywhere + auto& variables = opening_proof.variables; + auto& evaluations = opening_proof.evaluations; + auto& commitments = opening_proof.commitments; + auto& PI = opening_proof.PI; + + std::vector kate_opening_elements(commitments); + + std::vector flattened_evaluations; + for (const auto& evals : evaluations) { + for (const auto& eval : evals) { + flattened_evaluations.push_back(eval); + } + } + const Fr nu = challenge_generator.generate_challenge(flattened_evaluations); + + // TODO: flatten into Fr vector + // should probs add a method into Group for this (takes a std::vector spits out + // std::vector) + // TODO TODO: challenge generator needs to be able to accept both Fq and Fr! + std::vector foo; + for (const auto& pi : PI) { + foo.push_back(Fr(pi.x)); + foo.push_back(Fr(pi.y)); + } + const Fr separator_challenge = challenge_generator.generate_challenge(foo); + + const size_t num_polynomials = commitments.size(); + ASSERT(evaluations.size() == commitments.size()); + + std::vector kate_opening_scalars; + + Fr poly_separator_challenge = 1; + Fr batch_evaluation_scalar = 0; + + // 1. compute the scalar multipliers we need to apply to each of our commitments as part of the Kate + // verification algorithm when batching commitments [P0], ..., [Pn] we use challenge `nu` to create random + // linear combination: [P] = nu^0*[P0] + nu^1*[P1] + ... + nu^n*[Pn] + // 2. compute the `batch_evaluation_scalar`, the scalar multiplier we apply to the generator point. + for (size_t i = 0; i < num_polynomials; ++i) { + Fr opening_scalar = 0; + // num evaluations at this poly + Fr opening_separator_challenge = 1; + for (size_t j = 0; j < evaluations[i].size(); ++j) { + opening_scalar += (opening_separator_challenge); + batch_evaluation_scalar += (evaluations[i][j] * opening_separator_challenge * poly_separator_challenge); + opening_separator_challenge *= separator_challenge; + } + opening_scalar *= poly_separator_challenge; + kate_opening_scalars.push_back(opening_scalar); + poly_separator_challenge *= nu; + } + kate_opening_elements.push_back(G1::affine_one); + kate_opening_scalars.push_back(-batch_evaluation_scalar); + + // compute the scalar multipliers we must apply to the opening proof group elements `PI` + // in both the left hand and right hand pairing argument + std::vector kate_rhs_opening_elements; + std::vector kate_rhs_opening_scalars; + Fr opening_separator_challenge = 1; + for (size_t i = 0; i < PI.size(); ++i) { + kate_opening_elements.push_back(PI[i]); + kate_opening_scalars.push_back(variables[i] * opening_separator_challenge); + kate_rhs_opening_elements.push_back(PI[i]); + kate_rhs_opening_scalars.push_back(-opening_separator_challenge); + opening_separator_challenge *= separator_challenge; + } + + typename G1::element P[2]; + P[0] = typename G1::element(kate_opening_elements[0]) * kate_opening_scalars[0]; + P[1] = typename G1::element(kate_rhs_opening_elements[0]) * kate_rhs_opening_scalars[0]; + + for (size_t i = 1; i < kate_opening_elements.size(); ++i) { + P[0] += typename G1::element(kate_opening_elements[i]) * kate_opening_scalars[i]; + } + for (size_t i = 1; i < kate_rhs_opening_elements.size(); ++i) { + P[1] += typename G1::element(kate_rhs_opening_elements[i]) * kate_rhs_opening_scalars[i]; + } + G1::element::batch_normalize(P, 2); + + typename G1::affine_element P_affine[2]{ + { P[0].x, P[0].y }, + { P[1].x, P[1].y }, + }; + + // The final pairing check of step 12. + // TODO: try to template parametrise the pairing + fq12 output :/ + barretenberg::fq12 result = + barretenberg::pairing::reduced_ate_pairing_batch_precomputed(P_affine, srs->get_precomputed_g2_lines(), 2); + + return (result == barretenberg::fq12::one()); + } +}; \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate.test.cpp b/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate.test.cpp new file mode 100644 index 000000000000..5b142e398f98 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate.test.cpp @@ -0,0 +1,298 @@ + +#include "kate.hpp" + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace barretenberg; +using namespace waffle; + +struct Bn254 { + typedef barretenberg::fq Fq; + typedef barretenberg::fr Fr; + typedef barretenberg::g1 G1; +}; +typedef KateCommitmentSchemeData CommitmentSchemeData; + +static std::array challenges{ fr::random_element(), fr::random_element(), fr::random_element(), + fr::random_element(), fr::random_element(), fr::random_element(), + fr::random_element(), fr::random_element(), fr::random_element(), + fr::random_element() }; + +class MockChallengeGenerator { + public: + fr generate_challenge(const std::vector&) + { + auto result = challenges[count % 10]; + count++; + return result; + } + size_t count = 0; +}; + +typedef Kate, MockChallengeGenerator> KateBn254; + +// TEST(kate, open) +// { +// const size_t n = 16; + +// std::cout << "a" << std::endl; +// auto file_crs = std::make_shared("../srs_db"); +// auto crs = file_crs->get_prover_crs(n); +// std::cout << "b" << std::endl; + +// polynomial poly(n, n); +// for (size_t i = 0; i < 16; ++i) { +// poly[i] = fr::random_element(); +// } + +// std::cout << "c" << std::endl; +// const std::vector commitments = KateBn254::commit({ &poly[0] }, n, crs); + +// transcript::StandardTranscript inp_tx = transcript::StandardTranscript({}); +// waffle::KateCommitmentScheme newKate; +// auto circuit_proving_key = std::make_shared(n, 0, crs); +// work_queue queue(circuit_proving_key.get(), nullptr, &inp_tx); +// newKate.commit(&poly[0], "F_COMM", 0, queue); +// queue.process_queue(); + +// auto expected = inp_tx.get_group_element("F_COMM"); + +// EXPECT_EQ(commitments[0], expected); +// } + +// These tests were never working in sumcheck work. +// TEST(kate, kate_commit_open_verify_one_poly) +// { +// const size_t n = 16; + +// auto file_crs = std::make_shared("../srs_db"); +// auto crs = file_crs->get_prover_crs(n); +// auto verifier_crs = file_crs->get_verifier_crs(); + +// polynomial poly(n, n); +// for (size_t i = 0; i < 16; ++i) { +// poly[i] = fr::random_element(); +// } + +// fr z = fr::random_element(); + +// fr eval = poly.evaluate(z, n); + +// const std::vector commitments = KateBn254::commit({ &poly[0] }, n, crs); + +// KateBn254::OpeningSchema opening_schema{ .polynomials = { &poly[0] }, +// .shifted_polynomials = {}, +// .commitments = commitments, +// .variables = { { z } }, +// .evaluations = { { eval } }, +// .shifted_evaluations = {}, +// .n = n }; + +// MockChallengeGenerator prover_challenges; +// const auto opening_proof = KateBn254::batch_open(opening_schema, crs, prover_challenges); + +// MockChallengeGenerator verifier_challenges; +// const bool verified = KateBn254::batch_verify(opening_proof, verifier_crs, verifier_challenges); + +// EXPECT_EQ(verified, true); +// } + +// TEST(kate, kate_commit_open_verify_many_poly_many_vars) +// { +// const size_t num_polys = 9; +// const size_t num_openings = 7; +// const size_t n = 8; + +// auto file_crs = std::make_shared("../srs_db"); +// auto crs = file_crs->get_prover_crs(n); +// auto verifier_crs = file_crs->get_verifier_crs(); + +// std::vector polys(num_polys); +// std::vector evaluation_points; +// std::vector> polynomial_evaluations; + +// // n.b. when working with pointers as pointers to arrays, the underlying data cannot move! +// // this makes them a brittle construct. +// // Atm the commitment scheme spec represents polynomials as Fr* arrays... +// // This is because the current `polynomial` class is itself very brittle and ideally needs a big refactor, +// // it also only works for barretenberg::fr which is not sufficient anymore (i.e. we need grumpkin::fr support +// too) std::vector poly_pointers; for (size_t i = 0; i < num_openings; ++i) { +// evaluation_points.push_back(fr::random_element()); +// } + +// for (size_t j = 0; j < num_polys; ++j) { +// polys[j] = polynomial(n, n); +// auto& poly = polys[j]; + +// // polynomial poly(n, n); +// for (size_t i = 0; i < n; ++i) { +// poly[i] = fr::random_element(); +// } +// std::vector evaluations; +// for (size_t i = 0; i < num_openings; ++i) { +// evaluations.push_back(poly.evaluate(evaluation_points[i], n)); +// } +// polynomial_evaluations.push_back(evaluations); + +// poly_pointers.push_back(&(polys[j][0])); +// } + +// const std::vector commitments = KateBn254::commit(poly_pointers, n, crs); + +// KateBn254::OpeningSchema opening_schema{ .polynomials = poly_pointers, +// .shifted_polynomials = {}, +// .commitments = commitments, +// .variables = { evaluation_points }, +// .evaluations = polynomial_evaluations, +// .shifted_evaluations = {}, +// .n = n }; + +// MockChallengeGenerator prover_challenges; + +// const auto opening_proof = KateBn254::batch_open(opening_schema, crs, prover_challenges); + +// MockChallengeGenerator verifier_challenges; +// const bool verified = KateBn254::batch_verify(opening_proof, verifier_crs, verifier_challenges); + +// EXPECT_EQ(verified, true); +// } + +// // generate random polynomial F(X) = coeffs +// size_t n = 256; +// std::vector coeffs(n); +// for (size_t i = 0; i < n; ++i) { +// coeffs[i] = fr::random_element(); +// } +// std::vector W(coeffs.begin(), coeffs.end()); + +// // generate random evaluation point z +// fr z = fr::random_element(); + +// // compute opening polynomial W(X), and evaluation f = F(z) +// transcript::StandardTranscript inp_tx = transcript::StandardTranscript({}); +// waffle::KateCommitmentScheme newKate; + +// // std::shared_ptr crs_factory = (new FileReferenceStringFactory("../srs_db")); +// auto file_crs = std::make_shared("../srs_db"); +// auto crs = file_crs->get_prover_crs(n); +// auto circuit_proving_key = std::make_shared(n, 0, crs); +// work_queue queue(circuit_proving_key.get(), nullptr, &inp_tx); + +// newKate.commit(&coeffs[0], "F_COMM", 0, queue); +// queue.process_queue(); + +// fr y = fr::random_element(); +// fr f_y = polynomial_arithmetic::evaluate(&coeffs[0], y, n); +// fr f = polynomial_arithmetic::evaluate(&coeffs[0], z, n); + +// newKate.compute_opening_polynomial(&coeffs[0], &W[0], z, n, "W_COMM", fr(0), queue); +// queue.process_queue(); + +// // check if W(y)(y - z) = F(y) - F(z) +// fr w_y = polynomial_arithmetic::evaluate(&W[0], y, n); +// fr y_minus_z = y - z; +// fr f_y_minus_f = f_y - f; + +// EXPECT_EQ(w_y * y_minus_z, f_y_minus_f); + +// } + +// TEST(commitment_scheme, kate_batch_open) +// { +// // generate random evaluation points [z_1, z_2, ...] +// size_t t = 8; +// std::vector z_points(t); +// for (size_t k = 0; k < t; ++k) { +// z_points[k] = fr::random_element(); +// } + +// // generate random polynomials F(X) = coeffs +// // +// // z_1 -> [F_{1,1}, F_{1,2}, F_{1, 3}, ..., F_{1, m}] +// // z_2 -> [F_{2,1}, F_{2,2}, F_{2, 3}, ..., F_{2, m}] +// // ... +// // z_t -> [F_{t,1}, F_{t,2}, F_{t, 3}, ..., F_{t, m}] +// // +// // Note that each polynomial F_{k, j} \in F^{n} +// // +// size_t n = 64; +// size_t m = 4; +// std::vector coeffs(n * m * t); +// for (size_t k = 0; k < t; ++k) { +// for (size_t j = 0; j < m; ++j) { +// for (size_t i = 0; i < n; ++i) { +// coeffs[k * (m * n) + j * n + i] = fr::random_element(); +// } +// } +// } + +// // setting up the Kate commitment scheme class +// transcript::StandardTranscript inp_tx = transcript::StandardTranscript({}); +// waffle::KateCommitmentScheme newKate; + +// auto file_crs = std::make_shared("../srs_db"); +// auto crs = file_crs->get_prover_crs(n); +// auto circuit_proving_key = std::make_shared(n, 0, crs); +// work_queue queue(circuit_proving_key.get(), nullptr, &inp_tx); + +// // commit to individual polynomials +// for (size_t k = 0; k < t; ++k) { +// for (size_t j = 0; j < m; ++j) { +// newKate.commit(&coeffs[k * m * n + j * n], "F_{" + std::to_string(k + 1) + ", " + std::to_string(j + 1) + +// "}", 0, queue); +// } +// } +// queue.process_queue(); + +// // create random challenges, tags and item_constants +// std::vector challenges(t); +// std::vector tags(t); +// std::vector item_constants(t); +// for (size_t k = 0; k < t; ++k) { +// challenges[k] = fr::random_element(); +// tags[k] = "W_" + std::to_string(k + 1); +// item_constants[k] = fr(0); +// } + +// // compute opening polynomials W_1, W_2, ..., W_t +// std::vector W(n * t); +// newKate.generic_batch_open(&coeffs[0], &W[0], m, &z_points[0], t, &challenges[0], n, &tags[0], +// &item_constants[0], queue); queue.process_queue(); + +// // check if W_{k}(y) * (y - z_k) = \sum_{j} challenge[k]^{j - 1} * [F_{k, j}(y) - F_{k, j}(z_k)] +// fr y = fr::random_element(); +// for (size_t k = 0; k < t; ++k) { + +// // compute lhs +// fr W_k_at_y = polynomial_arithmetic::evaluate(&W[k * n], y, n); +// fr y_minus_z_k = y - z_points[k]; +// fr lhs = W_k_at_y * y_minus_z_k; + +// fr challenge_pow = fr(1); +// fr rhs = fr(0); +// for (size_t j = 0; j < m; ++j) { + +// // compute evaluations of source polynomials at y and z_points +// fr f_kj_at_y = polynomial_arithmetic::evaluate(&coeffs[k * m * n + j * n], y, n); +// fr f_kj_at_z = polynomial_arithmetic::evaluate(&coeffs[k * m * n + j * n], z_points[k], n); + +// // compute rhs +// fr f_term = f_kj_at_y - f_kj_at_z; +// rhs += challenge_pow * f_term; +// challenge_pow *= challenges[k]; +// } + +// EXPECT_EQ(lhs, rhs); +// } +// } diff --git a/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate_commitment_scheme_data.hpp b/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate_commitment_scheme_data.hpp new file mode 100644 index 000000000000..72108f779f9f --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/commitment_scheme/kate/kate_commitment_scheme_data.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include +#include "../commitment_scheme.hpp" + +/** + * @brief describes the data structures used by the Kate commitment scheme. Conforms to the CommitmentSchemeData + * specification (TODO make into a concept) + * + * @tparam Curve the elliptic curve being used + * + * @details The purpose of this class is to provide an abstraction layer that prevents Kate-specific data types from + * leaking out of our CommitmentScheme concept. For example, consider a proof system that has a CommitmentScheme + * template parameter. If parametrised using Kate, commitments will be Curve::G1::affine_element types. If parametrised + * using IPA, commitments will be std::vector types For the proof system to be + * commitment-scheme agnostic we need a single unifying type for commitments from any commitment scheme This is + * CommitmentSchemeData exposes a generic `Commitment` type Now the above proof system can use + * `CommitmentScheme::Commitment` to refer to its commitments and not have to worry about underlying type details + */ +template class KateCommitmentSchemeData { + public: + // expose field and group elements for convenience + typedef typename Curve::Fq Fq; + typedef typename Curve::Fr Fr; + typedef typename Curve::G1 G1; + + // define how Kate represents commitments + typedef typename G1::affine_element Commitment; + + // expose a generic type for the ProverSRS and VerifierSRS as this may differ depending on commitment scheme + typedef waffle::ProverReferenceString SRS; + typedef waffle::VerifierReferenceString VerifierSRS; + + // TODO: this only works or Fr?! We need to refactor `polynomial` to be field-agnostic + typedef barretenberg::polynomial Polynomial; + + // // NOTE: this sort of aliasing is not allowed by gcc! + // using OpeningSchema = OpeningSchema; + // using OpeningProof = OpeningProof; + + // struct OpeningSchema { + // std::vector polynomials; + // std::vector shifted_polynomials; + // std::vector commitments; + // // 2d vector. First vector = number of variables, second vector = number of point openings for each variable. + // I + // // think we can assume we open all polynomials at all points to keep things simplish... + // std::vector> variables; + + // // 2d vector. First vector = evaluations for a specific polynomial. Second vector = evaluations for a + // specific + // // polynomial given a specific opening point + // std::vector> evaluations; + // std::vector> shifted_evaluations; + + // const size_t n; + // }; + + // /** + // * @brief describes information (minus challenges) required to verify a Kate opening proof. + // * Conforms to the OpeningProof concept + // * + // * @param commitments Commitments to the polynomials being opened + // * @param variables The set of points that the polynomials are being opened at + // * @param evaluations The claimed evaluations of the committed polynomials when evaluated at points described by + // * `variables` + // * @param PI the opening proof group elements. One for every variable + // */ + // struct OpeningProof { + // std::vector commitments; + // // variables we're opening our polynomials at, and their opening proofs + // std::vector variables; + // // 2d vector. First vector = evaluations for a specific polynomial. Second vector = evaluations for a + // specific + // // polynomial given a specific opening point + // std::vector> evaluations; + // std::vector PI; + // }; +}; diff --git a/barretenberg/cpp/src/aztec/honk/commitment_scheme/shplonk.hpp b/barretenberg/cpp/src/aztec/honk/commitment_scheme/shplonk.hpp new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.cpp b/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.cpp new file mode 100644 index 000000000000..0163aac1ac6c --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.cpp @@ -0,0 +1,191 @@ +#include "honk_prover.hpp" + +namespace honk { + +/** + * Create HonkProver from proving key, witness and manifest. + * + * @param input_key Proving key. + * @param input_manifest Input manifest + * + * @tparam settings Settings class. + * */ +template +HonkProver::HonkProver(std::shared_ptr input_key, + const transcript::Manifest& input_manifest) + : n(input_key == nullptr ? 0 : input_key->n) + , transcript(input_manifest, settings::hash_type, settings::num_challenge_bytes) + , key(input_key) + , queue(key.get(), &transcript) +{} + +/** + * For Plonk systems: + * - Compute commitments to wires 1,2,3 + * - Get public inputs (which were stored in w_2_lagrange) and add to transcript + * + * For Honk, we should + * - Commit to wires 1,2,3 + * - Add PI to transcript (I guess PI will stay in w_2 for now?) + * + * */ +template void HonkProver::compute_wire_commitments() +{ + // TODO(luke): Compute wire commitments + + // TODO(luke): add public inputs to trascript for Honk + // const polynomial& public_wires_source = key->polynomial_cache.get("w_2_lagrange"); + // std::vector public_wires; + // for (size_t i = 0; i < key->num_public_inputs; ++i) { + // public_wires.push_back(public_wires_source[i]); + // } + // transcript.add_element("public_inputs", ::to_buffer(public_wires)); +} + +/** + * For Plonk systems: + * - added some initial data to transcript: circuit size and PI size + * - added randomness to lagrange wires + * - performed ifft to get monomial wires + * + * For Honk: + * - Still add initial data to transcript? That's it? + * + * */ +template void HonkProver::execute_preamble_round() +{ + // TODO(lde): add some initial data to transcript (circuit size and PI size) +} + +/** + * For Plonk systems this does 1 thing: compute wire commitments. + * This can probably be the identical thing for Honk. + * */ +template void HonkProver::execute_first_round() +{ + // TODO(luke): compute_wire_polynomial_commitments() +} + +/** + * For Plonk systems this + * - Do Fiat-Shamir to get "eta" challenge + * - does stuff related only to lookups (compute 's' etc and do some RAM/ROM stuff with w_4). + * + * For Standard Honk, this is a non-op (jsut like for Standard/Turbo Plonk). + * */ +template void HonkProver::execute_second_round() +{ + // TODO(luke): no-op (eta is not needed in Standard) +} + +/** + * For Plonk systems: + * - Do Fiat-Shamir to get "beta" challenge + * - Compute grand product polynomials (permutation and lookup) + * - Compute grand product commitments + * + * For Honk, we should + * - Do Fiat-Shamir to get "beta" challenge + * - Compute grand product polynomials (permutation only) + * - Compute grand product commitment (permutation only) + * + * */ +template void HonkProver::execute_third_round() +{ + // TODO(luke): compute beta/gamma challenge (Note: gamma = beta^2) + // TODO(luke): compute_grand_product_polynomial + // TODO(luke): compute_grand_product_polynomial_commitment +} + +/** + * For Plonk systems: + * - Do Fiat-Shamir to get "alpha" challenge + * - Compute coset_fft(L_1) + * - Compute quotient polynomial (with blinding) + * - Compute quotient polynomial commitment + * + * For Honk + * - Do Fiat-Shamir to get "alpha" challenge + * - Run Sumcheck + * + * */ +template void HonkProver::execute_fourth_round() +{ + // TODO(luke): Do Fiat-Shamir to get "alpha" challenge + // TODO(luke): Run Sumcheck +} + +/** + * For Plonk systems (no linearization): + * - Do Fiat-Shamir to get "z" challenge + * - Compute evaluation of quotient polynomial + * + * For Honk: + * - I don't think there's anything to do here. The analog should all occur in Sumcheck + * - Maybe some pre-processing for Gemini? + * + * */ +template void HonkProver::execute_fifth_round() +{ + // TODO(luke): Is there anything to do here? Possible some pre-processing for Gemini? +} + +/** + * For Plonk systems (no linearization): + * - Do Fiat-Shamir to get "nu" challenge + * - Perform batch opening + * + * For Honk: + * - Do Fiat-Shamir to get "nu" challenge? + * - engage in Gemini? + * + * */ +template void HonkProver::execute_sixth_round() +{ + // TODO(luke): Do Fiat-Shamir to get "nu" challenge? + // TODO(luke): Gemini? +} + +template waffle::plonk_proof& HonkProver::export_proof() +{ + proof.proof_data = transcript.export_transcript(); + return proof; +} + +template waffle::plonk_proof& HonkProver::construct_proof() +{ + // Execute init round. Randomize witness polynomials. + execute_preamble_round(); + queue.process_queue(); + + // Compute wire precommitments and sometimes random widget round commitments + execute_first_round(); + queue.process_queue(); + + // Fiat-Shamir eta + execute random widgets. + execute_second_round(); + queue.process_queue(); + + // Fiat-Shamir beta & gamma, execute random widgets (Permutation widget is executed here) + // and fft the witnesses + execute_third_round(); + queue.process_queue(); + + // Fiat-Shamir alpha, compute & commit to quotient polynomial. + execute_fourth_round(); + queue.process_queue(); + + execute_fifth_round(); + + execute_sixth_round(); + queue.process_queue(); + + queue.flush_queue(); + + return export_proof(); +} + +// TODO(luke): Need to define a 'standard_settings' analog for Standard Honk +template class HonkProver; + +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.hpp b/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.hpp new file mode 100644 index 000000000000..42083ce04897 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.hpp @@ -0,0 +1,65 @@ +#pragma once +#include "../../proof_system/proving_key/proving_key.hpp" +#include "../../plonk/proof_system/types/plonk_proof.hpp" +#include "../../plonk/proof_system/types/program_settings.hpp" + +namespace honk { + +template class HonkProver { + + public: + // TODO(luke): update this appropriately to work with Honk Manifest + HonkProver(std::shared_ptr input_key = nullptr, + const transcript::Manifest& manifest = transcript::Manifest({})); + + void execute_preamble_round(); + void execute_first_round(); + void execute_second_round(); + void execute_third_round(); + void execute_fourth_round(); + void execute_fifth_round(); + void execute_sixth_round(); + + void compute_wire_commitments(); + + waffle::plonk_proof& export_proof(); + waffle::plonk_proof& construct_proof(); + + size_t get_circuit_size() const { return n; } + + void flush_queued_work_items() { queue.flush_queue(); } + + waffle::work_queue::work_item_info get_queued_work_item_info() const { return queue.get_queued_work_item_info(); } + + size_t get_scalar_multiplication_size(const size_t work_item_number) const + { + return queue.get_scalar_multiplication_size(work_item_number); + } + + // TODO(luke): Eventually get rid of this but leave it for convenience for now + size_t n; + + // No more widgets. The new 'relations' may be owned by Sumcheck rather than Prover... + // std::vector> random_widgets; + // std::vector>> transition_widgets; + + // TODO(luke): maybe pointer instead? + transcript::StandardTranscript transcript; + + // TODO(luke): Honk PoC will have equivalent members + std::shared_ptr key; + // std::unique_ptr commitment_scheme; + + // TODO(luke): Honk only needs a small portion of the functionality but may be fine to use existing work_queue + waffle::work_queue queue; + + private: + waffle::plonk_proof proof; +}; + +// TODO(luke): need equivalent notion of settings for Honk +extern template class HonkProver; + +typedef HonkProver Prover; + +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.test.cpp b/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.test.cpp new file mode 100644 index 000000000000..578975972c43 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/proof_system/honk_prover.test.cpp @@ -0,0 +1,30 @@ +#include "./honk_prover.hpp" +#include "../../proof_system/proving_key/proving_key.hpp" +#include "../../srs/reference_string/file_reference_string.hpp" +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +using namespace honk; + +namespace test_honk_prover { + +TEST(HonkProver, HonkProverInstantiation) +{ + // Define some mock inputs for ProvingKey constructor + size_t num_gates = 8; + size_t num_public_inputs = 0; + auto reference_string = std::make_shared(num_gates + 1, "../srs_db/ignition"); + + // Instatiate a proving_key and make a pointer to it + auto proving_key = + std::make_shared(num_gates, num_public_inputs, reference_string, waffle::STANDARD); + + // Instantiate a HonkProver with the proving_key pointer + auto honk_prover = Prover(proving_key); +} + +} // namespace test_honk_prover \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck.hpp new file mode 100644 index 000000000000..74040b326e87 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck.hpp @@ -0,0 +1,35 @@ +#include "./sumcheck_round.hpp" +#include +#include +#include + +namespace honk { +namespace sumcheck { +template class... ConstraintPack> class Sumcheck { + using Fr = typename SumcheckTypes::Fr; + using Univariate = typename SumcheckTypes::Univariate; + using EdgeGroup = typename SumcheckTypes::EdgeGroup; + using HonkPolys = typename SumcheckTypes::HonkPolys; + using ChallengeContainer = typename SumcheckTypes::ChallengeContainer; + using Transcript = Transcript; + + public: + static constexpr size_t NUM_CONSTRAINTS = sizeof...(ConstraintPack); + + HonkPolys polynomials; + SumcheckRound round; + size_t multivariate_d; // aka num_vars + size_t multivariate_n; + Transcript transcript; + ChallengeContainer challenges; // construct with round size, claimed sum + + Sumcheck(HonkPolys polynomials) + : polynomials(polynomials) + { + multivariate_d = polynomials.multivariate_d; + multivariate_n = 1 << multivariate_d; + // TODO: construct round, etc. + }; +}; +} // namespace sumcheck +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_round.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_round.hpp new file mode 100644 index 000000000000..157b040ce81f --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_round.hpp @@ -0,0 +1,317 @@ +#include +#include +#include +#include +#include +#include "./sumcheck_types/univariate.hpp" +#include "./sumcheck_types/constraint_manager.hpp" +#include "./sumcheck_types/barycentric_data.hpp" +namespace honk { +namespace sumcheck { + +/* + Notation: The polynomial P(X1, X2) that is the low-degree extension of its values vij = P(i,j) + for i,j ∈ H = {0,1} is conveniently recorded as follows: + (0,1)-----(1,1) v01 ------ v11 + | | | | P(X1,X2) = (v01 * (1-X1) + v11 * X1) * X2 + | H^2 | | P(X1,X2) | + (v00 * (1-X1) + v10 * X1) * (1-X2) + | | | | + (0,0) ---- (1,0) v00 -------v10 +*/ + +/* + Example: There are two low-degree extensions Y1, Y2 over the square H^2 in the Cartesian plane. + + 3 -------- 7 4 -------- 8 + | | | | Let F(X1, X2) = G(Y1, Y2) = G0(Y1(X1, X2) + Y2(X1, X2)) + | Y1 | | Y2 | + α G1(Y1(X1, X2) + Y2(X1, X2)), + | | | | where the constraints are G0(Y1, Y2) = Y1 * Y2 + 1 -------- 5 2 -------- 6 and G1(Y1, Y2) = Y1 + Y2. + + G itself is represented by a SumcheckRound class. + G1, G2 together comprise the ConstraintPack. + The polynomials Y1, Y2 are stored as two edge groups: + 3 4 7 8 +one containing | and | and another containing | and | . + 1 2 5 6 +The rationale here is that both folding and evaluation will proceed one edge group at a time. + */ + +template class... ConstraintPack> class SumcheckRound { + using Fr = typename SumcheckTypes::Fr; + using Multivariates = typename SumcheckTypes::Multivariates; + using ChallengeContainer = typename SumcheckTypes::ChallengeContainer; + + public: + size_t round_size; + bool failed = false; + Fr target_total_sum; + Multivariates multivariates; + std::array purported_evaluations; + ConstraintManager...> constraint_manager; // TODO(cody); move more evals, maybe more, into here + ChallengeContainer challenges; + static constexpr size_t SUMCHECK_CONSTRAINT_DEGREE_PLUS_ONE = + 5; // TODO(luke): This value is independently defined in multiple locations + BarycentricData barycentric = + BarycentricData(); + std::array, Multivariates::num> edge_extensions; + std::array, Multivariates::num> extended_univariates; + static constexpr size_t NUM_CONSTRAINTS = sizeof...(ConstraintPack); + + SumcheckRound(Multivariates multivariates, ChallengeContainer challenges) + : multivariates(multivariates) + , challenges(challenges) + { + // TODO: test edge case + // Here (and everywhere?) multivariate_n is assumed to be a power of 2 + // will be halved after each round + round_size = multivariates.multivariate_n; + } + + SumcheckRound(std::array purported_evaluations, ChallengeContainer challenges) + : purported_evaluations(purported_evaluations) + , challenges(challenges) + {} + + /** + * @brief Given a tuple t = (t_0, t_1, ..., t_{NUM_CONSTRAINTS-1}) and a challenge α, + * modify the tuple in place to (t_0, αt_1, ..., α^{NUM_CONSTRAINTS-1}t_{NUM_CONSTRAINTS-1}). + */ + template void scale_tuple(auto& tuple, Fr challenge, Fr running_challenge) + { + std::get(tuple) *= running_challenge; + running_challenge *= challenge; + if constexpr (idx + 1 < NUM_CONSTRAINTS) { + scale_tuple(tuple, challenge, running_challenge); + } + }; + /** + * @brief Given a tuple t = (t_0, t_1, ..., t_{NUM_CONSTRAINTS-1}) and a challenge α, + * return t_0 + αt_1 + ... + α^{NUM_CONSTRAINTS-1}t_{NUM_CONSTRAINTS-1}). + */ + template T batch_over_constraints(auto& tuple, Fr challenge) + { + Fr running_challenge = 1; + scale_tuple<>(tuple, challenge, running_challenge); + extend_univariate_accumulators<>(); + auto result = T(); + // T result = std::apply([&](auto... v) { return (v + ...); }, tuple); + for (size_t i = 0; i < NUM_CONSTRAINTS; ++i) { + result += extended_univariates[i]; + } + return result; + } + + /** + * @brief Evaluate some constraints by evaluating each edge in the edge group at + * Univariate::length-many values. Store each value separately in the corresponding + * entry of constraint_evals. + * + * @details Should only be called externally with constraint_idx equal to 0. + * + */ + void extend_edges(std::array polynomial, size_t edge_idx) + { + for (size_t idx = 0; idx < Multivariates::num; idx++) { + auto edge = Univariate({ polynomial[idx][edge_idx], polynomial[idx][edge_idx + 1] }); + edge_extensions[idx] = barycentric.extend(edge); + } + } + + // TODO(cody): make private + template void accumulate_constraint_univariates() + { + std::get(constraint_manager.constraints) + .add_edge_contribution(edge_extensions, + std::get(constraint_manager.univariate_accumulators)); + + // Repeat for the next constraint. + if constexpr (constraint_idx + 1 < NUM_CONSTRAINTS) { + accumulate_constraint_univariates(); + } + } + + // TODO(cody): make private + // TODO(cody): make uniform with univariates + template + void accumulate_constraint_evaluations(std::array& constraint_evaluations) + { + std::get(constraint_manager.constraints) + .add_full_constraint_value_contribution(purported_evaluations, constraint_evaluations[constraint_idx]); + + // Repeat for the next constraint. + if constexpr (constraint_idx + 1 < NUM_CONSTRAINTS) { + accumulate_constraint_evaluations(constraint_evaluations); + } + } + + /** + * @brief After executing each widget on each edge, producing a tuple of univariates of differing lenghts, + * extend all univariates to the max of the lenghts required by the largest constraint. + * + * @tparam constraint_idx + */ + template void extend_univariate_accumulators() + { + extended_univariates[constraint_idx] = + std::get(constraint_manager.constraints) + .barycentric.extend(std::get(constraint_manager.univariate_accumulators)); + + // Repeat for the next constraint. + if constexpr (constraint_idx + 1 < NUM_CONSTRAINTS) { + extend_univariate_accumulators(); + } + } + + /** + * @brief In the first round, return the evaluations of the univariate restriction S(X_l) at EdgeGroup::length-many + * values. Most likely this will end up being S(0), ... , S(t-1) where t is around 12. + * + * @details We have a separate function for the first round so we can halve the memory + * usage of the sumcheck round by only copy the results after folding. + * + * @param edges + * @param challenges + * @return Univariate + * + */ + Univariate compute_initial_univariate_restriction( + Multivariates& multivariates, ChallengeContainer& challenges) + { + for (size_t edge_idx = 0; edge_idx < round_size; edge_idx += 2) { + extend_edges(multivariates.full_polynomials, edge_idx); + accumulate_constraint_univariates<>(); + } + + Fr running_challenge(1); + Fr challenge = challenges.get_constraint_separator_challenge(); + auto result = batch_over_constraints>( + constraint_manager.univariate_accumulators, challenge); + + // at this point, we are able to + // - add these coefficients to the transcript and extract u_l + // - partially evaluate all multivariates in u_l + return result; + } + + /** + * @brief Return the evaluations of the univariate restriction S_l(X_l) at EdgeGroup::length-many values. + * Most likely this will end up being S_l(0), ... , S_l(t-1) where t is around 12. + * + * @param edges + * @param challenges + * @return Univariate + * + */ + Univariate compute_univariate_restriction(Multivariates& multivariates, + ChallengeContainer& challenges) + { + // For each edge index, iterate over all constraints, accumulating for each constraint the contribution + // to each of desired evaluations of S_l. + std::tuple::CONSTRAINT_LENGTH>...> constraint_univariates = + std::tuple(ConstraintPack::CONSTRAINT_LENGTH...); + + for (size_t edge_idx = 0; edge_idx < round_size; edge_idx += 2) { + extend_edges(multivariates.folded_multivariates, edge_idx); + accumulate_constraint_univariates<>(constraint_univariates); + } + + // Construct the univariate restriction + Fr running_challenge(1); + Fr challenge = challenges.get_constraint_separator_challenge(); + Univariate result({ 0 }); // need to initialize to 0 + for (auto& univariate : constraint_univariates) { + result += univariate * running_challenge; + running_challenge *= challenge; + } + + // - add these coefficients to the transcript and extract u_l + // - partially evaluate all multivariates in u_l + return result; + } + + Fr compute_full_honk_constraint_purported_value(ChallengeContainer& challenges) + { + // TODO(cody): Reuse functions from univariate_accumulators batching? + std::array constraint_evaluations{ { 0 } }; + accumulate_constraint_evaluations<>(constraint_evaluations); + + Fr running_challenge(1); + Fr challenge = challenges.get_constraint_separator_challenge(); + Fr output(0); + for (auto& evals : constraint_evaluations) { + output += evals * running_challenge; + running_challenge *= challenge; + } + + return output; + } + + bool check_sum(Univariate& univariate_restriction) + { + // S_l(0) + S_l(1) + Fr total_sum = univariate_restriction.at(0) + univariate_restriction.at(1); + bool sumcheck_round_passes = (target_total_sum == total_sum); // an assert_equal + return sumcheck_round_passes; + }; + + /** + * @brief Have ChallengeContainer sample the next univariate evalution challenge u_l and the resulting univariate + * value sigma_l of the function S_l. + * @param evals + * @param challenges + */ + Fr compute_challenge_and_evaluation(Univariate& univariate_restriction, + ChallengeContainer& challenges) + { + // add challenges to transcript and run Fiat-Shamir + Fr challenge = challenges.get_sumcheck_round_challenge(univariate_restriction); + auto barycentric = BarycentricData::num_evals, + Univariate::num_evals>(); + target_total_sum = barycentric.evaluate(univariate_restriction, challenge); + return challenge; + } + + bool execute_first_round() + { + Univariate univariate_restriction = + compute_initial_univariate_restriction(multivariates, challenges); + // evaluate univariate restriction and challenge and check for equality with target value + failed = !check_sum(univariate_restriction); + + if (failed) { + // TODO: use to set composer.failed? + return false; + } + // compute univariate evaluation challenge and update the target value + // for the next call to check_sum + Fr round_challenge = compute_challenge_and_evaluation(univariate_restriction, challenges); + multivariates.fold(round_size, round_challenge); + round_size /= 2; + + return true; + }; + + bool execute() + { + Univariate univariate_restriction = + compute_univariate_restriction(multivariates, challenges); + // evaluate univariate restriction and challenge and check for equality with target value + failed = !check_sum(univariate_restriction); + + if (failed) { + // TODO: use to set composer.failed? + return false; + } + // compute univariate evaluation challenge and update the target value + // for the next call to check_sum + Fr round_challenge = compute_challenge_and_evaluation(univariate_restriction, challenges); + multivariates.fold(round_size, round_challenge); + round_size /= 2; + + return true; + }; +}; +} // namespace sumcheck +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_round.test.cpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_round.test.cpp new file mode 100644 index 000000000000..43573ac5d86a --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_round.test.cpp @@ -0,0 +1,321 @@ +#include "./transcript.hpp" +#include "./sumcheck_round.hpp" +#include "./sumcheck_types/constraint.hpp" +#include "./sumcheck_types/arithmetic_constraint.hpp" +#include "./sumcheck_types/multivariates.hpp" +#include "./sumcheck_types/univariate.hpp" +#include "./sumcheck_types/challenge_container.hpp" +#include +#include + +#include + +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +using namespace honk; +using namespace honk::sumcheck; + +template class MockTranscript : public Transcript { + public: + Fr get_challenge() { return mock_challenge; }; + Fr mock_challenge = -1; +}; + +namespace test_sumcheck_round { + +TEST(Sumcheck, ComputeUnivariateProverMock) +{ + // arithmetic constraint G is deegree 3 in 8 variables + // G(Y1, ..., Y8) = Y4Y1Y2 + Y5Y1 + Y6Y2 + Y7Y3 + Y8 + const size_t num_polys(MULTIVARIATE::COUNT); + const size_t multivariate_d(1); + const size_t multivariate_n(1 << multivariate_d); + const size_t constraint_degree_plus_one = 5; // TODO(cody) extract from widget + + class SumcheckTypes { + public: + using Fr = barretenberg::fr; + // using Univariate = Univariate; + using Multivariates = ::Multivariates; + using ChallengeContainer = + ::ChallengeContainer, Univariate>; + }; + + SumcheckTypes::Fr w_l[2] = { 1, 2 }; + SumcheckTypes::Fr w_r[2] = { 1, 2 }; + SumcheckTypes::Fr w_o[2] = { 1, 2 }; + SumcheckTypes::Fr z_perm[2] = { 1, 2 }; + SumcheckTypes::Fr z_perm_shift[2] = { 1, 2 }; + SumcheckTypes::Fr q_m[2] = { 1, 2 }; + SumcheckTypes::Fr q_l[2] = { 1, 2 }; + SumcheckTypes::Fr q_r[2] = { 1, 2 }; + SumcheckTypes::Fr q_o[2] = { 1, 2 }; + SumcheckTypes::Fr q_c[2] = { 1, 2 }; + SumcheckTypes::Fr sigma_1[2] = { 1, 2 }; + SumcheckTypes::Fr sigma_2[2] = { 1, 2 }; + SumcheckTypes::Fr sigma_3[2] = { 1, 2 }; + SumcheckTypes::Fr id_1[2] = { 1, 2 }; + SumcheckTypes::Fr id_2[2] = { 1, 2 }; + SumcheckTypes::Fr id_3[2] = { 1, 2 }; + SumcheckTypes::Fr lagrange_1[2] = { 1, 2 }; + + std::array full_polynomials({ w_l, + w_r, + w_o, + z_perm, + z_perm_shift, + q_m, + q_l, + q_r, + q_o, + q_c, + sigma_1, + sigma_2, + sigma_3, + id_1, + id_2, + id_3, + lagrange_1 }); + + auto multivariates = SumcheckTypes::Multivariates(full_polynomials); + + auto transcript = MockTranscript(); // actually a shared pointer to a transcript? + auto challenges = SumcheckTypes::ChallengeContainer(transcript); + + size_t round_size = 1; + // call SumcheckRound with one constraint + auto round = SumcheckRound(multivariates, challenges); + Univariate restriction = + round.compute_initial_univariate_restriction(multivariates, challenges); + Univariate expected_restriction{ { 5, 22, 57, 116, 205 } }; + EXPECT_EQ(restriction, expected_restriction); +} + +TEST(Sumcheck, ComputeUnivariateVerifierMock) +{ + // arithmetic constraint G is deegree 3 in 8 variables + // G(Y1, ..., Y8) = Y4Y1Y2 + Y5Y1 + Y6Y2 + Y7Y3 + Y8 + const size_t num_polys(MULTIVARIATE::COUNT); + const size_t multivariate_d(1); + const size_t multivariate_n(1 << multivariate_d); + const size_t constraint_degree_plus_one = 5; // TODO(cody) extract from widget + + class SumcheckTypes { + public: + using Fr = barretenberg::fr; + // using Univariate = Univariate; + using Multivariates = ::Multivariates; + using ChallengeContainer = + ::ChallengeContainer, Univariate>; + }; + + SumcheckTypes::Fr w_l = { 1 }; + SumcheckTypes::Fr w_r = { 2 }; + SumcheckTypes::Fr w_o = { 3 }; + SumcheckTypes::Fr z_perm = { 0 }; + SumcheckTypes::Fr z_perm_shift = { 0 }; + SumcheckTypes::Fr q_m = { 4 }; + SumcheckTypes::Fr q_l = { 5 }; + SumcheckTypes::Fr q_r = { 6 }; + SumcheckTypes::Fr q_o = { 7 }; + SumcheckTypes::Fr q_c = { 8 }; + SumcheckTypes::Fr sigma_1 = { 0 }; + SumcheckTypes::Fr sigma_2 = { 0 }; + SumcheckTypes::Fr sigma_3 = { 0 }; + SumcheckTypes::Fr id_1 = { 0 }; + SumcheckTypes::Fr id_2 = { 0 }; + SumcheckTypes::Fr id_3 = { 0 }; + SumcheckTypes::Fr lagrange_1 = { 0 }; + + // 4 * 1 * 2 + 5 * 1 + 6 * 2 + 7 * 3 + 8 = 54 + SumcheckTypes::Fr expected_full_purported_value = 54; + std::array purported_evaluations({ w_l, + w_r, + w_o, + z_perm, + z_perm_shift, + q_m, + q_l, + q_r, + q_o, + q_c, + sigma_1, + sigma_2, + sigma_3, + id_1, + id_2, + id_3, + lagrange_1 }); + + auto transcript = MockTranscript(); // actually a shared pointer to a transcript? + auto challenges = SumcheckTypes::ChallengeContainer(transcript); + + size_t round_size = 1; + // call SumcheckRound with one constraint + auto round = SumcheckRound(purported_evaluations, challenges); + SumcheckTypes::Fr full_purported_value = round.compute_full_honk_constraint_purported_value(challenges); + EXPECT_EQ(full_purported_value, expected_full_purported_value); +} + +// TEST(sumcheck, round) +// { +// // arithmetic constraint G is deegree 3 in 8 variables +// // G(Y1, ..., Y8) = Y4Y1Y2 + Y5Y1 + Y6Y2 + Y7Y3 + Y8 +// const size_t num_polys(MULTIVARIATE::COUNT); +// const size_t multivariate_d(2); +// const size_t multivariate_n(1 << multivariate_d); +// const size_t constraint_degree_plus_one = 5; + +// using Fr = barretenberg::fr; +// using Edge = Edge; +// using EdgeGroup = EdgeGroup; +// using Multivariates = Multivariates; +// using Univariate = Univariate; +// using ChallengeContainer = ChallengeContainer, Univariate>; + +// class SumcheckTypes { +// public: +// using Fr = Fr; +// using EdgeGroup = EdgeGroup; +// using Multivariates = Multivariates; +// using ChallengeContainer = ChallengeContainer; +// using Univariate = Univariate; +// }; + +// // TODO(cody): move this out of round. +// EdgeGroup group0({ Edge({ 1, 2 }), +// Edge({ 1, 2 }), +// Edge({ 1, 2 }), +// Edge({ 1, 2 }), +// Edge({ 1, 2 }), +// Edge({ 1, 2 }), +// Edge({ 1, 2 }), +// Edge({ 1, 2 }) }); + +// EdgeGroup group1({ Edge({ 7, 8 }), +// Edge({ 7, 8 }), +// Edge({ 7, 8 }), +// Edge({ 7, 8 }), +// Edge({ 7, 8 }), +// Edge({ 7, 8 }), +// Edge({ 7, 8 }), +// Edge({ 7, 8 }) }); + +// auto polynomials = Multivariates({ group0, group1 }); +// auto constraints = std::make_tuple(ArithmeticConstraint()); +// auto transcript = MockTranscript(); // actually a shared pointer to a transcript? +// auto challenges = ChallengeContainer(transcript); + +// auto round = SumcheckRound(polynomials, constraints, challenges); +// // The values of the univariate restriction S2 created in the first round +// // are the sum of a contribution form group0 and a contribution from group1. +// // Using Sage; +// // group0 contributes: [5, 22, 57, 116] +// // group1 contributes: [497, 712, 981, 1310] +// // Therefore the values of S2 on {0, 1, 2, 3} are: [502, 734, 1038, 1426] +// // and S2(0) + S2(1) = 502 + 734 = 1236 +// round.target_total_sum = 1236; +// EXPECT_EQ(round.round_size, 2); +// /* +// Folding with u2 = -1 +// 2 -------- 8 +// | | +// | Yi | +// | i=1...8 | +// 1 -------- 7 ~~> 0 -------- 6 +// (2(1-X1)+8X1) X2 0(1-X1)+6X1 +// +(1(1-X1)+7X1)(1-X2) +// */ +// round.execute(); +// EdgeGroup expected_group0({ Edge({ 0, 6 }), +// Edge({ 0, 6 }), +// Edge({ 0, 6 }), +// Edge({ 0, 6 }), +// Edge({ 0, 6 }), +// Edge({ 0, 6 }), +// Edge({ 0, 6 }), +// Edge({ 0, 6 }) }); +// EXPECT_EQ(expected_group0, round.polynomials.groups[0]); +// ASSERT_FALSE(round.failed); +// EXPECT_EQ(round.round_size, 1); +// } + +// TEST(sumcheck, round_from_pointers) +// { +// // arithmetic constraint G is deegree 3 in 8 variables +// // G(Y1, ..., Y8) = Y4Y1Y2 + Y5Y1 + Y6Y2 + Y7Y3 + Y8 +// const size_t num_polys(MULTIVARIATE::COUNT); +// const size_t multivariate_d(2); +// const size_t multivariate_n(1 << multivariate_d); +// const size_t constraint_degree_plus_one = 5; + +// using Fr = barretenberg::fr; +// using Edge = Edge; +// using EdgeGroup = EdgeGroup; +// using Multivariates = Multivariates; +// using ChallengeContainer = ChallengeContainer, Univariate>; + +// class SumcheckTypes { +// public: +// using Fr = Fr; +// using EdgeGroup = EdgeGroup; +// using Multivariates = Multivariates; +// using ChallengeContainer = ChallengeContainer; +// using Univariate = Univariate; +// }; + +// Fr w_l[4] = { 1, 2, 7, 8 }; +// Fr w_r[4] = { 1, 2, 7, 8 }; +// Fr w_o[4] = { 1, 2, 7, 8 }; +// Fr q_l[4] = { 1, 2, 7, 8 }; +// Fr q_m[4] = { 1, 2, 7, 8 }; +// Fr q_r[4] = { 1, 2, 7, 8 }; +// Fr q_o[4] = { 1, 2, 7, 8 }; +// Fr q_c[4] = { 1, 2, 7, 8 }; + +// std::array input_polys = { w_l, w_r, w_o, q_l, q_m, q_r, q_o, q_c }; + +// auto polynomials = Multivariates(input_polys); +// auto constraints = std::make_tuple(ArithmeticConstraint()); +// auto transcript = MockTranscript(); // actually a shared pointer to a transcript? +// auto challenges = ChallengeContainer(transcript); + +// auto round = SumcheckRound(polynomials, constraints, challenges); +// // The values of the univariate restriction S2 created in the first round +// // are the sum of a contribution form group0 and a contribution from group1. +// // Using Sage; +// // group0 contributes: [5, 22, 57, 116] +// // group1 contributes: [497, 712, 981, 1310] +// // Therefore the values of S2 on {0, 1, 2, 3} are: [502, 734, 1038, 1426] +// // and S2(0) + S2(1) = 502 + 734 = 1236 +// round.target_total_sum = 1236; +// EXPECT_EQ(round.round_size, 2); +// /* +// Folding with u2 = -1 +// 2 -------- 8 +// | | +// | Yi | +// | i=1...8 | +// 1 -------- 7 ~~> 0 -------- 6 +// (2(1-X1)+8X1) X2 0(1-X1)+6X1 +// +(1(1-X1)+7X1)(1-X2) +// */ +// round.execute(); +// // EdgeGroup expected_group0({ Edge({ 0, 6 }), +// // Edge({ 0, 6 }), +// // Edge({ 0, 6 }), +// // Edge({ 0, 6 }), +// // Edge({ 0, 6 }), +// // Edge({ 0, 6 }), +// // Edge({ 0, 6 }), +// // Edge({ 0, 6 }) }); +// // EXPECT_EQ(expected_group0, round.polynomials.groups[0]); +// // ASSERT_FALSE(round.failed); +// // EXPECT_EQ(round.round_size, 1); +// } +} // namespace test_sumcheck_round diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/arithmetic_constraint.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/arithmetic_constraint.hpp new file mode 100644 index 000000000000..002160b03d30 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/arithmetic_constraint.hpp @@ -0,0 +1,71 @@ +#include +#include +#include +#include "./constraint.hpp" +#include "./multivariates.hpp" +#include "./barycentric_data.hpp" +#include "./univariate.hpp" +#include "./challenge_container.hpp" +#include "../transcript.hpp" +#include +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +namespace honk { +namespace sumcheck { + +template class ArithmeticConstraint : public Constraint { + public: + static constexpr size_t CONSTRAINT_LENGTH = 4; // degree of this constraint + 1 + using Constraint::HONK_CONSTRAINT_LENGTH; + using Constraint::NUM_HONK_MULTIVARIATES; + // Will be used after adding all edge contributions to extend + // FUTURE OPTIMIZATION: successively extend as needed? + BarycentricData barycentric = + BarycentricData(); + + using UnivariateClass = Univariate; + + // using UnivariateView = UnivariateView; + + ArithmeticConstraint() = default; + + // TODO: optimize! Karatsuba in general, at least for some degrees? + // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both + void add_edge_contribution(auto edge_extensions, Univariate& evals) + { + auto w_l = UnivariateView(edge_extensions[MULTIVARIATE::W_L]); + auto w_r = UnivariateView(edge_extensions[MULTIVARIATE::W_R]); + auto w_o = UnivariateView(edge_extensions[MULTIVARIATE::W_O]); + auto q_m = UnivariateView(edge_extensions[MULTIVARIATE::Q_M]); + auto q_l = UnivariateView(edge_extensions[MULTIVARIATE::Q_L]); + auto q_r = UnivariateView(edge_extensions[MULTIVARIATE::Q_R]); + auto q_o = UnivariateView(edge_extensions[MULTIVARIATE::Q_O]); + auto q_c = UnivariateView(edge_extensions[MULTIVARIATE::Q_C]); + + evals += w_l * (q_m * w_r + q_l); + evals += q_r * w_r; + evals += q_o * w_o; + evals += q_c; + }; + + void add_full_constraint_value_contribution(std::array purported_evaluations, + Fr& full_honk_constraint_value) + { + + auto w_l = purported_evaluations[MULTIVARIATE::W_L]; + auto w_r = purported_evaluations[MULTIVARIATE::W_R]; + auto w_o = purported_evaluations[MULTIVARIATE::W_O]; + auto q_m = purported_evaluations[MULTIVARIATE::Q_M]; + auto q_l = purported_evaluations[MULTIVARIATE::Q_L]; + auto q_r = purported_evaluations[MULTIVARIATE::Q_R]; + auto q_o = purported_evaluations[MULTIVARIATE::Q_O]; + auto q_c = purported_evaluations[MULTIVARIATE::Q_C]; + full_honk_constraint_value += w_l * (q_m * w_r + q_l); + full_honk_constraint_value += q_r * w_r; + full_honk_constraint_value += q_o * w_o; + full_honk_constraint_value += q_c; + }; +}; +} // namespace sumcheck +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/barycentric_data.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/barycentric_data.hpp new file mode 100644 index 000000000000..1dad6b20a82f --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/barycentric_data.hpp @@ -0,0 +1,145 @@ +#pragma once +#include +#include +#include +#include "univariate.hpp" + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +namespace honk { +namespace sumcheck { + +/** + * NOTE: We should definitely consider question of optimal choice of domain, but if decide on {0,1,...,t-1} then we can + * simplify the implementation a bit. + */ +template class BarycentricData { + public: + static constexpr size_t big_domain_size = std::max(domain_size, num_evals); + // TODO: these should be static, also constexpr, but arrays are not constexpr + std::array big_domain; + std::array lagrange_denominators; + std::array precomputed_denominator_inverses; + std::array full_numerator_values; + + constexpr BarycentricData() + { + // build big_domain, currently the set of x_i in {0, 1, ..., t-1} + for (size_t i = 0; i != big_domain_size; ++i) { + big_domain[i] = i; + } + + // build set of lagrange_denominators d_i = \prod_{j!=i} x_i - x_j + for (size_t i = 0; i != domain_size; ++i) { + lagrange_denominators[i] = 1; + for (size_t j = 0; j != domain_size; ++j) { + if (j != i) { + lagrange_denominators[i] *= big_domain[i] - big_domain[j]; + } + } + } + + // for each x_k in the big domain, build set of domain size-many denominator inverses + // 1/(d_i*(x_k - x_j)). will multiply against each of these (rather than to divide by something) + // for each barycentric evaluation + for (size_t k = domain_size; k != num_evals; ++k) { + for (size_t j = 0; j != domain_size; ++j) { + Fr inv = lagrange_denominators[j]; + inv *= (big_domain[k] - big_domain[j]); + inv = Fr(1) / inv; // prob have self_inverse method; should be part of Field concept + precomputed_denominator_inverses[k * domain_size + j] = inv; + } + } + + // get full numerator values + // full numerator is M(x) = \prod_{i} (x-x_i) + // these will be zero for i < domain_size, but that's ok because + // at such entries we will already have the evaluations of the polynomial + for (size_t i = 0; i != num_evals; ++i) { + full_numerator_values[i] = 1; + Fr v_i = i; + for (size_t j = 0; j != domain_size; ++j) { + full_numerator_values[i] *= v_i - big_domain[j]; + } + } + } + + /** + * @brief Given A univariate f represented by {f(0), ..., f(t-1)}, compute {f(t), ..., f(u-1)} + * and return the Univariate represented by {f(0), ..., f(u-1)}. + * + * @details Write v_i = f(x_i) on a the domain {x_0, ..., x_{t-1}}. To efficiently compute the needed values of f, + * we use the barycentric formula + * - f(x) = B(x) Σ_{i=0}^{t-1} v_i / (d_i*(x-x_i)) + * where + * - B(x) = Π_{i=0}^{t-1} (x-x_i) + * - d_i = Π_{j ∈ {0, ..., t-1}, j≠i} (x_i-x_j) for i ∈ {0, ..., t-1} + * + * NOTE: just taking x_i = i for now and possibly forever. Hence can significantly optimize: + * extending an Edge f = v0(1-X) + v1X to a new value involves just one addition and a subtraction: + * setting Δ = v1-v0, the values of f(X) are + * f(0)=v0, f(1)= v0 + Δ, v2 = f(1) + Δ, v3 = f(2) + Δ... + * + */ + Univariate extend(Univariate f) + { + // ASSERT(u>t); + Univariate result; + + for (size_t k = 0; k != domain_size; ++k) { + result.value_at(k) = f.value_at(k); + } + + for (size_t k = domain_size; k != num_evals; ++k) { + result.value_at(k) = 0; + // compute each term v_j / (d_j*(x-x_j)) of the sum + for (size_t j = 0; j != domain_size; ++j) { + Fr term = f.value_at(j); + term *= precomputed_denominator_inverses[domain_size * k + j]; + result.value_at(k) += term; + } + // scale the sum by the the value of of B(x) + result.value_at(k) *= full_numerator_values[k]; + } + return result; + } + + /** + * @brief Evaluate a univariate at a point u not known at compile time + * and assumed not to be in the domain (else we divide by zero). + * @param f + * @return Fr + */ + Fr evaluate(Univariate& f, const Fr& u) + { + + Fr full_numerator_value = 1; + for (size_t i = 0; i != domain_size; ++i) { + full_numerator_value *= u - i; + } + + // build set of domain size-many denominator inverses 1/(d_i*(x_k - x_j)). will multiply against each of + // these (rather than to divide by something) for each barycentric evaluation + std::array denominator_inverses; + for (size_t i = 0; i != domain_size; ++i) { + Fr inv = lagrange_denominators[i]; + inv *= u - big_domain[i]; // warning: need to avoid zero here + inv = Fr(1) / inv; + denominator_inverses[i] = inv; + } + + Fr result = 0; + // compute each term v_j / (d_j*(x-x_j)) of the sum + for (size_t i = 0; i != domain_size; ++i) { + Fr term = f.value_at(i); + term *= denominator_inverses[i]; + result += term; + } + // scale the sum by the the value of of B(x) + result *= full_numerator_value; + return result; + }; +}; +} // namespace sumcheck +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/challenge_container.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/challenge_container.hpp new file mode 100644 index 000000000000..f0d6d86e5697 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/challenge_container.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include "../transcript.hpp" + +namespace honk { +namespace sumcheck { +template class ChallengeContainer { + public: + Fr get_constraint_separator_challenge() { return transcript.get_challenge(); }; // these are powers of a challenge + // Fr get_constraint_bliding_base(){return transcript.get_challenge(1);} // will get element zeta as well + + Transcript transcript; // TODO(cody):really a pointer to such a thing? + ChallengeContainer(Transcript transcript) + : transcript(transcript){}; + Fr get_sumcheck_round_challenge(Univariate univariate_restriction) + { + return transcript.get_challenge(); + }; // this is u_l + + Fr get_challenge_equals_one() { return transcript.get_challenge_equals_one(); }; +}; +} // namespace sumcheck +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint.hpp new file mode 100644 index 000000000000..042df2b0a791 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint.hpp @@ -0,0 +1,16 @@ +#pragma once +#include +#include +#include +#include "./multivariates.hpp" +// #include "honk/sumcheck/sumcheck_types/univariate.hpp" + +namespace honk::sumcheck { + +template class Constraint { + public: + static const size_t HONK_CONSTRAINT_LENGTH = 5; // TODO(luke): move to something more global + static constexpr size_t NUM_HONK_MULTIVARIATES = MULTIVARIATE::COUNT; +}; + +} // namespace honk::sumcheck diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint.test.cpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint.test.cpp new file mode 100644 index 000000000000..c992d01232a6 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint.test.cpp @@ -0,0 +1,198 @@ +#include "./constraint.hpp" +#include "./arithmetic_constraint.hpp" +#include "./grand_product_initialization_constraint.hpp" +#include "./grand_product_computation_constraint.hpp" +#include "./multivariates.hpp" +#include "./univariate.hpp" +#include "./challenge_container.hpp" +#include +#include +#include "../transcript.hpp" + +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +using namespace honk::sumcheck; + +namespace honk { +namespace sumcheck { + +// template class MockTranscript : public Transcript { +// public: +// Fr get_challenge() { return mock_challenge; }; +// Fr mock_challenge = -1; +// }; + +// field is named Fscalar here because of clash with the Fr expected to be +// part of ConstraintTypes. Got impatient; should find better way +template class sumcheck_constraint : public testing::Test { + template using Univariate = Univariate; + template using UnivariateView = UnivariateView; + // template using ChallengeContainer = ChallengeContainer, Univariate>; + + template class ExampleConstraintTypes { + public: + using Fr = Fscalar; + // using Univariate = Univariate; + // using ChallengeContainer = ChallengeContainer; + }; + + // TODO(luke): may want to make this more flexible/generic + static std::array, MULTIVARIATE::COUNT> compute_mock_edge_extensions() + { + // TODO(cody): build from Univariate<2>'s? + auto w_l = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto w_r = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto w_o = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto z_perm = Univariate<5>({ 1, 2, 3, 4, 5 }); + // Note: z_perm_shift can be any linear poly for the sake of the tests but should not be equal to z_perm to + // avoid a trivial computation in the case of the grand_product_computation_constraint + auto z_perm_shift = Univariate<5>({ 2, 1, 0, -1, -2 }); + auto q_m = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto q_l = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto q_r = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto q_o = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto q_c = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto sigma_1 = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto sigma_2 = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto sigma_3 = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto id_1 = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto id_2 = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto id_3 = Univariate<5>({ 1, 2, 3, 4, 5 }); + auto lagrange_1 = Univariate<5>({ 1, 2, 3, 4, 5 }); + + std::array, MULTIVARIATE::COUNT> edge_extensions({ w_l, + w_r, + w_o, + z_perm, + z_perm_shift, + q_m, + q_l, + q_r, + q_o, + q_c, + sigma_1, + sigma_2, + sigma_3, + id_1, + id_2, + id_3, + lagrange_1 }); + return edge_extensions; + } + + public: + static void test_arithmetic_constraint() + { + auto edge_extensions = compute_mock_edge_extensions(); + + auto constraint = ArithmeticConstraint(); + using UnivariateView = UnivariateView; + using Univariate = Univariate; + + // Manually compute the expected edge contribution + auto w_l = UnivariateView(edge_extensions[MULTIVARIATE::W_L]); + auto w_r = UnivariateView(edge_extensions[MULTIVARIATE::W_R]); + auto w_o = UnivariateView(edge_extensions[MULTIVARIATE::W_O]); + auto q_m = UnivariateView(edge_extensions[MULTIVARIATE::Q_M]); + auto q_l = UnivariateView(edge_extensions[MULTIVARIATE::Q_L]); + auto q_r = UnivariateView(edge_extensions[MULTIVARIATE::Q_R]); + auto q_o = UnivariateView(edge_extensions[MULTIVARIATE::Q_O]); + auto q_c = UnivariateView(edge_extensions[MULTIVARIATE::Q_C]); + Univariate expected_evals = (q_m * w_r * w_l) + (q_r * w_r) + (q_l * w_l) + (q_o * w_o) + (q_c); + // Univariate expected_evals{ { 5, 22, 57, 116 } }; + + auto evals = Univariate(); + constraint.add_edge_contribution(edge_extensions, evals); + + EXPECT_EQ(evals, expected_evals); + }; + + static void test_grand_product_computation_constraint() + { + using ChallengeContainer = ChallengeContainer, Univariate<5>>; + + // TODO(luke): Write a test that illustrates the following? + // Note: the below z_perm_shift = X^2 will fail because it results in a constraint of degree 2*1*1*1 = 5 which + // cannot be represented by 5 points. Therefore when we do the calculation then barycentrically extend, we are + // effectively exprapolating a 4th degree polynomial instead of the correct 5th degree poly + // auto z_perm_shift = Univariate<5>({ 1, 4, 9, 16, 25 }); // X^2 + + auto edge_extensions = compute_mock_edge_extensions(); + auto constraint = GrandProductComputationConstraint(); + auto transcript = Transcript(); + auto challenges = ChallengeContainer(transcript); + using UnivariateView = UnivariateView; + using Univariate = Univariate; + + // Manually compute the expected edge contribution + auto w_1 = UnivariateView(edge_extensions[MULTIVARIATE::W_L]); + auto w_2 = UnivariateView(edge_extensions[MULTIVARIATE::W_R]); + auto w_3 = UnivariateView(edge_extensions[MULTIVARIATE::W_O]); + auto sigma_1 = UnivariateView(edge_extensions[MULTIVARIATE::SIGMA_1]); + auto sigma_2 = UnivariateView(edge_extensions[MULTIVARIATE::SIGMA_2]); + auto sigma_3 = UnivariateView(edge_extensions[MULTIVARIATE::SIGMA_3]); + auto id_1 = UnivariateView(edge_extensions[MULTIVARIATE::ID_1]); + auto id_2 = UnivariateView(edge_extensions[MULTIVARIATE::ID_1]); + auto id_3 = UnivariateView(edge_extensions[MULTIVARIATE::ID_1]); + auto z_perm = UnivariateView(edge_extensions[MULTIVARIATE::Z_PERM]); + auto z_perm_shift = UnivariateView(edge_extensions[MULTIVARIATE::Z_PERM_SHIFT]); + // auto lagrange_1 = UnivariateView(edge_extensions[MULTIVARIATE::LAGRANGE_1]); + // TODO(luke): use real transcript/challenges + Fscalar beta = challenges.get_challenge_equals_one(); + Fscalar gamma = challenges.get_challenge_equals_one(); + + auto expected_evals = Univariate(); + expected_evals += + z_perm * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * (w_3 + id_3 * beta + gamma); + expected_evals -= z_perm_shift * (w_1 + sigma_1 * beta + gamma) * (w_2 + sigma_2 * beta + gamma) * + (w_3 + sigma_3 * beta + gamma); + + auto evals = Univariate(); + constraint.add_edge_contribution(edge_extensions, evals, challenges); + + EXPECT_EQ(evals, expected_evals); + }; + + static void test_grand_product_initialization_constraint() + { + auto edge_extensions = compute_mock_edge_extensions(); + auto constraint = GrandProductInitializationConstraint(); + using UnivariateView = UnivariateView; + using Univariate = Univariate; + + // Manually compute the expected edge contribution + auto z_perm = UnivariateView(edge_extensions[MULTIVARIATE::Z_PERM]); + auto lagrange_1 = UnivariateView(edge_extensions[MULTIVARIATE::LAGRANGE_1]); + auto expected_evals = lagrange_1 * (z_perm - Fscalar(1)); + + // Compute the edge contribution using add_edge_contribution + auto evals = Univariate(); + constraint.add_edge_contribution(edge_extensions, evals); + + EXPECT_EQ(evals, expected_evals); + }; +}; + +typedef testing::Types FieldTypes; +TYPED_TEST_SUITE(sumcheck_constraint, FieldTypes); + +TYPED_TEST(sumcheck_constraint, arithmetic_constraint) +{ + TestFixture::test_arithmetic_constraint(); +} + +TYPED_TEST(sumcheck_constraint, grand_product_computation_constraint) +{ + TestFixture::test_grand_product_computation_constraint(); +} + +TYPED_TEST(sumcheck_constraint, grand_product_initialization_constraint) +{ + TestFixture::test_grand_product_initialization_constraint(); +} +} // namespace sumcheck +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint_manager.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint_manager.hpp new file mode 100644 index 000000000000..a6029a159d9a --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint_manager.hpp @@ -0,0 +1,25 @@ +#pragma once +#include +#include +#include +#include "barycentric_data.hpp" +#include "univariate.hpp" + +namespace honk::sumcheck { + +template class ConstraintManager { + // template class ConstraintManager { + public: + static constexpr size_t NUM_CONSTRAINTS = sizeof...(Constraints); + // TODO(cody): const correctness + std::tuple constraints; + std::tuple univariate_accumulators; + // TODO(cody): make barycentric stuff static and put in here, rather than constraints? + // First need to figure out how max length (determined by flavour) is supplied. + // static constexpr auto barycentric_data = + // std::tuple(BarycentricData()...) + ConstraintManager() + : constraints(Constraints()...) + , univariate_accumulators(typename Constraints::UnivariateClass()...){}; +}; +} // namespace honk::sumcheck \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint_manager.test.cpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint_manager.test.cpp new file mode 100644 index 000000000000..f91d343a2b73 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/constraint_manager.test.cpp @@ -0,0 +1,43 @@ +#include "./constraint_manager.hpp" +#include "./arithmetic_constraint.hpp" +#include "./grand_product_computation_constraint.hpp" +#include "./grand_product_initialization_constraint.hpp" +#include "./multivariates.hpp" +#include "./univariate.hpp" +#include "./challenge_container.hpp" +#include +#include +#include "../transcript.hpp" + +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +using namespace honk::sumcheck; + +namespace honk { +namespace sumcheck { + +template class ConstraintManagerTests : public testing::Test {}; + +typedef testing::Types FieldTypes; +TYPED_TEST_SUITE(ConstraintManagerTests, FieldTypes); + +TYPED_TEST(ConstraintManagerTests, Constructor) +{ + using Field = TypeParam; + using ArithmeticConstraint = ArithmeticConstraint; + using GrandProductComputationConstraint = GrandProductComputationConstraint; + using GrandProductInitializationConstraint = GrandProductInitializationConstraint; + using ConstraintManager = ConstraintManager; + auto constraint_manager = ConstraintManager(); + EXPECT_EQ(std::get<0>(constraint_manager.constraints).CONSTRAINT_LENGTH, 4); + EXPECT_EQ(std::get<1>(constraint_manager.constraints).CONSTRAINT_LENGTH, 5); + EXPECT_EQ(std::get<2>(constraint_manager.constraints).CONSTRAINT_LENGTH, 3); +} +} // namespace sumcheck +} // namespace honk \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/grand_product_computation_constraint.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/grand_product_computation_constraint.hpp new file mode 100644 index 000000000000..8e1baa68984a --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/grand_product_computation_constraint.hpp @@ -0,0 +1,214 @@ +#include "./constraint.hpp" +#include "./multivariates.hpp" +#include "./univariate.hpp" +#include "./barycentric_data.hpp" +#include "./challenge_container.hpp" + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +namespace honk::sumcheck { + +template class GrandProductComputationConstraint : public Constraint { + public: + static constexpr size_t CONSTRAINT_LENGTH = 5; // degree of this constraint + 1 + using Constraint::HONK_CONSTRAINT_LENGTH; + using Constraint::NUM_HONK_MULTIVARIATES; + BarycentricData barycentric = + BarycentricData(); + using UnivariateClass = Univariate; // TODO(cody): ugly name temporary for gcc + // using UnivariateView = UnivariateView; + + // using ChallengeContainer = ChallengeContainer, UnivariateClass>; + + public: + GrandProductComputationConstraint() = default; + + /** + * @brief Add contribution of the permutation constraint for a given edge + * + * @detail There are 2 constraints associated with enforcing the wire copy constraints + * This file handles the constraint that confirms faithful calculation of the grand + * product polynomial Z_perm. (Initialization constraint Z_perm(0) = 1 is handled elsewhere). + * + * z_perm(X)*P(X) - z_perm_shift(X)*Q(X), where + * P(X) = Prod_{i=1:3} w_i(X) + β*(n*(i-1) + idx(X)) + γ + * Q(X) = Prod_{i=1:3} w_i(X) + β*σ_i(X) + γ + * + */ + void add_edge_contribution(auto& edge_extensions, + UnivariateClass& evals, + ChallengeContainer, UnivariateClass> challenge_container) + { + Fr beta = challenge_container.get_challenge_equals_one(); // Fr(1) + Fr gamma = challenge_container.get_challenge_equals_one(); // Fr(1) + + auto w_1 = UnivariateView(edge_extensions[MULTIVARIATE::W_L]); + auto w_2 = UnivariateView(edge_extensions[MULTIVARIATE::W_R]); + auto w_3 = UnivariateView(edge_extensions[MULTIVARIATE::W_O]); + auto sigma_1 = UnivariateView(edge_extensions[MULTIVARIATE::SIGMA_1]); + auto sigma_2 = UnivariateView(edge_extensions[MULTIVARIATE::SIGMA_2]); + auto sigma_3 = UnivariateView(edge_extensions[MULTIVARIATE::SIGMA_3]); + auto id_1 = UnivariateView(edge_extensions[MULTIVARIATE::ID_1]); + auto id_2 = UnivariateView(edge_extensions[MULTIVARIATE::ID_1]); + auto id_3 = UnivariateView(edge_extensions[MULTIVARIATE::ID_1]); + auto z_perm = UnivariateView(edge_extensions[MULTIVARIATE::Z_PERM]); + auto z_perm_shift = UnivariateView(edge_extensions[MULTIVARIATE::Z_PERM_SHIFT]); + // auto lagrange_1 = UnivariateView(edge_extensions[MULTIVARIATE::LAGRANGE_1]); + + // Contribution (1) + evals += z_perm; + evals *= w_1 + id_1 * beta + gamma; + evals *= w_2 + id_2 * beta + gamma; + evals *= w_3 + id_3 * beta + gamma; + evals -= z_perm_shift * (w_1 + sigma_1 * beta + gamma) * (w_2 + sigma_2 * beta + gamma) * + (w_3 + sigma_3 * beta + gamma); + }; + + void add_full_constraint_value_contribution(std::array purported_evaluations, + Fr& full_honk_constraint_value) + { + Fr beta = 1; // to be obtained from transcript + Fr gamma = 1; + + auto w_1 = purported_evaluations[MULTIVARIATE::W_L]; + auto w_2 = purported_evaluations[MULTIVARIATE::W_R]; + auto w_3 = purported_evaluations[MULTIVARIATE::W_O]; + auto sigma_1 = purported_evaluations[MULTIVARIATE::SIGMA_1]; + auto sigma_2 = purported_evaluations[MULTIVARIATE::SIGMA_2]; + auto sigma_3 = purported_evaluations[MULTIVARIATE::SIGMA_3]; + auto id_1 = purported_evaluations[MULTIVARIATE::ID_1]; + auto id_2 = purported_evaluations[MULTIVARIATE::ID_1]; + auto id_3 = purported_evaluations[MULTIVARIATE::ID_1]; + auto z_perm = purported_evaluations[MULTIVARIATE::Z_PERM]; + auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; + auto lagrange_1 = purported_evaluations[MULTIVARIATE::LAGRANGE_1]; + + // Contribution (1) + full_honk_constraint_value += z_perm; + full_honk_constraint_value *= w_1 + beta * id_1 + gamma; + full_honk_constraint_value *= w_2 + beta * id_2 + gamma; + full_honk_constraint_value *= w_3 + beta * id_3 + gamma; + full_honk_constraint_value -= z_perm_shift * (w_1 + beta * sigma_1 + gamma) * (w_2 + beta * sigma_2 + gamma) * + (w_3 + beta * sigma_3 + gamma); + }; + + /* ********* ********* ********* ********* ********* ********* ********* ********* ********* ********* */ + + // TODO(luke): This function probably doesn't belong in this class. It could be moved to e.g. the composer + /** + * @brief Compute the permutation grand product polynomial Z_perm(X) + * * + * @detail (This description assumes program_width 3). Z_perm may be defined in terms of its values + * on X_i = 0,1,...,n-1 as Z_perm[0] = 1 and for i = 1:n-1 + * + * (w_1(j) + β⋅id_1(j) + γ) ⋅ (w_2(j) + β⋅id_2(j) + γ) ⋅ (w_3(j) + β⋅id_3(j) + γ) + * Z_perm[i] = ∏ -------------------------------------------------------------------------------- + * (w_1(j) + β⋅σ_1(j) + γ) ⋅ (w_2(j) + β⋅σ_2(j) + γ) ⋅ (w_3(j) + β⋅σ_3(j) + γ) + * + * where ∏ := ∏_{j=0:i-1} and id_i(X) = id(X) + n*(i-1). These evaluations are constructed over the + * course of three steps. For expositional simplicity, write Z_perm[i] as + * + * A_1(j) ⋅ A_2(j) ⋅ A_3(j) + * Z_perm[i] = ∏ -------------------------- + * B_1(j) ⋅ B_2(j) ⋅ B_3(j) + * + * Step 1) Compute the 2*program_width length-n polynomials A_i and B_i + * Step 2) Compute the 2*program_width length-n polynomials ∏ A_i(j) and ∏ B_i(j) + * Step 3) Compute the two length-n polynomials defined by + * numer[i] = ∏ A_1(j)⋅A_2(j)⋅A_3(j), and denom[i] = ∏ B_1(j)⋅B_2(j)⋅B_3(j) + * Step 4) Compute Z_perm[i+1] = numer[i]/denom[i] (recall: Z_perm[0] = 1) + * + * Note: Step (4) utilizes Montgomery batch inversion to replace n-many inversions with + * one batch inversion (at the expense of more multiplications) + */ + // template + void compute_grand_product_polynomial_z(/*transcript::StandardTranscript& transcript*/) + { + const size_t program_width = 3; // eventually a template param? + size_t key_n = 100; // temp placeholder to get things building + + // Allocate scratch space for accumulators + Fr* numererator_accum[program_width]; + Fr* denominator_accum[program_width]; + for (size_t i = 0; i < program_width; ++i) { + numererator_accum[i] = static_cast(aligned_alloc(64, sizeof(Fr) * key_n)); + denominator_accum[i] = static_cast(aligned_alloc(64, sizeof(Fr) * key_n)); + } + + // Popoulate wire and permutation polynomials + std::array wires; + std::array sigmas; + for (size_t i = 0; i < program_width; ++i) { + std::string wire_id = "w_" + std::to_string(i + 1) + "_lagrange"; + std::string sigma_id = "sigma_" + std::to_string(i + 1) + "_lagrange"; + // wires[i] = key->polynomial_cache.get(wire_id).get_coefficients(); + // sigmas[i] = key->polynomial_cache.get(sigma_id).get_coefficients(); + } + + // Get random challenges (to be obtained from transcript) + Fr beta = Fr::random_element(); + Fr gamma = Fr::random_element(); + + // Step (1) + for (size_t i = 0; i < key_n; ++i) { + for (size_t k = 0; k < program_width; ++k) { + // TODO(luke): maybe this idx is replaced by proper ID polys in the future + Fr idx = k * key_n + i; + numererator_accum[k][i] = wires[k][i] + (idx * beta) + gamma; // w_k(i) + β.(k*n+i) + γ + denominator_accum[k][i] = wires[k][i] + (sigmas[k][i] * beta) + gamma; // w_k(i) + β.σ_k(i) + γ + } + } + + // Step (2) + for (size_t k = 0; k < program_width; ++k) { + for (size_t i = 0; i < key_n - 1; ++i) { + numererator_accum[k][i + 1] *= numererator_accum[k][i]; + denominator_accum[k][i + 1] *= denominator_accum[k][i]; + } + } + + // Step (3) + for (size_t i = 0; i < key_n; ++i) { + for (size_t k = 1; k < program_width; ++k) { + numererator_accum[0][i] *= numererator_accum[k][i]; + denominator_accum[0][i] *= denominator_accum[k][i]; + } + } + + // Step (4) + // Use Montgomery batch inversion to compute z_perm[i+1] = numererator_accum[0][i] / denominator_accum[0][i] + Fr* inversion_coefficients = &denominator_accum[1][0]; // arbitrary scratch space + Fr inversion_accumulator = Fr::one(); + for (size_t i = 0; i < key_n; ++i) { + inversion_coefficients[i] = numererator_accum[0][i] * inversion_accumulator; + inversion_accumulator *= denominator_accum[0][i]; + } + + inversion_accumulator = inversion_accumulator.invert(); // perform single inversion per thread + for (size_t i = key_n - 1; i != -1; --i) { + // TODO(luke): What needs to be done Re the comment below: + // We can avoid fully reducing z_perm[i + 1] as the inverse fft will take care of that for us + numererator_accum[0][i] = inversion_accumulator * inversion_coefficients[i]; + inversion_accumulator *= denominator_accum[0][i]; + } + + // Construct permutation polynomial 'z_perm' in lagrange form as: + // z_perm = [1 numererator_accum[0][0] numererator_accum[0][1] ... numererator_accum[0][n-2]] + // polynomial z_perm(key_n, key_n); + // z_perm[0] = Fr::one(); + // barretenberg::polynomial_arithmetic::copy_polynomial(numererator_accum[0], &z_perm[1], key_n - 1, key_n - + // 1); + + // free memory allocated for scratch space + for (size_t k = 0; k < program_width; ++k) { + aligned_free(numererator_accum[k]); + aligned_free(denominator_accum[k]); + } + + // TODO(luke): Commit to z here? + + // key->polynomial_cache.put("z_perm", std::move(z_perm)); + } +}; +} // namespace honk::sumcheck diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/grand_product_initialization_constraint.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/grand_product_initialization_constraint.hpp new file mode 100644 index 000000000000..45d79e8ed73d --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/grand_product_initialization_constraint.hpp @@ -0,0 +1,51 @@ +#include "./constraint.hpp" +#include "./multivariates.hpp" +#include "./univariate.hpp" +#include "./barycentric_data.hpp" + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +namespace honk::sumcheck { + +template class GrandProductInitializationConstraint : public Constraint { + public: + static constexpr size_t CONSTRAINT_LENGTH = 3; // degree of this constraint + 1 + using Constraint::HONK_CONSTRAINT_LENGTH; + using Constraint::NUM_HONK_MULTIVARIATES; + BarycentricData barycentric = + BarycentricData(); + using UnivariateClass = Univariate; + // using UnivariateView = UnivariateView; + + public: + GrandProductInitializationConstraint() = default; + + /** + * @brief Add contribution of the permutation constraint for a given edge + * + * @detail There are 2 constraints associated with enforcing the wire copy constraints + * This file handles the constraint Z_perm(0) = 1 via the constraint: + * + * C(X) = L_1(X)(z_perm(X) - 1) + */ + void add_edge_contribution(auto& edge_extensions, UnivariateClass& evals) + { + auto z_perm = UnivariateView(edge_extensions[MULTIVARIATE::Z_PERM]); + auto lagrange_1 = UnivariateView(edge_extensions[MULTIVARIATE::LAGRANGE_1]); + auto one = Fr(1); + + evals += lagrange_1 * (z_perm - one); + }; + + void add_full_constraint_value_contribution(std::array purported_evaluations, + Fr& full_honk_constraint_value) + { + auto z_perm = purported_evaluations[MULTIVARIATE::Z_PERM]; + auto lagrange_1 = purported_evaluations[MULTIVARIATE::LAGRANGE_1]; + auto one = Fr(1); + + full_honk_constraint_value += lagrange_1 * (z_perm - one); + }; +}; +} // namespace honk::sumcheck diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/multivariates.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/multivariates.hpp new file mode 100644 index 000000000000..cc5153caf635 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/multivariates.hpp @@ -0,0 +1,134 @@ +#pragma once // just adding these willy-nilly +#include // just added to get info() + +namespace honk { +// starting with arithmetic and permutation constraints +// Note: including Z_PERM_SHIFT here is probably not the right thing long term but +// doing it for now for convenience +enum MULTIVARIATE { + W_L, + W_R, + W_O, + Z_PERM, + Z_PERM_SHIFT, + Q_M, + Q_L, + Q_R, + Q_O, + Q_C, + SIGMA_1, + SIGMA_2, + SIGMA_3, + ID_1, + ID_2, + ID_3, + LAGRANGE_1, + COUNT +}; +static constexpr size_t NUM_MULTIVARIATES = MULTIVARIATE::COUNT; + +namespace sumcheck { +/** + * + * @brief A container for all of the Honk! polynomials (e.g., wire and selector polynomials). + * These polynomials all low-degree extensions over H^d with H = {0, 1} (where d = + * ceil(log(number of gates))), hence they are multilinear polynomials in d variables. As such, it is efficient to store + * these polynomials in terms of univariate degree-1 polynomials. We call such a polynomial an Edge, short for + + ... TODO(cody)rewrite! + + * Suppose now the Honk polynomials (multilinear in d variables) are called P_1, ..., P_N. At initialization, + * we think of these as lying in a two-dimensional array, where each column records the value of one P_i on H^d. In this + * array, each row contains N edge polynomials (an EdgeGroup). Hence the array has shape (n/2, N). After the first + * round, the array will be updated ('folded'), so that the first n/4 rows will represent the evaluations P_i(X1, ..., + * X_{d-1}, u_d) as a low-degree extension on H^{d-1}. + * + * @tparam Fr + * + * NOTE: With ~40 columns, prob only want to allocate 256 EdgeGroup's at once to keep stack under 1MB? + * TODO: might want to just do C-style multidimensional array? for guaranteed adjacency? + * NOTE: got rid of `populate` method--just assuming the EdgeGroup's are constructed at the time that the + * Multivariatess instance is constructed + */ +template class Multivariates { + public: + const static size_t multivariate_d = num_vars; + const static size_t multivariate_n = 1 << num_vars; + static constexpr size_t num = num_polys; + + std::array> 1)>, num_polys> folded_polynomials; + std::array full_polynomials; + + /* For groups, we imagine all of the defining polynomial data in + a matrix like this: + | P_1 | P_2 | P_3 | P_4 | ... | P_N | N = NUM_HONK_POLYS + |-----------------------------------| + group 0 --| * | * | * | * | ... | * | vertex 0 + \-| * | * | * | * | ... | * | vertex 1 + group 1 --| * | * | * | * | ... | * | vertex 2 + \-| * | * | * | * | ... | * | vertex 3 + | * | * | * | * | ... | * | + group m-1 --| * | * | * | * | ... | * | vertex n-2 + \-| * | * | * | * | ... | * | vertex n-1 + m = n/2 + + In practice, we record this value in an n/2 x N matrix groups + where each row is though of as a group of edge polynomials. + + */ + Multivariates() = default; + + Multivariates(std::array full_polynomials) + : full_polynomials(full_polynomials){}; + + /** + * @brief Evaluate at the round challenge and prepare class for next round. + * Illustration of layout in example of first round when d==3 (showing just one Honk polynomial, + * i.e., what happens in just one column of our two-dimensional array): + * + * groups vertex terms collected vertex terms groups after folding + * g0 -- v0 (1-X1)(1-X2)(1-X3) --- (v0(1-X3) + v1 X3) (1-X1)(1-X2) ---- (v0(1-u3) + v1 u3) (1-X1)(1-X2) + * \- v1 (1-X1)(1-X2) X3 --/ --- (v2(1-u3) + v3 u3) (1-X1) X2 + * g1 -- v2 (1-X1) X2 (1-X3) --- (v1(1-X3) + v2 X3) (1-X1) X2 -/ -- (v4(1-u3) + v5 u3) X1 (1-X2) + * \- v3 (1-X1) X2 X3 --/ / - (v6(1-u3) + v7 u3) X1 X2 + * g2 -- v4 X1 (1-X2)(1-X3) --- (v3(1-X3) + v4 X3) X1 (1-X2)-/ / + * \- v5 X1 (1-X2) X3 --/ / + * g3 -- v6 X1 X2 (1-X3) --- (v5(1-X3) + v6 X3) X1 X2 -/ + * \- v7 X1 X2 X3 --/ + * + * TODO: Is it better to avoid copying in the to get the third column? could maybe do by + * just tracking a gap parameter in the for loop, e.g. EDGE_GAP = (1 << i). + * @param challenge + */ + + void fold(size_t round_size, const Fr& challenge) + { + for (size_t j = 0; j < num_polys; ++j) { + for (size_t i = 0; i < round_size; i += 2) { + // old: a0, a1 + // new: (1 - r).a0 + r.a1 + // => r.(a1 - a0) + a0 + folded_polynomials[j][i >> 1] = + folded_polynomials[j][i] + challenge * (folded_polynomials[j][i + 1] - folded_polynomials[j][i]); + } + } + } + + void fold_first_round(size_t round_size, const Fr& challenge) + { + for (size_t j = 0; j < num_polys; ++j) { + for (size_t i = 0; i < round_size; i += 2) { + // old: a0, a1 + // new: (1 - r).a0 + r.a1 + // => r.(a1 - a0) + a0 + folded_polynomials[j][i >> 1] = + full_polynomials[j][i] + challenge * (full_polynomials[j][i + 1] - full_polynomials[j][i]); + } + } + } + + // TODO(cody): Double check edge case here and above. For now, test_fold_1 + // seems to show that the round_size==2 case is handled correctly +}; +} // namespace sumcheck +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/multivariates.test.cpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/multivariates.test.cpp new file mode 100644 index 000000000000..e262b15da570 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/multivariates.test.cpp @@ -0,0 +1,134 @@ +#include "./multivariates.hpp" +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +using namespace honk::sumcheck; +namespace test_sumcheck_polynomials { + +template class sumcheck_polynomials : public testing::Test { + template + using Multivariates = Multivariates; + + public: + static void test_honk_polys_constructors() + { + const size_t num_polys(4); + const size_t multivariate_d(2); + // const size_t multivariate_n(1 << multivariate_d); + + Fr f0[3] = { 0, 0, 1 }; + Fr f1[3] = { 1, 1, 1 }; + Fr f2[3] = { 3, 4, 1 }; + Fr f3[3] = { -1, -1, 1 }; + + auto full_polynomials = std::array({ f0, f1, f2, f3 }); + auto multivariates = Multivariates(full_polynomials); + + EXPECT_EQ(multivariates.full_polynomials, full_polynomials); + } + + // TODO(cody): rewrite this comment + /* + u2 = 1 ~~> + v01 ------ v11 ~~> + | | ~~> + | Y | ~~> + | | ~~> + v00 ------ v10 ~~> v00 * (1-u2) + v01 * u2 -------- (v11 * u2 + v10 * (1-u2)) + (v01 * (1-X1) + v11 * X1) * X2 ~~> (v00 * (1-u2) + v01 * u2) * (1-X1) + + (v00 * (1-X1) + v10 * X1) * (1-X2) ~~> + (v11 * u2 + v10 * (1-u2)) * X1 + */ + static void test_fold_two() + { + const size_t num_polys(2); + const size_t multivariate_d(1); + const size_t multivariate_n(1 << multivariate_d); + + Fr v00 = Fr::random_element(); + Fr v01 = Fr::random_element(); + Fr v10 = Fr::random_element(); + Fr v11 = Fr::random_element(); + + Fr f0[2] = { v00, v10 }; + Fr f1[2] = { v01, v11 }; + + auto full_polynomials = std::array({ f0, f1 }); + auto multivariates = Multivariates(full_polynomials); + + Fr u2 = Fr::random_element(); + Fr expected_lo = v00 * (Fr(1) - u2) + v10 * u2; + Fr expected_hi = v11 * u2 + v01 * (Fr(1) - u2); + + multivariates.fold_first_round(2, u2); + + EXPECT_EQ(multivariates.folded_polynomials[0][0], expected_lo); + EXPECT_EQ(multivariates.folded_polynomials[1][0], expected_hi); + + Fr u1 = Fr::random_element(); + Fr expected_val = expected_lo * (Fr(1) - u1) + expected_hi * u1; + + multivariates.fold(multivariate_n >> 1, u1); + // Seems the edge case is handled correctly? + EXPECT_EQ(multivariates.folded_polynomials[0][0], expected_val); + } + + // TODO(cody): reinstate this + // /* + // u2 = 1 + // 3 -------- 7 4 -------- 8 ~~> + // | | | | ~~> + // | Y1 | | Y2 | ~~> + // | | | | ~~> + // 1 -------- 5 2 -------- 6 ~~> 3 -------- 7 4 -------- 8 + // (3(1-X1)+7X1) X2 (4(1-X1)+8X1) X2 3(1-X1)+7X1 4(1-X1)+8X1 + // +(1(1-X1)+5X1)(1-X2) +(2(1-X1)+6X1)(1-X2) + // */ + // static void test_fold_2() + // { + // const size_t num_polys(2); + // const size_t multivariate_d(2); + // const size_t multivariate_n(1 << multivariate_d); + + // Edge Y11 = Edge({ 1, 3 }); + // Edge Y12 = Edge({ 5, 7 }); + // Edge Y21 = Edge({ 2, 4 }); + // Edge Y22 = Edge({ 6, 8 }); + + // auto group_1 = EdgeGroup({ Y11, Y21 }); + // auto group_2 = EdgeGroup({ Y12, Y22 }); + + // std::array, multivariate_d> groups{ group_1, group_2 }; + // auto polys = Multivariates(groups); + + // Fr u2 = 1; + // polys.fold(n, u2); + + // EXPECT_EQ(polys.groups[0][0].at(0), 3); + // EXPECT_EQ(polys.groups[0][0].at(1), 7); + + // EXPECT_EQ(polys.groups[0][1].at(0), 4); + // EXPECT_EQ(polys.groups[0][1].at(1), 8); + // } +}; + +typedef testing::Types FieldTypes; +TYPED_TEST_SUITE(sumcheck_polynomials, FieldTypes); + +TYPED_TEST(sumcheck_polynomials, honk_polys_constructor) +{ + TestFixture::test_honk_polys_constructors(); +} +TYPED_TEST(sumcheck_polynomials, fold_2) +{ + TestFixture::test_fold_two(); +} +// TYPED_TEST(sumcheck_polynomials, fold_2) +// { +// TestFixture::test_fold_2(); +// } +} // namespace test_sumcheck_polynomials \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/univariate.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/univariate.hpp new file mode 100644 index 000000000000..9843b92960cb --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/univariate.hpp @@ -0,0 +1,261 @@ +#pragma once +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +namespace honk { +namespace sumcheck { + +template class UnivariateView; + +template class Univariate { + public: + static constexpr size_t LENGTH = _length; + + std::array evaluations; + + Univariate() = default; + + explicit Univariate(std::array evaluations) + : evaluations(evaluations) + {} + Univariate(const Univariate& other) + : evaluations(other.evaluations) + {} + Univariate(Univariate&& other) noexcept + : evaluations(std::move(other.evaluations)) + {} + + // Construct Univariate from UnivariateView + explicit Univariate(UnivariateView in) + : evaluations({ { 0 } }) + { + for (size_t i = 0; i < in.evaluations.size(); ++i) { + evaluations[i] = in.evaluations[i]; + } + } + + Fr& value_at(size_t i) { return evaluations[i]; }; + + // Operations between Univariate and other Univariate + Univariate operator=(const Univariate& other) + { + evaluations = other.evaluations; + return *this; + } + + Univariate operator=(Univariate&& other) + { + evaluations = std::move(other.evaluations); + return *this; + } + + bool operator==(const Univariate& other) const = default; + + Univariate operator+=(const Univariate& other) + { + for (size_t i = 0; i < _length; ++i) { + evaluations[i] += other.evaluations[i]; + } + return *this; + } + Univariate operator-=(const Univariate& other) + { + for (size_t i = 0; i < _length; ++i) { + evaluations[i] -= other.evaluations[i]; + } + return *this; + } + Univariate operator*=(const Univariate& other) + { + for (size_t i = 0; i < _length; ++i) { + evaluations[i] *= other.evaluations[i]; + } + return *this; + } + Univariate operator+(const Univariate& other) const + { + Univariate res(*this); + res += other; + return res; + } + + Univariate operator-(const Univariate& other) const + { + Univariate res(*this); + res -= other; + return res; + } + Univariate operator*(const Univariate& other) const + { + Univariate res(*this); + res *= other; + return res; + } + + // Operations between Univariate and scalar + Univariate operator+=(const Fr& scalar) + { + for (auto& eval : evaluations) { + eval += scalar; + } + return *this; + } + + Univariate operator-=(const Fr& scalar) + { + for (auto& eval : evaluations) { + eval -= scalar; + } + return *this; + } + Univariate operator*=(const Fr& scalar) + { + for (auto& eval : evaluations) { + eval *= scalar; + } + return *this; + } + + Univariate operator+(const Fr& scalar) + { + Univariate res(*this); + res += scalar; + return res; + } + + Univariate operator-(const Fr& scalar) + { + Univariate res(*this); + res -= scalar; + return res; + } + + Univariate operator*(const Fr& scalar) + { + Univariate res(*this); + res *= scalar; + return res; + } + + // Operations between Univariate and UnivariateView + Univariate operator+=(const UnivariateView& view) + { + for (size_t i = 0; i < _length; ++i) { + evaluations[i] += view.evaluations[i]; + } + return *this; + } + + Univariate operator-=(const UnivariateView& view) + { + for (size_t i = 0; i < _length; ++i) { + evaluations[i] -= view.evaluations[i]; + } + return *this; + } + + Univariate operator*=(const UnivariateView& view) + { + for (size_t i = 0; i < _length; ++i) { + evaluations[i] *= view.evaluations[i]; + } + return *this; + } + + Univariate operator+(const UnivariateView& view) + { + Univariate res(*this); + res += view; + return res; + } + + Univariate operator-(const UnivariateView& view) + { + Univariate res(*this); + res -= view; + return res; + } + + Univariate operator*(const UnivariateView& view) + { + Univariate res(*this); + res *= view; + return res; + } +}; + +template class UnivariateView { + public: + std::span evaluations; + + UnivariateView() = default; + + Fr& value_at(size_t i) { return evaluations[i]; }; + + template + explicit UnivariateView(Univariate univariate_in) + : evaluations(std::span(univariate_in.evaluations.begin(), view_length)){}; + + Univariate operator+(const UnivariateView& other) const + { + Univariate res(*this); + res += other; + return res; + } + + Univariate operator-(const UnivariateView& other) const + { + Univariate res(*this); + res -= other; + return res; + } + + Univariate operator*(const UnivariateView& other) const + { + Univariate res(*this); + res *= other; + return res; + } + + Univariate operator*(const Univariate& other) const + { + Univariate res(*this); + res *= other; + return res; + } + + Univariate operator+(const Univariate& other) const + { + Univariate res(*this); + res += other; + return res; + } + + Univariate operator+(const Fr& other) const + { + Univariate res(*this); + res += other; + return res; + } + + Univariate operator-(const Fr& other) const + { + Univariate res(*this); + res -= other; + return res; + } + + Univariate operator*(const Fr& other) const + { + Univariate res(*this); + res *= other; + return res; + } +}; +} // namespace sumcheck +} // namespace honk diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/univariate.test.cpp b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/univariate.test.cpp new file mode 100644 index 000000000000..ccb2b5c9d655 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/sumcheck_types/univariate.test.cpp @@ -0,0 +1,213 @@ +#include "./barycentric_data.hpp" +#include "./univariate.hpp" +#include +#include +#include +#include +#include + +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + +using namespace honk::sumcheck; +namespace test_univariate { + +template class UnivariateTests : public testing::Test { + template using UnivariateView = UnivariateView; + + template Univariate random_univariate() + { + auto output = Univariate(); + for (size_t i = 0; i != length; ++i) { + output.value_at(i) = Fr::random_element(); + } + return output; + }; + + public: + static void test_constructors() + { + Fr a0 = Fr::random_element(); + Fr a1 = Fr::random_element(); + Fr a2 = Fr::random_element(); + + Univariate uni({ a0, a1, a2 }); + + EXPECT_EQ(uni.value_at(0), a0); + EXPECT_EQ(uni.value_at(1), a1); + EXPECT_EQ(uni.value_at(2), a2); + } + + static void test_addition() + { + Univariate f1{ { 1, 2 } }; + Univariate f2{ { 3, 4 } }; + // output should be {4, 6} + Univariate expected_result{ { 4, 6 } }; + auto f1f2 = f1 + f2; + EXPECT_EQ(f1f2, expected_result); + } + + static void test_barycentric_data() + { + const size_t domain_size = 2; + const size_t num_evals = 3; + auto barycentric = BarycentricData(); + std::array expected_big_domain{ { 0, 1, 2 } }; + std::array expected_denominators{ { -1, 1 } }; + std::array expected_full_numerator_values{ { 0, 0, 2 } }; + EXPECT_EQ(barycentric.big_domain, expected_big_domain); + EXPECT_EQ(barycentric.lagrange_denominators, expected_denominators); + EXPECT_EQ(barycentric.full_numerator_values, expected_full_numerator_values); + + // e1(X) = 1*(1-X) + 2*X = 1 + X + Univariate e1{ { 1, 2 } }; + Fr u = Fr::random_element(); + Fr calculated_val_at_u = barycentric.evaluate(e1, u); + EXPECT_EQ(u + 1, calculated_val_at_u); + + Univariate ext1 = barycentric.extend(e1); + Univariate expected{ { 1, 2, 3 } }; + EXPECT_EQ(ext1, expected); + } + + static void test_barycentric_data_extend() + { + const size_t domain_size = 5; + const size_t num_evals = 6; + auto barycentric = BarycentricData(); + + // Note: we are able to represent a degree 4 polynomial with 5 points thus this + // extension will succeed. It would fail for values on a polynomial of degree > 4. + Univariate e1{ { 1, 3, 25, 109, 321 } }; // X^4 + X^3 + 1 + + Univariate ext1 = barycentric.extend(e1); + + Univariate expected{ { 1, 3, 25, 109, 321, 751 } }; + + EXPECT_EQ(ext1, expected); + } + + static void test_multiplication() + { + auto barycentric = BarycentricData(); + Univariate f1 = barycentric.extend(Univariate{ { 1, 2 } }); + Univariate f2 = barycentric.extend(Univariate{ { 3, 4 } }); + // output should be {3, 8, 15} + Univariate expected_result{ { 3, 8, 15 } }; + Univariate f1f2 = f1 * f2; + EXPECT_EQ(f1f2, expected_result); + } + + static void test_construct_univariate_view_from_univariate() + { + Univariate f{ { 1, 2, 3 } }; + UnivariateView<2> g(f); + EXPECT_EQ(g.value_at(0), f.value_at(0)); + EXPECT_EQ(g.value_at(1), f.value_at(1)); + } + + static void test_construct_univariate_from_univariate_view() + { + Univariate f{ { 1, 2, 3 } }; + UnivariateView<2> g(f); + Univariate h(g); + EXPECT_EQ(h.value_at(0), g.value_at(0)); + EXPECT_EQ(h.value_at(1), g.value_at(1)); + } + + static void test_univariate_view_addition() + { + Univariate f1{ { 1, 2, 3 } }; + Univariate f2{ { 3, 4, 3 } }; + + UnivariateView<2> g1(f1); + UnivariateView<2> g2(f2); + + Univariate expected_result{ { 4, 6 } }; + Univariate result = g1 + g2; + EXPECT_EQ(result, expected_result); + + Univariate result2 = result + g1; + Univariate expected_result2{ { 5, 8 } }; + EXPECT_EQ(result2, expected_result2); + } + static void test_univariate_view_subtraction() + { + Univariate f1{ { 1, 2, 3 } }; + Univariate f2{ { 3, 4, 3 } }; + + UnivariateView<2> g1(f1); + UnivariateView<2> g2(f2); + + Univariate expected_result{ { -2, -2 } }; + Univariate result = g1 - g2; + EXPECT_EQ(result, expected_result); + + Univariate result2 = result - g1; + Univariate expected_result2{ { -3, -4 } }; + EXPECT_EQ(result2, expected_result2); + } + + static void test_univariate_view_multiplication() + { + Univariate f1{ { 1, 2, 3 } }; + Univariate f2{ { 3, 4, 3 } }; + + UnivariateView<2> g1(f1); + UnivariateView<2> g2(f2); + + Univariate expected_result{ { 3, 8 } }; + Univariate result = g1 * g2; + EXPECT_EQ(result, expected_result); + + Univariate result2 = result * g1; + Univariate expected_result2{ { 3, 16 } }; + EXPECT_EQ(result2, expected_result2); + } +}; + +using FieldTypes = testing::Types; +TYPED_TEST_SUITE(UnivariateTests, FieldTypes); + +TYPED_TEST(UnivariateTests, Constructors) +{ + TestFixture::test_constructors(); +} +TYPED_TEST(UnivariateTests, Addition) +{ + TestFixture::test_addition(); +} +TYPED_TEST(UnivariateTests, UnivariateToView) +{ + TestFixture::test_construct_univariate_from_univariate_view(); +} +TYPED_TEST(UnivariateTests, ViewToUnivariate) +{ + TestFixture::test_construct_univariate_view_from_univariate(); +} +TYPED_TEST(UnivariateTests, ViewAddition) +{ + TestFixture::test_univariate_view_addition(); +} +TYPED_TEST(UnivariateTests, ViewMultiplication) +{ + TestFixture::test_univariate_view_subtraction(); +} +TYPED_TEST(UnivariateTests, ViewSubtraction) +{ + TestFixture::test_univariate_view_multiplication(); +} +TYPED_TEST(UnivariateTests, BarycentricData) +{ + TestFixture::test_barycentric_data(); +} +TYPED_TEST(UnivariateTests, BarycentricDataExtend) +{ + TestFixture::test_barycentric_data_extend(); +} +TYPED_TEST(UnivariateTests, Multiplication) +{ + TestFixture::test_multiplication(); +} +} // namespace test_univariate diff --git a/barretenberg/cpp/src/aztec/honk/sumcheck/transcript.hpp b/barretenberg/cpp/src/aztec/honk/sumcheck/transcript.hpp new file mode 100644 index 000000000000..b1158172c3c0 --- /dev/null +++ b/barretenberg/cpp/src/aztec/honk/sumcheck/transcript.hpp @@ -0,0 +1,10 @@ +#pragma once +namespace honk { +template class Transcript { + public: + // Fr add() // data to the transcript + Fr get_challenge() { return Fr::random_element(); }; + Fr get_challenge_equals_one() { return Fr::one(); }; + // std::array<...> data +}; +}; // namespace honk diff --git a/barretenberg/cpp/src/aztec/plonk/CMakeLists.txt b/barretenberg/cpp/src/aztec/plonk/CMakeLists.txt index 26d67ea5f843..a3c26bb16438 100644 --- a/barretenberg/cpp/src/aztec/plonk/CMakeLists.txt +++ b/barretenberg/cpp/src/aztec/plonk/CMakeLists.txt @@ -1 +1 @@ -barretenberg_module(plonk crypto_pedersen polynomials crypto_sha256 ecc crypto_blake3s) \ No newline at end of file +barretenberg_module(plonk proof_system crypto_pedersen polynomials crypto_sha256 ecc crypto_blake3s) \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/plonk/composer/composer_base.cpp b/barretenberg/cpp/src/aztec/plonk/composer/composer_base.cpp index d03b605c4672..7259b8f9611b 100644 --- a/barretenberg/cpp/src/aztec/plonk/composer/composer_base.cpp +++ b/barretenberg/cpp/src/aztec/plonk/composer/composer_base.cpp @@ -1,5 +1,5 @@ #include "composer_base.hpp" -#include +#include #include #include diff --git a/barretenberg/cpp/src/aztec/plonk/composer/standard_composer.test.cpp b/barretenberg/cpp/src/aztec/plonk/composer/standard_composer.test.cpp index 50b92f2ccbb4..9130492af08d 100644 --- a/barretenberg/cpp/src/aztec/plonk/composer/standard_composer.test.cpp +++ b/barretenberg/cpp/src/aztec/plonk/composer/standard_composer.test.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include using namespace barretenberg; diff --git a/barretenberg/cpp/src/aztec/plonk/composer/turbo_composer.test.cpp b/barretenberg/cpp/src/aztec/plonk/composer/turbo_composer.test.cpp index cb1d7dc97f18..0003ab319311 100644 --- a/barretenberg/cpp/src/aztec/plonk/composer/turbo_composer.test.cpp +++ b/barretenberg/cpp/src/aztec/plonk/composer/turbo_composer.test.cpp @@ -1,7 +1,7 @@ #include "turbo_composer.hpp" #include #include -#include +#include using namespace barretenberg; using namespace crypto::pedersen; diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/commitment_scheme/commitment_scheme.hpp b/barretenberg/cpp/src/aztec/plonk/proof_system/commitment_scheme/commitment_scheme.hpp index e5da3710148e..e7bb7f8c8941 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/commitment_scheme/commitment_scheme.hpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/commitment_scheme/commitment_scheme.hpp @@ -1,7 +1,7 @@ #pragma once #include "../../transcript/transcript_wrappers.hpp" #include "../../../polynomials/polynomial_arithmetic.hpp" -#include "../prover/work_queue.hpp" +#include "../../../proof_system/work_queue/work_queue.hpp" #include "../../../polynomials/polynomial.hpp" #include "../types/commitment_open_proof.hpp" #include "../types/program_settings.hpp" diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/commitment_scheme/commitment_scheme.test.cpp b/barretenberg/cpp/src/aztec/plonk/proof_system/commitment_scheme/commitment_scheme.test.cpp index 84bf1bd670b7..03c65d72a50d 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/commitment_scheme/commitment_scheme.test.cpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/commitment_scheme/commitment_scheme.test.cpp @@ -6,7 +6,7 @@ #include #include "./polynomials/polynomial_arithmetic.hpp" #include "./polynomials/polynomial.hpp" -#include "../prover/work_queue.hpp" +#include "../../../proof_system/work_queue/work_queue.hpp" #include "../types/program_settings.hpp" #include "../../composer/composer_base.hpp" #include diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/prover/prover.cpp b/barretenberg/cpp/src/aztec/plonk/proof_system/prover/prover.cpp index 0da77ed3d491..2dfd8ddec23f 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/prover/prover.cpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/prover/prover.cpp @@ -412,7 +412,7 @@ template void ProverBase::execute_fourth_round() size_t widget_counter = 0; for (auto& widget : transition_widgets) { - widget_counter++; + widget_counter = widget_counter + 1; alpha_base = widget->compute_quotient_contribution(alpha_base, transcript); } diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/prover/prover.hpp b/barretenberg/cpp/src/aztec/plonk/proof_system/prover/prover.hpp index da2cbdc66b4a..4233f5a06d02 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/prover/prover.hpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/prover/prover.hpp @@ -1,10 +1,10 @@ #pragma once #include "../../transcript/transcript_wrappers.hpp" -#include "../proving_key/proving_key.hpp" +#include "../../../proof_system/proving_key/proving_key.hpp" #include "../types/plonk_proof.hpp" #include "../types/program_settings.hpp" #include "../widgets/random_widgets/random_widget.hpp" -#include "./work_queue.hpp" +#include "../../../proof_system/work_queue/work_queue.hpp" #include "../widgets/transition_widgets/transition_widget.hpp" #include "../commitment_scheme/commitment_scheme.hpp" namespace waffle { diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/verifier/verifier.test.cpp b/barretenberg/cpp/src/aztec/plonk/proof_system/verifier/verifier.test.cpp index 9261ed9f7d8d..46dbd1fc0e5e 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/verifier/verifier.test.cpp @@ -1,5 +1,5 @@ #include "../prover/prover.hpp" -#include "../proving_key/proving_key.hpp" +#include "../../../proof_system/proving_key/proving_key.hpp" #include "../utils/linearizer.hpp" #include "../utils/permutation.hpp" #include "../widgets/transition_widgets/arithmetic_widget.hpp" diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/permutation_widget_impl.hpp b/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/permutation_widget_impl.hpp index 376d0da5d1cd..1397204f5f6c 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/permutation_widget_impl.hpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/permutation_widget_impl.hpp @@ -1,7 +1,7 @@ #pragma once #include #include -#include +#include #include #include diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/plookup_widget_impl.hpp b/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/plookup_widget_impl.hpp index 8eadc4c49d83..6cbb6e768c73 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/plookup_widget_impl.hpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/plookup_widget_impl.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/random_widget.hpp b/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/random_widget.hpp index f697dc06dd65..c7a853e87631 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/random_widget.hpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/random_widgets/random_widget.hpp @@ -1,7 +1,7 @@ #pragma once #include "../../../transcript/transcript_wrappers.hpp" #include "../../verification_key/verification_key.hpp" -#include "../../prover/work_queue.hpp" +#include "../../../../proof_system/work_queue/work_queue.hpp" #include #include diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/transition_widgets/transition_widget.hpp b/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/transition_widgets/transition_widget.hpp index 34ab006298ab..88667d8263b0 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/transition_widgets/transition_widget.hpp +++ b/barretenberg/cpp/src/aztec/plonk/proof_system/widgets/transition_widgets/transition_widget.hpp @@ -8,9 +8,9 @@ #include #include "../../types/polynomial_manifest.hpp" #include "../../types/prover_settings.hpp" -#include "../../proving_key/proving_key.hpp" +#include "../../../../proof_system/proving_key/proving_key.hpp" #include "../../verification_key/verification_key.hpp" -#include "../../prover/work_queue.hpp" +#include "../../../../proof_system/work_queue/work_queue.hpp" namespace waffle { diff --git a/barretenberg/cpp/src/aztec/proof_system/CMakeLists.txt b/barretenberg/cpp/src/aztec/proof_system/CMakeLists.txt new file mode 100644 index 000000000000..797c1dfa49ab --- /dev/null +++ b/barretenberg/cpp/src/aztec/proof_system/CMakeLists.txt @@ -0,0 +1 @@ +barretenberg_module(proof_system plonk polynomials) \ No newline at end of file diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_cache.cpp b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_cache.cpp similarity index 100% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_cache.cpp rename to barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_cache.cpp diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_cache.hpp b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_cache.hpp similarity index 97% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_cache.hpp rename to barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_cache.hpp index 107a1c32c256..8a6e3c88af27 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_cache.hpp +++ b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_cache.hpp @@ -3,7 +3,7 @@ #include #include #include "polynomial_store.hpp" -#include "../types/polynomial_manifest.hpp" +#include "../../plonk/proof_system/types/polynomial_manifest.hpp" namespace waffle { diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_cache.test.cpp b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_cache.test.cpp similarity index 100% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_cache.test.cpp rename to barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_cache.test.cpp diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store.hpp b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store.hpp similarity index 96% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store.hpp rename to barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store.hpp index 54d290516e46..50b65405c2dd 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store.hpp +++ b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store.hpp @@ -1,7 +1,7 @@ #pragma once #include -#include +#include "../../polynomials/polynomial.hpp" namespace waffle { diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store.test.cpp b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store.test.cpp similarity index 100% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store.test.cpp rename to barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store.test.cpp diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store_mem.cpp b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store_mem.cpp similarity index 100% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store_mem.cpp rename to barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store_mem.cpp diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store_wasm.cpp b/barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store_wasm.cpp similarity index 100% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/polynomial_store_wasm.cpp rename to barretenberg/cpp/src/aztec/proof_system/polynomial_cache/polynomial_store_wasm.cpp diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/proving_key.cpp b/barretenberg/cpp/src/aztec/proof_system/proving_key/proving_key.cpp similarity index 100% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/proving_key.cpp rename to barretenberg/cpp/src/aztec/proof_system/proving_key/proving_key.cpp diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/proving_key.hpp b/barretenberg/cpp/src/aztec/proof_system/proving_key/proving_key.hpp similarity index 97% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/proving_key.hpp rename to barretenberg/cpp/src/aztec/proof_system/proving_key/proving_key.hpp index 9957e7909959..1b86c69e0709 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/proving_key.hpp +++ b/barretenberg/cpp/src/aztec/proof_system/proving_key/proving_key.hpp @@ -9,7 +9,7 @@ #include #include -#include "polynomial_cache.hpp" +#include "../polynomial_cache/polynomial_cache.hpp" namespace waffle { diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/proving_key.test.cpp b/barretenberg/cpp/src/aztec/proof_system/proving_key/proving_key.test.cpp similarity index 98% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/proving_key.test.cpp rename to barretenberg/cpp/src/aztec/proof_system/proving_key/proving_key.test.cpp index 94ce6d29319b..48ce173023eb 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/proving_key.test.cpp +++ b/barretenberg/cpp/src/aztec/proof_system/proving_key/proving_key.test.cpp @@ -61,7 +61,7 @@ TEST(proving_key, proving_key_from_mmaped_key) // Write each precomputed polynomial in the proving key to // its own file using write_mmap - std::string pk_dir = "../src/aztec/plonk/proof_system/proving_key/fixtures"; + std::string pk_dir = "../src/aztec/proof_system/proving_key/fixtures"; std::filesystem::create_directories(pk_dir); std::string pk_path = pk_dir + "/proving_key"; std::ofstream os(pk_path); diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/serialize.hpp b/barretenberg/cpp/src/aztec/proof_system/proving_key/serialize.hpp similarity index 100% rename from barretenberg/cpp/src/aztec/plonk/proof_system/proving_key/serialize.hpp rename to barretenberg/cpp/src/aztec/proof_system/proving_key/serialize.hpp diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/prover/work_queue.cpp b/barretenberg/cpp/src/aztec/proof_system/work_queue/work_queue.cpp similarity index 100% rename from barretenberg/cpp/src/aztec/plonk/proof_system/prover/work_queue.cpp rename to barretenberg/cpp/src/aztec/proof_system/work_queue/work_queue.cpp diff --git a/barretenberg/cpp/src/aztec/plonk/proof_system/prover/work_queue.hpp b/barretenberg/cpp/src/aztec/proof_system/work_queue/work_queue.hpp similarity index 97% rename from barretenberg/cpp/src/aztec/plonk/proof_system/prover/work_queue.hpp rename to barretenberg/cpp/src/aztec/proof_system/work_queue/work_queue.hpp index 72b7aa4d006b..061f7e6d26f6 100644 --- a/barretenberg/cpp/src/aztec/plonk/proof_system/prover/work_queue.hpp +++ b/barretenberg/cpp/src/aztec/proof_system/work_queue/work_queue.hpp @@ -1,6 +1,6 @@ #pragma once -#include "../../transcript/transcript_wrappers.hpp" +#include "../../plonk/transcript/transcript_wrappers.hpp" #include "../proving_key/proving_key.hpp" namespace waffle { diff --git a/barretenberg/cpp/src/aztec/rollup/keygen/main.cpp b/barretenberg/cpp/src/aztec/rollup/keygen/main.cpp index 779a23cb0298..c6684ba13776 100644 --- a/barretenberg/cpp/src/aztec/rollup/keygen/main.cpp +++ b/barretenberg/cpp/src/aztec/rollup/keygen/main.cpp @@ -5,7 +5,7 @@ #include "../proofs/claim/index.hpp" #include #include -#include +#include #include #include diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/account/account.test.cpp b/barretenberg/cpp/src/aztec/rollup/proofs/account/account.test.cpp index f11cd2b9b363..438a537cfee8 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/account/account.test.cpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/account/account.test.cpp @@ -8,7 +8,7 @@ #include #include -#include +#include #include #include diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/account/c_bind.cpp b/barretenberg/cpp/src/aztec/rollup/proofs/account/c_bind.cpp index b917813f48db..dcf2d78c0d79 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/account/c_bind.cpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/account/c_bind.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include using namespace barretenberg; diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/account/compute_circuit_data.hpp b/barretenberg/cpp/src/aztec/rollup/proofs/account/compute_circuit_data.hpp index 5ac1c263b94c..08334a01a6db 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/account/compute_circuit_data.hpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/account/compute_circuit_data.hpp @@ -1,6 +1,6 @@ #pragma once #include "account.hpp" -#include +#include #include #include "../compute_circuit_data.hpp" diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/claim/get_circuit_data.hpp b/barretenberg/cpp/src/aztec/rollup/proofs/claim/get_circuit_data.hpp index 5e0e231fa9be..801603bd536f 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/claim/get_circuit_data.hpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/claim/get_circuit_data.hpp @@ -1,7 +1,7 @@ #pragma once #include "claim_tx.hpp" #include "claim_circuit.hpp" -#include +#include #include #include #include "../compute_circuit_data.hpp" diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/compute_circuit_data.hpp b/barretenberg/cpp/src/aztec/rollup/proofs/compute_circuit_data.hpp index 72a8b91cffe9..8b2aca063fd9 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/compute_circuit_data.hpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/compute_circuit_data.hpp @@ -5,13 +5,13 @@ #include #include #include -#include +#include #include #define GET_COMPOSER_NAME_STRING(composer) \ - (typeid(composer) == typeid(waffle::StandardComposer) ? "StandardPlonk" \ - : typeid(composer) == typeid(waffle::TurboComposer) ? "TurboPlonk" \ - : "NULLPlonk") + (typeid(composer) == typeid(waffle::StandardComposer) \ + ? "StandardPlonk" \ + : typeid(composer) == typeid(waffle::TurboComposer) ? "TurboPlonk" : "NULLPlonk") namespace rollup { namespace proofs { diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/join_split/c_bind.cpp b/barretenberg/cpp/src/aztec/rollup/proofs/join_split/c_bind.cpp index e1cdb48be50c..0106a7a3417b 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/join_split/c_bind.cpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/join_split/c_bind.cpp @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include using namespace barretenberg; diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/join_split/join_split.test.cpp b/barretenberg/cpp/src/aztec/rollup/proofs/join_split/join_split.test.cpp index 1dcddd353691..9ae3fbc8a72e 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/join_split/join_split.test.cpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/join_split/join_split.test.cpp @@ -4,7 +4,7 @@ #include "../notes/native/index.hpp" #include #include -#include +#include #include namespace rollup { diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/join_split/join_split_js_parity.test.cpp b/barretenberg/cpp/src/aztec/rollup/proofs/join_split/join_split_js_parity.test.cpp index d6fa710c614d..fabefde3df9f 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/join_split/join_split_js_parity.test.cpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/join_split/join_split_js_parity.test.cpp @@ -4,7 +4,7 @@ #include "../notes/native/index.hpp" #include #include -#include +#include #include #include diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/rollup/compute_circuit_data.hpp b/barretenberg/cpp/src/aztec/rollup/proofs/rollup/compute_circuit_data.hpp index e0b2e9013fc1..e41e1d3870fc 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/rollup/compute_circuit_data.hpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/rollup/compute_circuit_data.hpp @@ -5,7 +5,7 @@ #include "../join_split/index.hpp" #include "../account/index.hpp" #include "../claim/index.hpp" -#include +#include #include namespace rollup { diff --git a/barretenberg/cpp/src/aztec/rollup/proofs/root_rollup/compute_circuit_data.cpp b/barretenberg/cpp/src/aztec/rollup/proofs/root_rollup/compute_circuit_data.cpp index b79048899522..bcc4d1f4db05 100644 --- a/barretenberg/cpp/src/aztec/rollup/proofs/root_rollup/compute_circuit_data.cpp +++ b/barretenberg/cpp/src/aztec/rollup/proofs/root_rollup/compute_circuit_data.cpp @@ -2,7 +2,7 @@ #include "../rollup/compute_circuit_data.hpp" #include "root_rollup_tx.hpp" #include "root_rollup_circuit.hpp" -#include +#include #include #include "./root_rollup_proof_data.hpp" diff --git a/barretenberg/cpp/src/aztec/rollup/rollup_cli/main.cpp b/barretenberg/cpp/src/aztec/rollup/rollup_cli/main.cpp index 4872272a6676..cdd14b4b6ef2 100644 --- a/barretenberg/cpp/src/aztec/rollup/rollup_cli/main.cpp +++ b/barretenberg/cpp/src/aztec/rollup/rollup_cli/main.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include using namespace ::rollup::proofs; diff --git a/barretenberg/cpp/src/aztec/stdlib/recursion/verifier/verifier.test.cpp b/barretenberg/cpp/src/aztec/stdlib/recursion/verifier/verifier.test.cpp index 9a84cf727f61..e84a69f7bef3 100644 --- a/barretenberg/cpp/src/aztec/stdlib/recursion/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/aztec/stdlib/recursion/verifier/verifier.test.cpp @@ -1,7 +1,7 @@ #include "verifier.hpp" #include #include -#include +#include #include #include #include diff --git a/barretenberg/cpp/src/aztec/stdlib/recursion/verifier/verifier_turbo.test.cpp b/barretenberg/cpp/src/aztec/stdlib/recursion/verifier/verifier_turbo.test.cpp index 3ae8d6482b6f..8f2bc675d601 100644 --- a/barretenberg/cpp/src/aztec/stdlib/recursion/verifier/verifier_turbo.test.cpp +++ b/barretenberg/cpp/src/aztec/stdlib/recursion/verifier/verifier_turbo.test.cpp @@ -1,7 +1,7 @@ #include "verifier.hpp" #include #include -#include +#include #include #include #include