diff --git a/circuits/cpp/barretenberg/.circleci/config.yml b/circuits/cpp/barretenberg/.circleci/config.yml index c8e04ef1dd6..f1acb93d572 100644 --- a/circuits/cpp/barretenberg/.circleci/config.yml +++ b/circuits/cpp/barretenberg/.circleci/config.yml @@ -148,7 +148,7 @@ jobs: name: "Build" command: cond_spot_run_build barretenberg-x86_64-linux-clang-assert 64 - barretenberg-tests: + stdlib-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -157,10 +157,10 @@ jobs: - *setup_env - run: name: "Test" - command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 bb-tests + command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 stdlib-tests - *save_logs - honk-tests: + barretenberg-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -169,11 +169,10 @@ jobs: - *setup_env - run: name: "Test" - command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 honk_tests + command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 bb-tests - *save_logs - - stdlib-primitives-tests: + honk-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -182,10 +181,10 @@ jobs: - *setup_env - run: name: "Test" - command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 stdlib_primitives_tests --gtest_filter=-stdlib_biggroup* + command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 honk_tests - *save_logs - stdlib-biggroup-tests: + proof-system-tests: docker: - image: aztecprotocol/alpine-build-image resource_class: small @@ -194,7 +193,7 @@ jobs: - *setup_env - run: name: "Test" - command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 stdlib_primitives_tests --gtest_filter=stdlib_biggroup* + command: cond_spot_run_tests barretenberg-x86_64-linux-clang-assert 1 proof_system_tests - *save_logs stdlib-recursion-turbo-tests: @@ -323,18 +322,17 @@ workflows: - x86_64-linux-clang: *defaults - x86_64-linux-clang-assert: *defaults - wasm-linux-clang: *defaults + - proof-system-tests: *bb_test - honk-tests: *bb_test - barretenberg-tests: *bb_test - - stdlib-primitives-tests: *bb_test - - stdlib-biggroup-tests: *bb_test + - stdlib-tests: *bb_test - stdlib-recursion-turbo-tests: *bb_test - stdlib-recursion-ultra-tests: *bb_test - join-split-tests: *bb_test - benchmark-aggregator: requires: - barretenberg-tests - - stdlib-primitives-tests - - stdlib-biggroup-tests + - stdlib-tests - stdlib-recursion-turbo-tests - stdlib-recursion-ultra-tests - join-split-tests diff --git a/circuits/cpp/barretenberg/barretenberg.code-workspace b/circuits/cpp/barretenberg/barretenberg.code-workspace index c0737c91760..a95ef89173f 100644 --- a/circuits/cpp/barretenberg/barretenberg.code-workspace +++ b/circuits/cpp/barretenberg/barretenberg.code-workspace @@ -84,6 +84,10 @@ // to the default value "clangd". // "clangd.path": "clangd-15", + // We should disable automatic inclusion of headers unless we decide to follow "WhyIWYU". + "clangd.arguments": [ + "-header-insertion=never" + ] // // CMake // diff --git a/circuits/cpp/barretenberg/cpp/.clangd b/circuits/cpp/barretenberg/cpp/.clangd index a082221eecc..599f23163a2 100644 --- a/circuits/cpp/barretenberg/cpp/.clangd +++ b/circuits/cpp/barretenberg/cpp/.clangd @@ -5,10 +5,11 @@ CompileFlags: # Tweak the parse settings If: PathMatch: [src/.*\.hpp, src/.*\.cpp, src/.*\.tcc] Diagnostics: - # Checks whether we are including unused header files + # Value Strict checks whether we are including unused header files # Note that some headers may be _implicitly_ used and still - # need to be included, so be careful before removing them. - UnusedIncludes: Strict + # need to be included. This is very noisy, and is probably best used + # by occasionally toggling it on. + UnusedIncludes: None # Static analysis configuration ClangTidy: @@ -56,6 +57,10 @@ Diagnostics: - cert-err58-cpp # Triggers on some tests that are not complex - readability-function-cognitive-complexity + # It is often nicer to not be explicit + - google-explicit-constructor + CheckOptions: + - cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor: True --- # this divider is necessary # Disable some checks for Google Test/Bench diff --git a/circuits/cpp/barretenberg/cpp/scripts/bb-tests b/circuits/cpp/barretenberg/cpp/scripts/bb-tests index ba012981ead..0bdd2508bbe 100644 --- a/circuits/cpp/barretenberg/cpp/scripts/bb-tests +++ b/circuits/cpp/barretenberg/cpp/scripts/bb-tests @@ -9,16 +9,7 @@ ecc_tests numeric_tests plonk_tests polynomials_tests -proof_system_tests join_split_example_proofs_inner_proof_data_tests join_split_example_proofs_notes_tests srs_tests -stdlib_aes128_tests -stdlib_blake2s_tests -stdlib_blake3s_tests -stdlib_ecdsa_tests -stdlib_merkle_tree_tests -stdlib_pedersen_commitment_tests -stdlib_schnorr_tests -stdlib_sha256_tests -transcript_tests +transcript_tests \ No newline at end of file diff --git a/circuits/cpp/barretenberg/cpp/scripts/stdlib-tests b/circuits/cpp/barretenberg/cpp/scripts/stdlib-tests new file mode 100644 index 00000000000..4f61b0c2f19 --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/scripts/stdlib-tests @@ -0,0 +1,9 @@ +stdlib_primitives_tests +stdlib_aes128_tests +stdlib_blake2s_tests +stdlib_blake3s_tests +stdlib_ecdsa_tests +stdlib_merkle_tree_tests +stdlib_pedersen_commitment_tests +stdlib_schnorr_tests +stdlib_sha256_tests \ No newline at end of file diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.cpp index 6867d9af37a..1b8568779bb 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.cpp @@ -1,8 +1,9 @@ #include "standard_honk_composer_helper.hpp" +#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" #include "barretenberg/honk/pcs/commitment_key.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" +#include "barretenberg/srs/reference_string/reference_string.hpp" #include #include @@ -14,7 +15,7 @@ namespace proof_system::honk { * Compute proving key base. * * 1. Load crs. - * 2. Initialize this.circuit_proving_key. + * 2. Initialize this->proving_key. * 3. Create constraint selector polynomials from each of this composer's `selectors` vectors and add them to the * proving key. * @@ -22,18 +23,17 @@ namespace proof_system::honk { * @param num_reserved_gates The number of reserved gates. * @return Pointer to the initialized proving key updated with selector polynomials. * */ -template -std::shared_ptr StandardHonkComposerHelper::compute_proving_key_base( +std::shared_ptr StandardHonkComposerHelper::compute_proving_key_base( const CircuitConstructor& constructor, const size_t minimum_circuit_size, const size_t num_randomized_gates) { - // Initialize circuit_proving_key - // TODO(#229)(Kesha): replace composer types. - circuit_proving_key = initialize_proving_key( + // Initialize proving_key + // TODO(#392)(Kesha): replace composer types. + proving_key = initialize_proving_key( constructor, crs_factory_.get(), minimum_circuit_size, num_randomized_gates, ComposerType::STANDARD_HONK); // Compute lagrange selectors - construct_lagrange_selector_forms(constructor, circuit_proving_key.get()); + construct_selector_polynomials(constructor, proving_key.get()); - return circuit_proving_key; + return proving_key; } /** @@ -42,29 +42,29 @@ std::shared_ptr StandardHonkComposerHelper -std::shared_ptr StandardHonkComposerHelper::compute_verification_key_base( - std::shared_ptr const& proving_key, std::shared_ptr const& vrs) +std::shared_ptr StandardHonkComposerHelper::compute_verification_key_base( + std::shared_ptr const& proving_key, + std::shared_ptr const& vrs) { - auto key = std::make_shared( + auto key = std::make_shared( proving_key->circuit_size, proving_key->num_public_inputs, vrs, proving_key->composer_type); // TODO(kesha): Dirty hack for now. Need to actually make commitment-agnositc auto commitment_key = pcs::kzg::CommitmentKey(proving_key->circuit_size, "../srs_db/ignition"); // Compute and store commitments to all precomputed polynomials - key->commitments["Q_M"] = commitment_key.commit(proving_key->polynomial_store.get("q_m_lagrange")); - key->commitments["Q_1"] = commitment_key.commit(proving_key->polynomial_store.get("q_1_lagrange")); - key->commitments["Q_2"] = commitment_key.commit(proving_key->polynomial_store.get("q_2_lagrange")); - key->commitments["Q_3"] = commitment_key.commit(proving_key->polynomial_store.get("q_3_lagrange")); - key->commitments["Q_C"] = commitment_key.commit(proving_key->polynomial_store.get("q_c_lagrange")); - key->commitments["SIGMA_1"] = commitment_key.commit(proving_key->polynomial_store.get("sigma_1_lagrange")); - key->commitments["SIGMA_2"] = commitment_key.commit(proving_key->polynomial_store.get("sigma_2_lagrange")); - key->commitments["SIGMA_3"] = commitment_key.commit(proving_key->polynomial_store.get("sigma_3_lagrange")); - key->commitments["ID_1"] = commitment_key.commit(proving_key->polynomial_store.get("id_1_lagrange")); - key->commitments["ID_2"] = commitment_key.commit(proving_key->polynomial_store.get("id_2_lagrange")); - key->commitments["ID_3"] = commitment_key.commit(proving_key->polynomial_store.get("id_3_lagrange")); - key->commitments["LAGRANGE_FIRST"] = commitment_key.commit(proving_key->polynomial_store.get("L_first_lagrange")); - key->commitments["LAGRANGE_LAST"] = commitment_key.commit(proving_key->polynomial_store.get("L_last_lagrange")); + key->q_m = commitment_key.commit(proving_key->q_m); + key->q_l = commitment_key.commit(proving_key->q_l); + key->q_r = commitment_key.commit(proving_key->q_r); + key->q_o = commitment_key.commit(proving_key->q_o); + key->q_c = commitment_key.commit(proving_key->q_c); + key->sigma_1 = commitment_key.commit(proving_key->sigma_1); + key->sigma_2 = commitment_key.commit(proving_key->sigma_2); + key->sigma_3 = commitment_key.commit(proving_key->sigma_3); + key->id_1 = commitment_key.commit(proving_key->id_1); + key->id_2 = commitment_key.commit(proving_key->id_2); + key->id_3 = commitment_key.commit(proving_key->id_3); + key->lagrange_first = commitment_key.commit(proving_key->lagrange_first); + key->lagrange_last = commitment_key.commit(proving_key->lagrange_last); return key; } @@ -78,14 +78,18 @@ std::shared_ptr StandardHonkComposerHelper -void StandardHonkComposerHelper::compute_witness(const CircuitConstructor& circuit_constructor, - const size_t minimum_circuit_size) +void StandardHonkComposerHelper::compute_witness(const CircuitConstructor& circuit_constructor, + const size_t minimum_circuit_size) { if (computed_witness) { return; } - wire_polynomials = compute_witness_base(circuit_constructor, minimum_circuit_size, NUM_RANDOMIZED_GATES); + auto wire_polynomials = + construct_wire_polynomials_base(circuit_constructor, minimum_circuit_size, NUM_RANDOMIZED_GATES); + + proving_key->w_l = wire_polynomials[0]; + proving_key->w_r = wire_polynomials[1]; + proving_key->w_o = wire_polynomials[2]; computed_witness = true; } @@ -97,24 +101,23 @@ void StandardHonkComposerHelper::compute_witness(const Circu * @return Proving key with saved computed polynomials. * */ -template -std::shared_ptr StandardHonkComposerHelper::compute_proving_key( +std::shared_ptr StandardHonkComposerHelper::compute_proving_key( const CircuitConstructor& circuit_constructor) { - if (circuit_proving_key) { - return circuit_proving_key; + if (proving_key) { + return proving_key; } // Compute q_l, q_r, q_o, etc polynomials - StandardHonkComposerHelper::compute_proving_key_base(circuit_constructor, ComposerType::STANDARD_HONK); + StandardHonkComposerHelper::compute_proving_key_base( + circuit_constructor, /*minimum_circuit_size=*/0, NUM_RANDOMIZED_GATES); // Compute sigma polynomials (we should update that late) - compute_standard_honk_sigma_permutations(circuit_constructor, - circuit_proving_key.get()); - compute_standard_honk_id_polynomials(circuit_proving_key.get()); + compute_standard_honk_sigma_permutations(circuit_constructor, proving_key.get()); + compute_standard_honk_id_polynomials(proving_key.get()); - compute_first_and_last_lagrange_polynomials(circuit_proving_key.get()); + compute_first_and_last_lagrange_polynomials(proving_key.get()); - return circuit_proving_key; + return proving_key; } /** @@ -122,30 +125,27 @@ std::shared_ptr StandardHonkComposerHelper -std::shared_ptr StandardHonkComposerHelper::compute_verification_key( +std::shared_ptr StandardHonkComposerHelper::compute_verification_key( const CircuitConstructor& circuit_constructor) { - if (circuit_verification_key) { - return circuit_verification_key; + if (verification_key) { + return verification_key; } - if (!circuit_proving_key) { + if (!proving_key) { compute_proving_key(circuit_constructor); } - circuit_verification_key = StandardHonkComposerHelper::compute_verification_key_base( - circuit_proving_key, crs_factory_->get_verifier_crs()); - circuit_verification_key->composer_type = circuit_proving_key->composer_type; + verification_key = + StandardHonkComposerHelper::compute_verification_key_base(proving_key, crs_factory_->get_verifier_crs()); + verification_key->composer_type = proving_key->composer_type; - return circuit_verification_key; + return verification_key; } -template -StandardVerifier StandardHonkComposerHelper::create_verifier( - const CircuitConstructor& circuit_constructor) +StandardVerifier StandardHonkComposerHelper::create_verifier(const CircuitConstructor& circuit_constructor) { compute_verification_key(circuit_constructor); - StandardVerifier output_state(circuit_verification_key); + StandardVerifier output_state(verification_key); // TODO(Cody): This should be more generic auto kate_verification_key = std::make_unique("../srs_db/ignition"); @@ -155,23 +155,13 @@ StandardVerifier StandardHonkComposerHelper::create_verifier return output_state; } -template -template -// TODO(Cody): this file should be generic with regard to flavor/arithmetization/whatever. -StandardProver StandardHonkComposerHelper::create_prover( - const CircuitConstructor& circuit_constructor) +StandardProver StandardHonkComposerHelper::create_prover(const CircuitConstructor& circuit_constructor) { compute_proving_key(circuit_constructor); compute_witness(circuit_constructor); - size_t num_sumcheck_rounds(circuit_proving_key->log_circuit_size); - // TODO(luke): what is this manifest? Remove? - auto manifest = Flavor::create_manifest(circuit_constructor.public_inputs.size(), num_sumcheck_rounds); - StandardProver output_state(std::move(wire_polynomials), circuit_proving_key); + StandardProver output_state(proving_key); return output_state; } -template class StandardHonkComposerHelper; -template StandardProver StandardHonkComposerHelper::create_prover( - const StandardCircuitConstructor& circuit_constructor); } // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.hpp index 5b033996d5d..031ebb8115f 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/standard_honk_composer_helper.hpp @@ -1,30 +1,28 @@ #pragma once -#include "barretenberg/polynomials/polynomial.hpp" +#include #include "barretenberg/srs/reference_string/file_reference_string.hpp" -#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/honk/proof_system/prover.hpp" #include "barretenberg/honk/proof_system/verifier.hpp" #include "barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp" -#include "barretenberg/honk/pcs/commitment_key.hpp" -#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" #include "barretenberg/plonk/proof_system/verifier/verifier.hpp" -#include "barretenberg/proof_system/arithmetization/gate_data.hpp" #include "barretenberg/proof_system/composer/composer_helper_lib.hpp" #include "barretenberg/proof_system/composer/permutation_helper.hpp" -#include +#include "barretenberg/honk/flavor/standard.hpp" namespace proof_system::honk { -// TODO(Kesha): change initializations to specify this parameter -// Cody: What does this mean? -template class StandardHonkComposerHelper { +class StandardHonkComposerHelper { public: + using Flavor = flavor::Standard; + using CircuitConstructor = Flavor::CircuitConstructor; + using ProvingKey = Flavor::ProvingKey; + using VerificationKey = Flavor::VerificationKey; + static constexpr size_t NUM_RANDOMIZED_GATES = 2; // equal to the number of multilinear evaluations leaked - static constexpr size_t num_wires = CircuitConstructor::num_wires; - std::shared_ptr circuit_proving_key; - std::vector wire_polynomials; - std::shared_ptr circuit_verification_key; + static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; + std::shared_ptr proving_key; + std::shared_ptr verification_key; // TODO(#218)(kesha): we need to put this into the commitment key, so that the composer doesn't have to handle srs // at all std::shared_ptr crs_factory_; @@ -41,10 +39,9 @@ template class StandardHonkComposerHelper { StandardHonkComposerHelper(std::unique_ptr&& crs_factory) : crs_factory_(std::move(crs_factory)) {} - StandardHonkComposerHelper(std::shared_ptr p_key, - std::shared_ptr v_key) - : circuit_proving_key(std::move(p_key)) - , circuit_verification_key(std::move(v_key)) + StandardHonkComposerHelper(std::shared_ptr p_key, std::shared_ptr v_key) + : proving_key(std::move(p_key)) + , verification_key(std::move(v_key)) {} StandardHonkComposerHelper(StandardHonkComposerHelper&& other) noexcept = default; StandardHonkComposerHelper(const StandardHonkComposerHelper& other) = delete; @@ -52,23 +49,21 @@ template class StandardHonkComposerHelper { StandardHonkComposerHelper& operator=(const StandardHonkComposerHelper& other) = delete; ~StandardHonkComposerHelper() = default; - std::shared_ptr compute_proving_key(const CircuitConstructor& circuit_constructor); - std::shared_ptr compute_verification_key(const CircuitConstructor& circuit_constructor); + std::shared_ptr compute_proving_key(const CircuitConstructor& circuit_constructor); + std::shared_ptr compute_verification_key(const CircuitConstructor& circuit_constructor); StandardVerifier create_verifier(const CircuitConstructor& circuit_constructor); - template StandardProver create_prover(const CircuitConstructor& circuit_constructor); + StandardProver create_prover(const CircuitConstructor& circuit_constructor); // TODO(#216)(Adrian): Seems error prone to provide the number of randomized gates - // Cody: Where should this go? In the flavor (or whatever that becomes)? - std::shared_ptr compute_proving_key_base( - const CircuitConstructor& circuit_constructor, - const size_t minimum_ciricut_size = 0, - const size_t num_randomized_gates = NUM_RANDOMIZED_GATES); + std::shared_ptr compute_proving_key_base(const CircuitConstructor& circuit_constructor, + const size_t minimum_circuit_size = 0, + const size_t num_randomized_gates = NUM_RANDOMIZED_GATES); // This needs to be static as it may be used only to compute the selector commitments. - static std::shared_ptr compute_verification_key_base( - std::shared_ptr const& proving_key, std::shared_ptr const& vrs); + static std::shared_ptr compute_verification_key_base( + std::shared_ptr const& proving_key, std::shared_ptr const& vrs); void compute_witness(const CircuitConstructor& circuit_constructor, const size_t minimum_circuit_size = 0); }; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp index dce07006c41..32981a343dc 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.cpp @@ -1,27 +1,16 @@ #include "ultra_honk_composer_helper.hpp" #include "barretenberg/honk/proof_system/ultra_prover.hpp" -#include "barretenberg/plonk/proof_system/types/program_settings.hpp" -#include "barretenberg/plonk/proof_system/types/prover_settings.hpp" -// #include "barretenberg/plonk/proof_system/verifier/verifier.hpp" #include "barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp" +#include "barretenberg/proof_system/composer/composer_helper_lib.hpp" #include "barretenberg/proof_system/composer/permutation_helper.hpp" -#include "barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp" - -#include -#include -#include -#include namespace proof_system::honk { /** * @brief Compute witness polynomials * - * TODO(luke): The wire polynomials are returned directly whereas the sorted list polys are added to the proving - * key. This should be made consistent once Cody's Flavor work is settled. */ -template -void UltraHonkComposerHelper::compute_witness(CircuitConstructor& circuit_constructor) +void UltraHonkComposerHelper::compute_witness(CircuitConstructor& circuit_constructor) { if (computed_witness) { return; @@ -40,8 +29,8 @@ void UltraHonkComposerHelper::compute_witness(CircuitConstru const size_t subgroup_size = circuit_constructor.get_circuit_subgroup_size(total_num_gates + NUM_RANDOMIZED_GATES); // Pad the wires (pointers to `witness_indices` of the `variables` vector). - // Note: the remaining NUM_RESERVED_GATES indices are padded with zeros within `compute_witness_base` (called - // next). + // Note: the remaining NUM_RESERVED_GATES indices are padded with zeros within `construct_wire_polynomials_base` + // (called next). for (size_t i = filled_gates; i < total_num_gates; ++i) { circuit_constructor.w_l.emplace_back(circuit_constructor.zero_idx); circuit_constructor.w_r.emplace_back(circuit_constructor.zero_idx); @@ -49,17 +38,24 @@ void UltraHonkComposerHelper::compute_witness(CircuitConstru circuit_constructor.w_4.emplace_back(circuit_constructor.zero_idx); } - // TODO(#340)(luke): within compute_witness_base, the 3rd argument is used in the calculation of the dyadic circuit - // size (subgroup_size). Here (and in other split composers) we're passing in NUM_RANDOMIZED_GATES, but elsewhere, - // e.g. directly above, we use NUM_RESERVED_GATES in a similar role. Therefore, these two constants must be equal - // for everything to be consistent. What we should do is compute the dyadic circuit size once and for all then pass - // that around rather than computing in multiple places. - wire_polynomials = compute_witness_base(circuit_constructor, total_num_gates, NUM_RANDOMIZED_GATES); + // TODO(#340)(luke): within construct_wire_polynomials_base, the 3rd argument is used in the calculation of the + // dyadic circuit size (subgroup_size). Here (and in other split composers) we're passing in NUM_RANDOMIZED_GATES, + // but elsewhere, e.g. directly above, we use NUM_RESERVED_GATES in a similar role. Therefore, these two constants + // must be equal for everything to be consistent. What we should do is compute the dyadic circuit size once and for + // all then pass that around rather than computing in multiple places. + auto wire_polynomials = + construct_wire_polynomials_base(circuit_constructor, total_num_gates, NUM_RANDOMIZED_GATES); + + proving_key->w_l = wire_polynomials[0]; + proving_key->w_r = wire_polynomials[1]; + proving_key->w_o = wire_polynomials[2]; + proving_key->w_4 = wire_polynomials[3]; polynomial s_1(subgroup_size); polynomial s_2(subgroup_size); polynomial s_3(subgroup_size); polynomial s_4(subgroup_size); + // TODO(luke): The +1 size for z_lookup is not necessary and can lead to confusion. Resolve. polynomial z_lookup(subgroup_size + 1); // Only instantiated in this function; nothing assigned. // Save space for adding random scalars in the s polynomial later. The subtracted 1 allows us to insert a `1` at the @@ -130,25 +126,22 @@ void UltraHonkComposerHelper::compute_witness(CircuitConstru ++count; } - // TODO(luke): Adding these to the key for now but this is inconsistent since these are 'witness' polys. Need - // to see what becomes of the proving key before making a decision here. - circuit_proving_key->polynomial_store.put("s_1_lagrange", std::move(s_1)); - circuit_proving_key->polynomial_store.put("s_2_lagrange", std::move(s_2)); - circuit_proving_key->polynomial_store.put("s_3_lagrange", std::move(s_3)); - circuit_proving_key->polynomial_store.put("s_4_lagrange", std::move(s_4)); + proving_key->sorted_1 = s_1; + proving_key->sorted_2 = s_2; + proving_key->sorted_3 = s_3; + proving_key->sorted_4 = s_4; computed_witness = true; } -template -UltraProver UltraHonkComposerHelper::create_prover(CircuitConstructor& circuit_constructor) +UltraProver UltraHonkComposerHelper::create_prover(CircuitConstructor& circuit_constructor) { finalize_circuit(circuit_constructor); compute_proving_key(circuit_constructor); compute_witness(circuit_constructor); - UltraProver output_state(std::move(wire_polynomials), circuit_proving_key); + UltraProver output_state(proving_key); return output_state; } @@ -159,14 +152,12 @@ UltraProver UltraHonkComposerHelper::create_prover(CircuitCo // * // * @return The verifier. // * */ -// // TODO(Cody): This should go away altogether. -// template -// plonk::UltraVerifier UltraHonkComposerHelper::create_verifier( +// plonk::UltraVerifier UltraHonkComposerHelper::create_verifier( // const CircuitConstructor& circuit_constructor) // { // auto verification_key = compute_verification_key(circuit_constructor); -// plonk::UltraVerifier output_state(circuit_verification_key, +// plonk::UltraVerifier output_state(verification_key, // create_manifest(circuit_constructor.public_inputs.size())); // std::unique_ptr> kate_commitment_scheme = @@ -177,12 +168,11 @@ UltraProver UltraHonkComposerHelper::create_prover(CircuitCo // return output_state; // } -template -std::shared_ptr UltraHonkComposerHelper::compute_proving_key( +std::shared_ptr UltraHonkComposerHelper::compute_proving_key( const CircuitConstructor& circuit_constructor) { - if (circuit_proving_key) { - return circuit_proving_key; + if (proving_key) { + return proving_key; } size_t tables_size = 0; @@ -194,23 +184,22 @@ std::shared_ptr UltraHonkComposerHelper: const size_t minimum_circuit_size = tables_size + lookups_size; const size_t num_randomized_gates = NUM_RANDOMIZED_GATES; - // Initialize circuit_proving_key - // TODO(#229)(Kesha): replace composer types. - circuit_proving_key = initialize_proving_key( + // Initialize proving_key + // TODO(#392)(Kesha): replace composer types. + proving_key = initialize_proving_key( circuit_constructor, crs_factory_.get(), minimum_circuit_size, num_randomized_gates, ComposerType::PLOOKUP); - construct_lagrange_selector_forms(circuit_constructor, circuit_proving_key.get()); + construct_selector_polynomials(circuit_constructor, proving_key.get()); // TODO(#217)(luke): Naively enforcing non-zero selectors for Honk will result in some relations not being // satisfied. - // enforce_nonzero_polynomial_selectors(circuit_constructor, circuit_proving_key.get()); + // enforce_nonzero_polynomial_selectors(circuit_constructor, proving_key.get()); - compute_honk_generalized_sigma_permutations(circuit_constructor, - circuit_proving_key.get()); + compute_honk_generalized_sigma_permutations(circuit_constructor, proving_key.get()); - compute_first_and_last_lagrange_polynomials(circuit_proving_key.get()); + compute_first_and_last_lagrange_polynomials(proving_key.get()); - const size_t subgroup_size = circuit_proving_key->circuit_size; + const size_t subgroup_size = proving_key->circuit_size; polynomial poly_q_table_column_1(subgroup_size); polynomial poly_q_table_column_2(subgroup_size); @@ -283,10 +272,10 @@ std::shared_ptr UltraHonkComposerHelper: // poly_q_table_column_3[subgroup_size - 1] = ++unique_last_value; // poly_q_table_column_4[subgroup_size - 1] = ++unique_last_value; - circuit_proving_key->polynomial_store.put("table_value_1_lagrange", std::move(poly_q_table_column_1)); - circuit_proving_key->polynomial_store.put("table_value_2_lagrange", std::move(poly_q_table_column_2)); - circuit_proving_key->polynomial_store.put("table_value_3_lagrange", std::move(poly_q_table_column_3)); - circuit_proving_key->polynomial_store.put("table_value_4_lagrange", std::move(poly_q_table_column_4)); + proving_key->table_1 = poly_q_table_column_1; + proving_key->table_2 = poly_q_table_column_2; + proving_key->table_3 = poly_q_table_column_3; + proving_key->table_4 = poly_q_table_column_4; // Copy memory read/write record data into proving key. Prover needs to know which gates contain a read/write // 'record' witness on the 4th wire. This wire value can only be fully computed once the first 3 wire polynomials @@ -294,17 +283,17 @@ std::shared_ptr UltraHonkComposerHelper: // using the plookup challenge `eta` std::copy(circuit_constructor.memory_read_records.begin(), circuit_constructor.memory_read_records.end(), - std::back_inserter(circuit_proving_key->memory_read_records)); + std::back_inserter(proving_key->memory_read_records)); std::copy(circuit_constructor.memory_write_records.begin(), circuit_constructor.memory_write_records.end(), - std::back_inserter(circuit_proving_key->memory_write_records)); + std::back_inserter(proving_key->memory_write_records)); - circuit_proving_key->recursive_proof_public_input_indices = + proving_key->recursive_proof_public_input_indices = std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); - circuit_proving_key->contains_recursive_proof = contains_recursive_proof; + proving_key->contains_recursive_proof = contains_recursive_proof; - return circuit_proving_key; + return proving_key; } // /** @@ -312,48 +301,45 @@ std::shared_ptr UltraHonkComposerHelper: // * // * @return Pointer to created circuit verification key. // * */ -// template -// std::shared_ptr UltraHonkComposerHelper::compute_verification_key( +// std::shared_ptr UltraHonkComposerHelper::compute_verification_key( // const CircuitConstructor& circuit_constructor) // { -// if (circuit_verification_key) { -// return circuit_verification_key; +// if (verification_key) { +// return verification_key; // } -// if (!circuit_proving_key) { +// if (!proving_key) { // compute_proving_key(circuit_constructor); // } -// circuit_verification_key = compute_verification_key_common(circuit_proving_key, +// verification_key = compute_verification_key_common(proving_key, // crs_factory_->get_verifier_crs()); -// circuit_verification_key->composer_type = type; // Invariably plookup for this class. +// verification_key->composer_type = type; // Invariably plookup for this class. // // See `add_recusrive_proof()` for how this recursive data is assigned. -// circuit_verification_key->recursive_proof_public_input_indices = +// verification_key->recursive_proof_public_input_indices = // std::vector(recursive_proof_public_input_indices.begin(), // recursive_proof_public_input_indices.end()); -// circuit_verification_key->contains_recursive_proof = contains_recursive_proof; +// verification_key->contains_recursive_proof = contains_recursive_proof; -// return circuit_verification_key; +// return verification_key; // } -// template -// void UltraHonkComposerHelper::add_table_column_selector_poly_to_proving_key( +// void UltraHonkComposerHelper::add_table_column_selector_poly_to_proving_key( // polynomial& selector_poly_lagrange_form, const std::string& tag) // { -// polynomial selector_poly_lagrange_form_copy(selector_poly_lagrange_form, circuit_proving_key->small_domain.size); +// polynomial selector_poly_lagrange_form_copy(selector_poly_lagrange_form, proving_key->small_domain.size); -// selector_poly_lagrange_form.ifft(circuit_proving_key->small_domain); +// selector_poly_lagrange_form.ifft(proving_key->small_domain); // auto& selector_poly_coeff_form = selector_poly_lagrange_form; -// polynomial selector_poly_coset_form(selector_poly_coeff_form, circuit_proving_key->circuit_size * 4); -// selector_poly_coset_form.coset_fft(circuit_proving_key->large_domain); +// polynomial selector_poly_coset_form(selector_poly_coeff_form, proving_key->circuit_size * 4); +// selector_poly_coset_form.coset_fft(proving_key->large_domain); -// circuit_proving_key->polynomial_store.put(tag, std::move(selector_poly_coeff_form)); -// circuit_proving_key->polynomial_store.put(tag + "_lagrange", std::move(selector_poly_lagrange_form_copy)); -// circuit_proving_key->polynomial_store.put(tag + "_fft", std::move(selector_poly_coset_form)); +// proving_key->polynomial_store.put(tag, std::move(selector_poly_coeff_form)); +// proving_key->polynomial_store.put(tag + "_lagrange", std::move(selector_poly_lagrange_form_copy)); +// proving_key->polynomial_store.put(tag + "_fft", std::move(selector_poly_coset_form)); // } -template class UltraHonkComposerHelper; } // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp index de309735e61..3bcd6ddd337 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp @@ -13,20 +13,22 @@ #include namespace proof_system::honk { -// TODO(Kesha): change initializations to specify this parameter -// Cody: What does this mean? -template class UltraHonkComposerHelper { +class UltraHonkComposerHelper { public: + using Flavor = flavor::Ultra; + using CircuitConstructor = Flavor::CircuitConstructor; + using ProvingKey = Flavor::ProvingKey; + using VerificationKey = Flavor::VerificationKey; + // TODO(#340)(luke): In the split composers, NUM_RANDOMIZED_GATES has replaced NUM_RESERVED_GATES (in some places) // to determine the next-power-of-2 circuit size. (There are some places in this composer that still use // NUM_RESERVED_GATES). Therefore for consistency within this composer itself, and consistency with the original // Ultra Composer, this value must match that of NUM_RESERVED_GATES. This issue needs to be reconciled // simultaneously here and in the other split composers. static constexpr size_t NUM_RANDOMIZED_GATES = 4; // equal to the number of multilinear evaluations leaked - static constexpr size_t program_width = CircuitConstructor::program_width; - std::vector wire_polynomials; - std::shared_ptr circuit_proving_key; - std::shared_ptr circuit_verification_key; + static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; + std::shared_ptr proving_key; + std::shared_ptr verification_key; // TODO(#218)(kesha): we need to put this into the commitment key, so that the composer doesn't have to handle srs // at all std::shared_ptr crs_factory_; @@ -45,9 +47,9 @@ template class UltraHonkComposerHelper { : crs_factory_(std::move(crs_factory)) {} - UltraHonkComposerHelper(std::shared_ptr p_key, std::shared_ptr v_key) - : circuit_proving_key(std::move(p_key)) - , circuit_verification_key(std::move(v_key)) + UltraHonkComposerHelper(std::shared_ptr p_key, std::shared_ptr v_key) + : proving_key(std::move(p_key)) + , verification_key(std::move(v_key)) {} UltraHonkComposerHelper(UltraHonkComposerHelper&& other) noexcept = default; @@ -58,8 +60,8 @@ template class UltraHonkComposerHelper { void finalize_circuit(CircuitConstructor& circuit_constructor) { circuit_constructor.finalize_circuit(); }; - std::shared_ptr compute_proving_key(const CircuitConstructor& circuit_constructor); - // std::shared_ptr compute_verification_key(const CircuitConstructor& circuit_constructor); + std::shared_ptr compute_proving_key(const CircuitConstructor& circuit_constructor); + // std::shared_ptr compute_verification_key(const CircuitConstructor& circuit_constructor); void compute_witness(CircuitConstructor& circuit_constructor); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/standard_honk_composer.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/standard_honk_composer.hpp index d99033e67d2..ea60cb6a2ad 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/standard_honk_composer.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/standard_honk_composer.hpp @@ -3,8 +3,6 @@ #include "composer_helper/standard_honk_composer_helper.hpp" #include "barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp" #include "barretenberg/srs/reference_string/file_reference_string.hpp" -#include "barretenberg/transcript/manifest.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" #include "barretenberg/proof_system/types/merkle_hash_type.hpp" #include "barretenberg/proof_system/types/pedersen_commitment_type.hpp" @@ -17,22 +15,28 @@ namespace proof_system::honk { */ class StandardHonkComposer { public: - static constexpr ComposerType type = ComposerType::STANDARD_HONK; + // TODO(#426): This doesn't belong here static constexpr merkle::HashType merkle_hash_type = merkle::HashType::LOOKUP_PEDERSEN; static constexpr pedersen::CommitmentType commitment_type = pedersen::CommitmentType::FIXED_BASE_PEDERSEN; + using Flavor = flavor::Standard; + using CircuitConstructor = StandardCircuitConstructor; + using ProvingKey = typename Flavor::ProvingKey; + using VerificationKey = typename Flavor::VerificationKey; + static constexpr ComposerType type = ComposerType::STANDARD_HONK; // TODO(Cody): Get rid of this. + static constexpr size_t UINT_LOG2_BASE = 2; // An instantiation of the circuit constructor that only depends on arithmetization, not on the proof system - StandardCircuitConstructor circuit_constructor; + CircuitConstructor circuit_constructor; // Composer helper contains all proof-related material that is separate from circuit creation such as: // 1) Proving and verification keys // 2) CRS // 3) Converting variables to witness vectors/polynomials - StandardHonkComposerHelper composer_helper; + StandardHonkComposerHelper composer_helper; // Leaving it in for now just in case bool contains_recursive_proof = false; - static constexpr size_t num_wires = StandardCircuitConstructor::num_wires; + static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; /**Standard methods*/ @@ -61,8 +65,8 @@ class StandardHonkComposer { {} - StandardHonkComposer(std::shared_ptr const& p_key, - std::shared_ptr const& v_key, + StandardHonkComposer(std::shared_ptr const& p_key, + std::shared_ptr const& v_key, size_t size_hint = 0) : circuit_constructor(size_hint) , composer_helper(p_key, v_key) @@ -165,12 +169,12 @@ class StandardHonkComposer { /**Proof and verification-related methods*/ - std::shared_ptr compute_proving_key() + std::shared_ptr compute_proving_key() { return composer_helper.compute_proving_key(circuit_constructor); } - std::shared_ptr compute_verification_key() + std::shared_ptr compute_verification_key() { return composer_helper.compute_verification_key(circuit_constructor); } @@ -180,7 +184,7 @@ class StandardHonkComposer { void compute_witness() { composer_helper.compute_witness(circuit_constructor); }; StandardVerifier create_verifier() { return composer_helper.create_verifier(circuit_constructor); } - StandardProver create_prover() { return composer_helper.create_prover(circuit_constructor); }; + StandardProver create_prover() { return composer_helper.create_prover(circuit_constructor); }; size_t& num_gates; std::vector& variables; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp index d481d2083d6..78a8c930ada 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/standard_honk_composer.test.cpp @@ -1,12 +1,16 @@ #include "standard_honk_composer.hpp" #include "barretenberg/honk/sumcheck/relations/relation.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" +#include #include +#include #include "barretenberg/honk/proof_system/prover.hpp" #include "barretenberg/honk/sumcheck/sumcheck_round.hpp" #include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" #include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" +#include "barretenberg/polynomials/polynomial.hpp" + +#pragma GCC diagnostic ignored "-Wunused-variable" #include "barretenberg/honk/utils/grand_product_delta.hpp" #include @@ -40,22 +44,22 @@ TEST(StandardHonkComposer, SigmaIDCorrectness) barretenberg::fr right = barretenberg::fr::one(); // Let's check that indices are the same and nothing is lost, first - for (size_t j = 0; j < composer.num_wires; ++j) { - std::string index = std::to_string(j + 1); - const auto& sigma_j = proving_key->polynomial_store.get("sigma_" + index + "_lagrange"); + size_t wire_idx = 0; + for (auto& sigma_polynomial : proving_key->get_sigma_polynomials()) { for (size_t i = 0; i < n; ++i) { - left *= (gamma + j * n + i); - right *= (gamma + sigma_j[i]); + left *= (gamma + wire_idx * n + i); + right *= (gamma + sigma_polynomial[i]); } // Ensure that the public inputs cycles are correctly broken // and fix the cycle by adding the extra terms - if (j == 0) { + if (wire_idx == 0) { for (size_t i = 0; i < num_public_inputs; ++i) { - EXPECT_EQ(sigma_j[i], -fr(i + 1)); + EXPECT_EQ(sigma_polynomial[i], -fr(i + 1)); left *= (gamma - (i + 1)); right *= (gamma + (n + i)); } } + ++wire_idx; } EXPECT_EQ(left, right); @@ -66,11 +70,14 @@ TEST(StandardHonkComposer, SigmaIDCorrectness) // Now let's check that witness values correspond to the permutation composer.compute_witness(); - for (size_t j = 0; j < composer.num_wires; ++j) { + auto permutation_polynomials = proving_key->get_sigma_polynomials(); + auto id_polynomials = proving_key->get_id_polynomials(); + auto wire_polynomials = proving_key->get_wires(); + for (size_t j = 0; j < StandardHonkComposer::NUM_WIRES; ++j) { std::string index = std::to_string(j + 1); - const auto& permutation_polynomial = proving_key->polynomial_store.get("sigma_" + index + "_lagrange"); - const auto& witness_polynomial = composer.composer_helper.wire_polynomials[j]; - const auto& id_polynomial = proving_key->polynomial_store.get("id_" + index + "_lagrange"); + const auto& permutation_polynomial = permutation_polynomials[j]; + const auto& witness_polynomial = wire_polynomials[j]; + const auto& id_polynomial = id_polynomials[j]; // left = ∏ᵢ,ⱼ(ωᵢ,ⱼ + β⋅ind(i,j) + γ) // right = ∏ᵢ,ⱼ(ωᵢ,ⱼ + β⋅σ(i,j) + γ) for (size_t i = 0; i < proving_key->circuit_size; ++i) { @@ -156,7 +163,8 @@ TEST(StandardHonkComposer, LagrangeCorrectness) random_polynomial[i] = barretenberg::fr::random_element(); } // Compute inner product of random polynomial and the first lagrange polynomial - barretenberg::polynomial first_lagrange_polynomial = proving_key->polynomial_store.get("L_first_lagrange"); + + barretenberg::polynomial first_lagrange_polynomial = proving_key->lagrange_first; barretenberg::fr first_product(0); for (size_t i = 0; i < proving_key->circuit_size; i++) { first_product += random_polynomial[i] * first_lagrange_polynomial[i]; @@ -164,7 +172,7 @@ TEST(StandardHonkComposer, LagrangeCorrectness) EXPECT_EQ(first_product, random_polynomial[0]); // Compute inner product of random polynomial and the last lagrange polynomial - barretenberg::polynomial last_lagrange_polynomial = proving_key->polynomial_store.get("L_last_lagrange"); + auto last_lagrange_polynomial = proving_key->lagrange_last; barretenberg::fr last_product(0); for (size_t i = 0; i < proving_key->circuit_size; i++) { last_product += random_polynomial[i] * last_lagrange_polynomial[i]; @@ -207,14 +215,8 @@ TEST(StandardHonkComposer, AssertEquals) auto get_maximum_cycle = [](auto& composer) { // Compute the proving key for sigma polynomials auto proving_key = composer.compute_proving_key(); - auto permutation_length = composer.num_wires * proving_key->circuit_size; - std::vector sigma_polynomials; - - // Put the sigma polynomials into a vector for easy access - for (size_t i = 0; i < composer.num_wires; i++) { - std::string index = std::to_string(i + 1); - sigma_polynomials.push_back(proving_key->polynomial_store.get("sigma_" + index + "_lagrange")); - } + auto permutation_length = composer.NUM_WIRES * proving_key->circuit_size; + auto sigma_polynomials = proving_key->get_sigma_polynomials(); // Let's compute the maximum cycle size_t maximum_cycle = 0; @@ -300,8 +302,7 @@ TEST(StandardHonkComposer, VerificationKeyCreation) // There is nothing we can really check apart from the fact that constraint selectors and permutation selectors were // committed to, we simply check that the verification key now contains the appropriate number of constraint and // permutation selector commitments. This method should work with any future arithemtization. - EXPECT_EQ(verification_key->commitments.size(), - composer.circuit_constructor.selectors.size() + composer.num_wires * 2 + 2); + EXPECT_EQ(verification_key->size(), composer.circuit_constructor.selectors.size() + composer.NUM_WIRES * 2 + 2); } TEST(StandardHonkComposer, BaseCase) @@ -350,4 +351,37 @@ TEST(StandardHonkComposer, TwoGates) run_test(/* expect_verified=*/true); run_test(/* expect_verified=*/false); } + +TEST(StandardHonkComposer, SumcheckEvaluations) +{ + auto run_test = [](bool expected_result) { + auto composer = StandardHonkComposer(); + fr a = fr::one(); + // Construct a small but non-trivial circuit + uint32_t a_idx = composer.add_public_variable(a); + fr b = fr::one(); + fr c = a + b; + fr d = a + c; + + if (expected_result == false) { + d += 1; + }; + + uint32_t b_idx = composer.add_variable(b); + uint32_t c_idx = composer.add_variable(c); + uint32_t d_idx = composer.add_variable(d); + for (size_t i = 0; i < 16; i++) { + composer.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); + composer.create_add_gate({ d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); + } + auto prover = composer.create_prover(); + plonk::proof proof = prover.construct_proof(); + + auto verifier = composer.create_verifier(); + bool verified = verifier.verify_proof(proof); + ASSERT_EQ(verified, expected_result); + }; + run_test(/*expected_result=*/true); + run_test(/*expected_result=*/false); +} } // namespace test_standard_honk_composer diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.hpp index dfdf5ff8dae..9bbdf0f9c08 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.hpp @@ -3,8 +3,7 @@ #include "barretenberg/honk/proof_system/ultra_prover.hpp" #include "barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp" #include "barretenberg/honk/composer/composer_helper/ultra_honk_composer_helper.hpp" -#include - +#include "barretenberg/honk/flavor/ultra.hpp" namespace proof_system::honk { class UltraHonkComposer { @@ -16,7 +15,12 @@ class UltraHonkComposer { // 1) Proving and verification keys // 2) CRS // 3) Converting variables to witness vectors/polynomials - UltraHonkComposerHelper composer_helper; + using Flavor = honk::flavor::Ultra; + using CircuitConstructor = UltraCircuitConstructor; + using ProvingKey = typename Flavor::ProvingKey; + using VerificationKey = typename Flavor::VerificationKey; + + UltraHonkComposerHelper composer_helper; size_t& num_gates; UltraHonkComposer() @@ -31,8 +35,8 @@ class UltraHonkComposer { , composer_helper(crs_factory) , num_gates(circuit_constructor.num_gates){}; - UltraHonkComposer(std::shared_ptr const& p_key, - std::shared_ptr const& v_key, + UltraHonkComposer(std::shared_ptr const& p_key, + std::shared_ptr const& v_key, size_t size_hint = 0); UltraHonkComposer(UltraHonkComposer&& other) = default; UltraHonkComposer& operator=(UltraHonkComposer&& other) = delete; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp index a36d563a794..c2dd80a0c2f 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/composer/ultra_honk_composer.test.cpp @@ -3,7 +3,6 @@ #include "barretenberg/honk/proof_system/ultra_prover.hpp" #include "barretenberg/honk/sumcheck/relations/relation.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" #include #include #include "barretenberg/honk/proof_system/prover.hpp" @@ -19,6 +18,7 @@ #include #include +#include using namespace proof_system::honk; @@ -41,88 +41,102 @@ std::vector add_variables(auto& composer, std::vector variables) */ void verify_consistency(honk::UltraProver& honk_prover, plonk::UltraProver& plonk_prover) { - auto& honk_store = honk_prover.key->polynomial_store; auto& plonk_store = plonk_prover.key->polynomial_store; - // Check that all selectors and table polynomials agree (aside from the final element which will differ - // due to not enforcing non-zero polynomials in Honk). - for (auto& entry : honk_store) { - std::string key = entry.first; - bool is_selector = (key.find("q_") != std::string::npos) || (key.find("table_type") != std::string::npos); - bool is_table = (key.find("table_value_") != std::string::npos); - if (plonk_store.contains(key) && (is_selector || is_table)) { - // check equality for all but final entry - for (size_t i = 0; i < honk_store.get(key).size() - 1; ++i) { - ASSERT_EQ(honk_store.get(key)[i], plonk_store.get(key)[i]); - } - } - } - - // Check that sorted witness-table polynomials agree - for (auto& entry : honk_store) { - std::string key = entry.first; - bool is_sorted_table = (key.find("s_") != std::string::npos); - if (plonk_store.contains(key) && is_sorted_table) { - ASSERT_EQ(honk_store.get(key), plonk_store.get(key)); + // Check consistency of table polys (aside from final entry) + auto honk_table_polys = honk_prover.key->get_table_polynomials(); + for (size_t i = 0; i < 4; ++i) { + std::string label = "table_value_" + std::to_string(i + 1) + "_lagrange"; + for (size_t j = 0; j < honk_prover.key->circuit_size - 1; ++j) { + ASSERT_EQ(honk_table_polys[i][j], plonk_store.get(label)[j]); } } - // Check that all wires agree - // Note: for Honk, wires are owned directly by the prover. For Plonk they are stored in the key. + // Check consistency of sorted concatenated witness-table polys (aside from final entry) + auto honk_sorted_polys = honk_prover.key->get_sorted_polynomials(); for (size_t i = 0; i < 4; ++i) { - std::string label = "w_" + std::to_string(i + 1) + "_lagrange"; - ASSERT_EQ(honk_prover.wire_polynomials[i], plonk_prover.key->polynomial_store.get(label)); - } -} - -/** - * @brief TEMPORARY (verbose) method for checking consistency of polynomials computed by Ultra Plonk/Honk composers - * - * @param honk_prover - * @param plonk_prover - */ -void check_consistency(honk::UltraProver& honk_prover, plonk::UltraProver& plonk_prover) -{ - auto& honk_store = honk_prover.key->polynomial_store; - auto& plonk_store = plonk_prover.key->polynomial_store; - for (auto& entry : honk_store) { - std::string key = entry.first; - if (plonk_store.contains(key)) { - - bool polys_equal = (honk_store.get(key) == plonk_store.get(key)); - if (polys_equal) { - info("Equal: ", key); - } - if (!polys_equal) { - info("UNEQUAL: ", key); - } + std::string label = "s_" + std::to_string(i + 1) + "_lagrange"; + for (size_t j = 0; j < honk_prover.key->circuit_size - 1; ++j) { + ASSERT_EQ(honk_sorted_polys[i][j], plonk_store.get(label)[j]); } } - for (size_t i = 0; i < 4; ++i) { - std::string label = "w_" + std::to_string(i + 1) + "_lagrange"; - bool wire_equal = (honk_prover.wire_polynomials[i] == plonk_prover.key->polynomial_store.get(label)); - if (wire_equal) { - info("Wire Equal: ", i); - } - if (!wire_equal) { - info("Wire UNEQUAL: ", i); + // Check consistency of selectors (aside from final entry) + auto honk_selectors = honk_prover.key->get_selectors(); + std::vector> plonk_selectors = { plonk_prover.key->polynomial_store.get("q_m_lagrange"), + plonk_prover.key->polynomial_store.get("q_c_lagrange"), + plonk_prover.key->polynomial_store.get("q_1_lagrange"), + plonk_prover.key->polynomial_store.get("q_2_lagrange"), + plonk_prover.key->polynomial_store.get("q_3_lagrange"), + plonk_prover.key->polynomial_store.get("q_4_lagrange"), + plonk_prover.key->polynomial_store.get("q_arith_lagrange"), + plonk_prover.key->polynomial_store.get("q_sort_lagrange"), + plonk_prover.key->polynomial_store.get("q_elliptic_lagrange"), + plonk_prover.key->polynomial_store.get("q_aux_lagrange"), + plonk_prover.key->polynomial_store.get("table_type_lagrange") }; + + for (size_t i = 0; i < plonk_selectors.size(); ++i) { + for (size_t j = 0; j < honk_prover.key->circuit_size - 1; ++j) { + ASSERT_EQ(honk_selectors[i][j], plonk_selectors[i][j]); } } - // std::string label = "w_1_lagrange"; - // for (size_t i = 0; i < plonk_store.get(label).size(); ++i) { - // auto val_honk = honk_prover.wire_polynomials[0][i]; - // // auto val_honk = honk_store.get(label)[i]; - // auto val_plonk = plonk_store.get(label)[i]; - // if (val_honk != val_plonk) { - // info("UNEQUAL index = ", i); - // info("honk: ",val_honk); - // info("plonk: ", val_plonk); - // } - // } + // Check that all wires agree + // Note: for Honk, wires are owned directly by the prover. For Plonk they are stored in the key. + ASSERT_EQ(honk_prover.key->w_l, plonk_prover.key->polynomial_store.get("w_1_lagrange")); + ASSERT_EQ(honk_prover.key->w_r, plonk_prover.key->polynomial_store.get("w_2_lagrange")); + ASSERT_EQ(honk_prover.key->w_o, plonk_prover.key->polynomial_store.get("w_3_lagrange")); + ASSERT_EQ(honk_prover.key->w_4, plonk_prover.key->polynomial_store.get("w_4_lagrange")); } +// /** +// * @brief TEMPORARY (verbose) method for checking consistency of polynomials computed by Ultra Plonk/Honk composers +// * +// * @param honk_prover +// * @param plonk_prover +// */ +// void check_consistency(honk::UltraProver& honk_prover, plonk::UltraProver& plonk_prover) +// { +// auto& honk_store = honk_prover.key->polynomial_store; +// auto& plonk_store = plonk_prover.key->polynomial_store; +// for (auto& entry : honk_store) { +// std::string key = entry.first; +// if (plonk_store.contains(key)) { + +// bool polys_equal = (honk_store.get(key) == plonk_store.get(key)); +// if (polys_equal) { +// info("Equal: ", key); +// } +// if (!polys_equal) { +// info("UNEQUAL: ", key); +// } +// } +// } + +// for (size_t i = 0; i < 4; ++i) { +// std::string label = "w_" + std::to_string(i + 1) + "_lagrange"; +// bool wire_equal = (honk_prover.wire_polynomials[i] == plonk_prover.key->polynomial_store.get(label)); +// if (wire_equal) { +// info("Wire Equal: ", i); +// } +// if (!wire_equal) { +// info("Wire UNEQUAL: ", i); +// } +// } + +// // std::string label = "w_1_lagrange"; +// // for (size_t i = 0; i < plonk_store.get(label).size(); ++i) { +// // auto val_honk = honk_prover.wire_polynomials[0][i]; +// // // auto val_honk = honk_store.get(label)[i]; +// // auto val_plonk = plonk_store.get(label)[i]; +// // if (val_honk != val_plonk) { +// // info("UNEQUAL index = ", i); +// // info("honk: ",val_honk); +// // info("plonk: ", val_plonk); +// // } +// // } +// } + TEST(UltraHonkComposer, create_gates_from_plookup_accumulators) { auto honk_composer = UltraHonkComposer(); @@ -893,7 +907,6 @@ TEST(UltraHonkComposer, rom) auto honk_prover = honk_composer.create_prover(); auto plonk_prover = plonk_composer.create_prover(); - check_consistency(honk_prover, plonk_prover); verify_consistency(honk_prover, plonk_prover); } diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.hpp deleted file mode 100644 index 05e7f2fb508..00000000000 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.hpp +++ /dev/null @@ -1,256 +0,0 @@ -#pragma once -#include -#include -#include "barretenberg/common/log.hpp" -#include "barretenberg/proof_system/arithmetization/arithmetization.hpp" -#include "barretenberg/transcript/manifest.hpp" - -namespace proof_system::honk { -// TODO(Cody) This _should_ be shared with Plonk, but it isn't. -struct StandardArithmetization { - /** - * @brief All of the multivariate polynomials used by the Standard Honk Prover. - * @details The polynomials are broken into three categories: precomputed, witness, and shifted. - * This separation must be maintained to allow for programmatic access, but the ordering of the - * polynomials can be permuted within each category if necessary. Polynomials can also be added - * or removed (assuming consistency with the prover algorithm) but the constants describing the - * number of polynomials in each category must be manually updated. - * - */ - enum POLYNOMIAL { - /* --- PRECOMPUTED POLYNOMIALS --- */ - Q_C, - Q_L, - Q_R, - Q_O, - Q_M, - SIGMA_1, - SIGMA_2, - SIGMA_3, - ID_1, - ID_2, - ID_3, - LAGRANGE_FIRST, - LAGRANGE_LAST, // = LAGRANGE_N-1 whithout ZK, but can be less - /* --- WITNESS POLYNOMIALS --- */ - W_L, - W_R, - W_O, - Z_PERM, - /* --- SHIFTED POLYNOMIALS --- */ - Z_PERM_SHIFT, - /* --- --- */ - COUNT // for programmatic determination of NUM_POLYNOMIALS - }; - - static constexpr size_t NUM_POLYNOMIALS = POLYNOMIAL::COUNT; - static constexpr size_t NUM_SHIFTED_POLYNOMIALS = 1; - static constexpr size_t NUM_PRECOMPUTED_POLYNOMIALS = 13; - static constexpr size_t NUM_UNSHIFTED_POLYNOMIALS = NUM_POLYNOMIALS - NUM_SHIFTED_POLYNOMIALS; - - // *** WARNING: The order of this array must be manually updated to match POLYNOMIAL enum *** - // TODO(luke): This is a temporary measure to associate the above enum with sting tags. Its only needed because - // the - // polynomials/commitments in the prover/verifier are stored in maps. This storage could be converted to simple - // arrays at which point these string tags can be removed. - inline static const std::array ENUM_TO_COMM = { - "Q_C", "Q_1", "Q_2", "Q_3", "Q_M", "SIGMA_1", - "SIGMA_2", "SIGMA_3", "ID_1", "ID_2", "ID_3", "LAGRANGE_FIRST", - "LAGRANGE_LAST", "W_1", "W_2", "W_3", "Z_PERM", "Z_PERM_SHIFT" - }; -}; -} // namespace proof_system::honk - -namespace proof_system::honk { -struct StandardHonk { - public: - // This whole file is broken; changes here are in anticipation of a follow-up rework of the flavor specificaiton. - using Arithmetization = arithmetization::Standard; - using MULTIVARIATE = proof_system::honk::StandardArithmetization::POLYNOMIAL; - // // TODO(Cody): Where to specify? is this polynomial manifest size? - // static constexpr size_t STANDARD_HONK_MANIFEST_SIZE = 16; - // TODO(Cody): Maybe relation should be supplied and this should be computed as is done in sumcheck? - // Then honk::StandardHonk (or whatever we rename it) would become an alias for a Honk flavor with a - // certain set of parameters, including the relations? - static constexpr size_t MAX_RELATION_LENGTH = 5; - - // TODO(Cody): should extract this from the parameter pack. Maybe that should be done here? - - // num_sumcheck_rounds = 1 if using quotient polynomials, otherwise = number of sumcheck rounds - static transcript::Manifest create_manifest(const size_t num_public_inputs, const size_t num_sumcheck_rounds = 1) - { - constexpr size_t g1_size = 64; - constexpr size_t fr_size = 32; - const size_t public_input_size = fr_size * num_public_inputs; - // clang-format off - /* A RoundManifest describes data that will be put in or extracted from a transcript. - Here we have (1 + 7 + num_sumcheck_rounds)-many RoundManifests. */ - std::vector manifest_rounds; - - // Round 0 - manifest_rounds.emplace_back(transcript::Manifest::RoundManifest( - { - { .name = "circuit_size", .num_bytes = 4, .derived_by_verifier = true }, - { .name = "public_input_size", .num_bytes = 4, .derived_by_verifier = true } - }, - /* challenge_name = */ "init", - /* num_challenges_in = */ 1)); - - // Round 1 - manifest_rounds.emplace_back(transcript::Manifest::RoundManifest( - { /* this is a noop */ }, - /* challenge_name = */ "eta", - /* num_challenges_in = */ 0)); - - // Round 2 - manifest_rounds.emplace_back(transcript::Manifest::RoundManifest( - { - { .name = "public_inputs", .num_bytes = public_input_size, .derived_by_verifier = false }, - { .name = "W_1", .num_bytes = g1_size, .derived_by_verifier = false }, - { .name = "W_2", .num_bytes = g1_size, .derived_by_verifier = false }, - { .name = "W_3", .num_bytes = g1_size, .derived_by_verifier = false }, - }, - /* challenge_name = */ "beta", - /* num_challenges_in = */ 2) // also produce "gamma" - ); - - // Round 3 - manifest_rounds.emplace_back(transcript::Manifest::RoundManifest( - { { .name = "Z_PERM", .num_bytes = g1_size, .derived_by_verifier = false } }, - /* challenge_name = */ "alpha", - /* num_challenges_in = */ 2) - ); - - // Rounds 4, ... 4 + num_sumcheck_rounds-1 - for (size_t i = 0; i < num_sumcheck_rounds; i++) { - auto label = std::to_string(i); - manifest_rounds.emplace_back( - transcript::Manifest::RoundManifest( - { - { .name = "univariate_" + label, .num_bytes = fr_size * honk::StandardHonk::MAX_RELATION_LENGTH, .derived_by_verifier = false } - }, - /* challenge_name = */ "u_" + label, - /* num_challenges_in = */ 1)); - } - - // Round 5 + num_sumcheck_rounds - manifest_rounds.emplace_back(transcript::Manifest::RoundManifest( - { - { .name = "multivariate_evaluations", .num_bytes = fr_size * honk::StandardArithmetization::NUM_POLYNOMIALS, .derived_by_verifier = false, .challenge_map_index = 0 }, - }, - /* challenge_name = */ "rho", - /* num_challenges_in = */ 1)); /* TODO(Cody): magic number! Where should this be specified? */ - - // Rounds 6 + num_sumcheck_rounds, ... , 6 + 2 * num_sumcheck_rounds - 1 - std::vector fold_commitment_entries; - for (size_t i = 1; i < num_sumcheck_rounds; i++) { - fold_commitment_entries.emplace_back(transcript::Manifest::ManifestEntry( - { .name = "FOLD_" + std::to_string(i), .num_bytes = g1_size, .derived_by_verifier = false })); - }; - manifest_rounds.emplace_back(transcript::Manifest::RoundManifest( - fold_commitment_entries, - /* challenge_name = */ "r", - /* num_challenges_in */ 1)); - - // Rounds 6 + 2 * num_sumcheck_rounds, ..., 6 + 3 * num_sumcheck_rounds - std::vector gemini_evaluation_entries; - for (size_t i = 0; i < num_sumcheck_rounds; i++) { - gemini_evaluation_entries.emplace_back(transcript::Manifest::ManifestEntry( - { .name = "a_" + std::to_string(i), .num_bytes = fr_size, .derived_by_verifier = false })); - }; - manifest_rounds.emplace_back(transcript::Manifest::RoundManifest( - gemini_evaluation_entries, - /* challenge_name = */ "nu", - /* num_challenges_in */ 1)); - - // Round 7 + 3 * num_sumcheck_rounds - manifest_rounds.emplace_back( - transcript::Manifest::RoundManifest( - { - { .name = "Q", .num_bytes = g1_size, .derived_by_verifier = false } - }, - /* challenge_name = */ "z", - /* num_challenges_in */ 1)); - - // Round 8 + 3 * num_sumcheck_rounds - manifest_rounds.emplace_back( - transcript::Manifest::RoundManifest( - { - { .name = "W", .num_bytes = g1_size, .derived_by_verifier = false } - }, - /* challenge_name = */ "separator", - /* num_challenges_in */ 1)); - - // clang-format on - - auto output = transcript::Manifest(manifest_rounds); - return output; - } -}; - -struct UltraArithmetization { - /** - * @brief All of the multivariate polynomials used by the Ultra Honk Prover. - * @details The polynomials are broken into three categories: precomputed, witness, and shifted. - * This separation must be maintained to allow for programmatic access, but the ordering of the - * polynomials can be permuted within each category if necessary. Polynomials can also be added - * or removed (assuming consistency with the prover algorithm) but the constants describing the - * number of polynomials in each category must be manually updated. - * - */ - enum POLYNOMIAL { - /* --- PRECOMPUTED POLYNOMIALS --- */ - Q_C, - Q_L, - Q_R, - Q_O, - Q_4, - Q_M, - QARITH, - QSORT, - QELLIPTIC, - QAUX, - QLOOKUPTYPE, - SIGMA_1, - SIGMA_2, - SIGMA_3, - SIGMA_4, - ID_1, - ID_2, - ID_3, - ID_4, - TABLE_1, - TABLE_2, - TABLE_3, - TABLE_4, - LAGRANGE_FIRST, - LAGRANGE_LAST, // = LAGRANGE_N-1 whithout ZK, but can be less - /* --- WITNESS POLYNOMIALS --- */ - W_L, - W_R, - W_O, - W_4, - S_1, - S_2, - S_3, - S_4, - S_ACCUM, - Z_PERM, - Z_LOOKUP, - /* --- SHIFTED POLYNOMIALS --- */ - W_1_SHIFT, - W_2_SHIFT, - W_3_SHIFT, - W_4_SHIFT, - TABLE_1_SHIFT, - TABLE_2_SHIFT, - TABLE_3_SHIFT, - TABLE_4_SHIFT, - S_ACCUM_SHIFT, - Z_PERM_SHIFT, - Z_LOOKUP_SHIFT, - /* --- --- */ - COUNT // for programmatic determination of NUM_POLYNOMIALS - }; -}; -} // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp index 06accb92651..1211313af4a 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp @@ -1,30 +1,145 @@ -#include "flavor.hpp" - +#include "barretenberg/honk/flavor/standard.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/srs/reference_string/reference_string.hpp" +#include #include -namespace test_flavor { - -// // TODO(Cody) This seems like a good idea, but I'm not sure why. -// TEST(Flavor, StandardArithmetization){ -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::W_L, 0); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::W_R, 1); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::W_O, 2); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Z_PERM, 3); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Z_PERM_SHIFT, 4); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_M, 5); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_L, 6); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_R, 7); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_O, 8); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_C, 9); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::SIGMA_1, 10); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::SIGMA_2, 11); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::SIGMA_3, 12); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::ID_1, 13); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::ID_2, 14); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::ID_3, 15); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::LAGRANGE_FIRST, 16); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::COUNT, 17); - -// } - -} // namespace test_flavor +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" +#pragma GCC diagnostic ignored "-Wunused-variable" + +namespace proof_system::test_flavor { +TEST(Flavor, StandardGetters) +{ + using Flavor = proof_system::honk::flavor::Standard; + using FF = Flavor::FF; + using ProvingKey = typename Flavor::ProvingKey; + + ProvingKey proving_key = []() { + auto crs_factory = ReferenceStringFactory(); + auto crs = crs_factory.get_prover_crs(4); + return Flavor::ProvingKey(/*circuit_size=*/4, /*num_public_inputs=*/0, crs, ComposerType::STANDARD); + }(); + + // set + size_t coset_idx = 0; + for (auto& id_poly : proving_key.get_id_polynomials()) { + typename Flavor::Polynomial new_poly(proving_key.circuit_size); + for (size_t i = 0; i < proving_key.circuit_size; ++i) { + id_poly[i] = coset_idx * proving_key.circuit_size + i; + } + ++coset_idx; + } + + // Polynomials in the proving key can be set through loops over subsets produced by the getters + EXPECT_EQ(proving_key.id_1[0], FF(0)); + EXPECT_EQ(proving_key.id_2[0], FF(4)); + EXPECT_EQ(proving_key.id_3[0], FF(8)); + + Flavor::VerificationKey verification_key; + Flavor::ProverPolynomials prover_polynomials; + Flavor::ExtendedEdges edges; + Flavor::PurportedEvaluations evals; + Flavor::CommitmentLabels commitment_labels; + + // Globals are also available through STL container sizes + EXPECT_EQ(prover_polynomials.size(), Flavor::NUM_ALL_ENTITIES); + // Shited polynomials have the righ tsize + EXPECT_EQ(prover_polynomials.size(), prover_polynomials.get_unshifted_then_shifted().size()); + // Commitment lables are stored in the flavor. + EXPECT_EQ(commitment_labels.w_r, "W_2"); + + auto get_test_polynomial = [](size_t& idx) { + Flavor::Polynomial poly(4); + for (size_t i = 0; i < 4; i++) { + poly[i] = idx++; + }; + return poly; + }; + + size_t idx = 0; + auto w_l = get_test_polynomial(idx); + auto w_r = get_test_polynomial(idx); + auto w_o = get_test_polynomial(idx); + auto z_perm = get_test_polynomial(idx); + auto z_perm_shift = get_test_polynomial(idx); + auto q_m = get_test_polynomial(idx); + auto q_l = get_test_polynomial(idx); + auto q_r = get_test_polynomial(idx); + auto q_o = get_test_polynomial(idx); + auto q_c = get_test_polynomial(idx); + auto sigma_1 = get_test_polynomial(idx); + auto sigma_2 = get_test_polynomial(idx); + auto sigma_3 = get_test_polynomial(idx); + auto id_1 = get_test_polynomial(idx); + auto id_2 = get_test_polynomial(idx); + auto id_3 = get_test_polynomial(idx); + auto lagrange_first = get_test_polynomial(idx); + auto lagrange_last = get_test_polynomial(idx); + + prover_polynomials.w_l = w_l; + prover_polynomials.w_r = w_r; + prover_polynomials.w_o = w_o; + prover_polynomials.z_perm = z_perm; + prover_polynomials.z_perm_shift = z_perm_shift; + prover_polynomials.q_m = q_m; + prover_polynomials.q_l = q_l; + prover_polynomials.q_r = q_r; + prover_polynomials.q_o = q_o; + prover_polynomials.q_c = q_c; + prover_polynomials.sigma_1 = sigma_1; + prover_polynomials.sigma_2 = sigma_2; + prover_polynomials.sigma_3 = sigma_3; + prover_polynomials.id_1 = id_1; + prover_polynomials.id_2 = id_2; + prover_polynomials.id_3 = id_3; + prover_polynomials.lagrange_first = lagrange_first; + prover_polynomials.lagrange_last = lagrange_last; + + // You can set polynomial values directly through the symbol names + // and then access the values through the getters. + idx = 0; + for (auto& poly : prover_polynomials.get_wires()) { + EXPECT_EQ(poly[0], 4 * idx); + EXPECT_EQ(poly[1], 4 * idx + 1); + EXPECT_EQ(poly[2], 4 * idx + 2); + EXPECT_EQ(poly[3], 4 * idx + 3); + ++idx; + }; + + idx = 4; // z_perm_shift is shifted + for (auto& poly : prover_polynomials.get_shifted()) { + EXPECT_EQ(poly[0], 4 * idx); + EXPECT_EQ(poly[1], 4 * idx + 1); + EXPECT_EQ(poly[2], 4 * idx + 2); + EXPECT_EQ(poly[3], 4 * idx + 3); + ++idx; + }; +} + +TEST(Flavor, AllEntitiesSpecialMemberFunctions) +{ + using Flavor = proof_system::honk::flavor::Standard; + using FF = Flavor::FF; + using FoldedPolynomials = Flavor::FoldedPolynomials; + using Polynomial = Polynomial; + + FoldedPolynomials polynomials_A; + std::vector random_poly{ 10 }; + for (auto& coeff : random_poly) { + coeff = FF::random_element(); + } + + // Test some special member functions. + + polynomials_A.w_l = random_poly; + + ASSERT_EQ(random_poly, polynomials_A.w_l); + + FoldedPolynomials polynomials_B(polynomials_A); + ASSERT_EQ(random_poly, polynomials_B.w_l); + + FoldedPolynomials polynomials_C(std::move(polynomials_B)); + ASSERT_EQ(random_poly, polynomials_C.w_l); +} + +} // namespace proof_system::test_flavor diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp new file mode 100644 index 00000000000..a88c1b6cfc8 --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp @@ -0,0 +1,275 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "barretenberg/honk/pcs/commitment_key.hpp" +#include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" +#include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/honk/transcript/transcript.hpp" +#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/polynomials/evaluation_domain.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp" +#include "barretenberg/srs/reference_string/reference_string.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" + +namespace proof_system::honk::flavor { + +/** + * @brief Standard Honk + * @details We built this flavor first because it is the most basic. Because of this, it will remain useful for testing + * various constructions. Future variants may exist with varying: underlying curve (here we use BN254); commitment + * scheme (here we use Gemini + Shplonk + KZG); zero knowlege property (it's not implemented yet, but in the future we + * will be able to toggle it on or off). + * + */ +class Standard { + public: + using CircuitConstructor = StandardCircuitConstructor; + using FF = barretenberg::fr; + using Polynomial = barretenberg::Polynomial; + using PolynomialHandle = std::span; + using G1 = barretenberg::g1; + using GroupElement = G1::element; + using Commitment = G1::affine_element; + using CommitmentHandle = G1::affine_element; + using PCSParams = pcs::kzg::Params; + + static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; + // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often + // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS` + static constexpr size_t NUM_ALL_ENTITIES = 18; + // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying + // assignment of witnesses. We again choose a neutral name. + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 13; + // The total number of witness entities not including shifts. + static constexpr size_t NUM_WITNESS_ENTITIES = 4; + + private: + /** + * @brief A base class labelling precomputed entities and (ordered) subsets of interest. + * @details Used to build the proving key and verification key. + */ + template + class PrecomputedEntities : public PrecomputedEntities_ { + public: + DataType& q_m = std::get<0>(this->_data); + DataType& q_l = std::get<1>(this->_data); + DataType& q_r = std::get<2>(this->_data); + DataType& q_o = std::get<3>(this->_data); + DataType& q_c = std::get<4>(this->_data); + DataType& sigma_1 = std::get<5>(this->_data); + DataType& sigma_2 = std::get<6>(this->_data); + DataType& sigma_3 = std::get<7>(this->_data); + DataType& id_1 = std::get<8>(this->_data); + DataType& id_2 = std::get<9>(this->_data); + DataType& id_3 = std::get<10>(this->_data); + DataType& lagrange_first = std::get<11>(this->_data); + DataType& lagrange_last = std::get<12>(this->_data); // = LAGRANGE_N-1 whithout ZK, but can be less + + std::vector get_selectors() override { return { q_m, q_l, q_r, q_o, q_c }; }; + std::vector get_sigma_polynomials() override { return { sigma_1, sigma_2, sigma_3 }; }; + std::vector get_id_polynomials() override { return { id_1, id_2, id_3 }; }; + }; + + /** + * @brief Container for all witness polynomials used/constructed by the prover. + * @details Shifts are not included here since they do not occupy their own memory. + */ + template + class WitnessEntities : public WitnessEntities_ { + public: + DataType& w_l = std::get<0>(this->_data); + DataType& w_r = std::get<1>(this->_data); + DataType& w_o = std::get<2>(this->_data); + DataType& z_perm = std::get<3>(this->_data); + + std::vector get_wires() override { return { w_l, w_r, w_o }; }; + }; + + /** + * @brief A base class labelling all entities (for instance, all of the polynomials used by the prover during + * sumcheck) in this Honk variant along with particular subsets of interest + * @details Used to build containers for: the prover's polynomial during sumcheck; the sumcheck's folded + * polynomials; the univariates consturcted during during sumcheck; the evaluations produced by sumcheck. + * + * Symbolically we have: AllEntities = PrecomputedEntities + WitnessEntities + "ShiftedEntities". It could be + * implemented as such, but we don't have this now. + */ + template + class AllEntities : public AllEntities_ { + public: + DataType& q_c = std::get<0>(this->_data); + DataType& q_l = std::get<1>(this->_data); + DataType& q_r = std::get<2>(this->_data); + DataType& q_o = std::get<3>(this->_data); + DataType& q_m = std::get<4>(this->_data); + DataType& sigma_1 = std::get<5>(this->_data); + DataType& sigma_2 = std::get<6>(this->_data); + DataType& sigma_3 = std::get<7>(this->_data); + DataType& id_1 = std::get<8>(this->_data); + DataType& id_2 = std::get<9>(this->_data); + DataType& id_3 = std::get<10>(this->_data); + DataType& lagrange_first = std::get<11>(this->_data); + DataType& lagrange_last = std::get<12>(this->_data); + DataType& w_l = std::get<13>(this->_data); + DataType& w_r = std::get<14>(this->_data); + DataType& w_o = std::get<15>(this->_data); + DataType& z_perm = std::get<16>(this->_data); + DataType& z_perm_shift = std::get<17>(this->_data); + + std::vector get_wires() override { return { w_l, w_r, w_o }; }; + + // Gemini-specific getters. + std::vector get_unshifted() override + { + return { q_c, q_l, q_r, q_o, q_m, sigma_1, sigma_2, sigma_3, id_1, id_2, id_3, lagrange_first, + lagrange_last, w_l, w_r, w_o, z_perm }; + }; + std::vector get_to_be_shifted() override { return { z_perm }; }; + std::vector get_shifted() override { return { z_perm_shift }; }; + + // TODO(Cody): It would be nice to define these constructors once in a base class template. + AllEntities() = default; + + AllEntities(const AllEntities& other) + : AllEntities_(other){}; + + AllEntities(AllEntities&& other) + : AllEntities_(other){}; + + AllEntities& operator=(const AllEntities& other) + { + if (this == &other) { + return *this; + } + AllEntities_::operator=(other); + return *this; + } + + AllEntities& operator=(AllEntities&& other) + { + AllEntities_::operator=(other); + return *this; + } + + ~AllEntities() = default; + }; + + public: + /** + * @brief The proving key is responsible for storing the polynomials used by the prover. + * @note TODO(Cody): Maybe multiple inheritance is the right thing here. In that case, nothing should eve inherit + * from ProvingKey. + */ + class ProvingKey : public ProvingKey_, + WitnessEntities> { + public: + // Expose constructors of the base class + using Base = ProvingKey_, + WitnessEntities>; + using Base::Base; + }; + + /** + * @brief The verification key is responsible for storing the the commitments to the precomputed (non-witness) + * polynomials used by the verifier. + * + * @note Note the discrepancy with what sort of data is stored here vs in the proving key. We may want to resolve + * that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our + * circuits. + */ + using VerificationKey = VerificationKey_>; + + /** + * @brief A container for polynomials handles; only stores spans. + */ + using ProverPolynomials = AllEntities; + + /** + * @brief A container for polynomials produced after the first round of sumcheck. + * @todo TODO(#394) Use polynomial classes for guaranteed memory alignment. + */ + using FoldedPolynomials = AllEntities, PolynomialHandle>; + + /** + * @brief A container for univariates produced during the hot loop in sumcheck. + * @todo TODO(#390): Simplify this by moving MAX_RELATION_LENGTH? + */ + template + using ExtendedEdges = + AllEntities, sumcheck::Univariate>; + + /** + * @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the + * evaluations of polynomials committed in earlier rounds. + */ + class PurportedEvaluations : public AllEntities { + public: + using Base = AllEntities; + using Base::Base; + PurportedEvaluations(std::array _data_in) { this->_data = _data_in; } + }; + + /** + * @brief A container for commitment labels. + * @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It + * has, however, been useful during debugging to have these labels available. + * + */ + class CommitmentLabels : public AllEntities { + public: + CommitmentLabels() + : AllEntities() + { + w_l = "W_1"; + w_r = "W_2"; + w_o = "W_3"; + z_perm = "Z_PERM"; + // The ones beginning with "__" are only used for debugging + z_perm_shift = "__Z_PERM_SHIFT"; + q_m = "__Q_M"; + q_l = "__Q_L"; + q_r = "__Q_R"; + q_o = "__Q_O"; + q_c = "__Q_C"; + sigma_1 = "__SIGMA_1"; + sigma_2 = "__SIGMA_2"; + sigma_3 = "__SIGMA_3"; + id_1 = "__ID_1"; + id_2 = "__ID_2"; + id_3 = "__ID_3"; + lagrange_first = "__LAGRANGE_FIRST"; + lagrange_last = "__LAGRANGE_LAST"; + }; + }; + + /** + * @brief A container for all commitments used by the verifier. + */ + class VerifierCommitments : public AllEntities { + public: + VerifierCommitments(std::shared_ptr verification_key) + { + // Initialize pre-computed commitments here, witness commitments during proof verification. + q_m = verification_key->q_m; + q_l = verification_key->q_l; + q_r = verification_key->q_r; + q_o = verification_key->q_o; + q_c = verification_key->q_c; + sigma_1 = verification_key->sigma_1; + sigma_2 = verification_key->sigma_2; + sigma_3 = verification_key->sigma_3; + id_1 = verification_key->id_1; + id_2 = verification_key->id_2; + id_3 = verification_key->id_3; + lagrange_first = verification_key->lagrange_first; + lagrange_last = verification_key->lagrange_last; + } + }; +}; + +} // namespace proof_system::honk::flavor diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp new file mode 100644 index 00000000000..f02947dd678 --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp @@ -0,0 +1,348 @@ +#pragma once +#include +#include +#include +#include +#include +#include +#include "barretenberg/honk/pcs/commitment_key.hpp" +#include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" +#include "barretenberg/ecc/curves/bn254/g1.hpp" +#include "barretenberg/honk/transcript/transcript.hpp" +#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/polynomials/evaluation_domain.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp" +#include "barretenberg/srs/reference_string/reference_string.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" + +namespace proof_system::honk::flavor { + +class Ultra { + public: + using CircuitConstructor = UltraCircuitConstructor; + using FF = barretenberg::fr; + using Polynomial = barretenberg::Polynomial; + using PolynomialHandle = std::span; + using G1 = barretenberg::g1; + using GroupElement = G1::element; + using Commitment = G1::affine_element; + using CommitmentHandle = G1::affine_element; + using PCSParams = pcs::kzg::Params; + + static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; + // The number of multivariate polynomials on which a sumcheck prover sumcheck operates (including shifts). We often + // need containers of this size to hold related data, so we choose a name more agnostic than `NUM_POLYNOMIALS` + static constexpr size_t NUM_ALL_ENTITIES = 47; + // The number of polynomials precomputed to describe a circuit and to aid a prover in constructing a satisfying + // assignment of witnesses. We again choose a neutral name. + static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; + // The total number of witness entities not including shifts. + static constexpr size_t NUM_WITNESS_ENTITIES = 11; + + private: + template + /** + * @brief A base class labelling precomputed entities and (ordered) subsets of interest. + * @details Used to build the proving key and verification key. + */ + class PrecomputedEntities : public PrecomputedEntities_ { + public: + DataType& q_m = std::get<0>(this->_data); + DataType& q_c = std::get<1>(this->_data); + DataType& q_l = std::get<2>(this->_data); + DataType& q_r = std::get<3>(this->_data); + DataType& q_o = std::get<4>(this->_data); + DataType& q_4 = std::get<5>(this->_data); + DataType& q_arith = std::get<6>(this->_data); + DataType& q_sort = std::get<7>(this->_data); + DataType& q_elliptic = std::get<8>(this->_data); + DataType& q_aux = std::get<9>(this->_data); + DataType& q_lookup = std::get<10>(this->_data); + DataType& sigma_1 = std::get<11>(this->_data); + DataType& sigma_2 = std::get<12>(this->_data); + DataType& sigma_3 = std::get<13>(this->_data); + DataType& sigma_4 = std::get<14>(this->_data); + DataType& id_1 = std::get<15>(this->_data); + DataType& id_2 = std::get<16>(this->_data); + DataType& id_3 = std::get<17>(this->_data); + DataType& id_4 = std::get<18>(this->_data); + DataType& table_1 = std::get<19>(this->_data); + DataType& table_2 = std::get<20>(this->_data); + DataType& table_3 = std::get<21>(this->_data); + DataType& table_4 = std::get<22>(this->_data); + DataType& lagrange_first = std::get<23>(this->_data); + DataType& lagrange_last = std::get<24>(this->_data); + + std::vector get_selectors() override + { + return { q_m, q_c, q_l, q_r, q_o, q_4, q_arith, q_sort, q_elliptic, q_aux, q_lookup }; + }; + std::vector get_sigma_polynomials() override { return { sigma_1, sigma_2, sigma_3, sigma_4 }; }; + std::vector get_id_polynomials() override { return { id_1, id_2, id_3, id_4 }; }; + + std::vector get_table_polynomials() { return { table_1, table_2, table_3, table_4 }; }; + }; + + /** + * @brief Container for all witness polynomials used/constructed by the prover. + * @details Shifts are not included here since they do not occupy their own memory. + */ + template + class WitnessEntities : public WitnessEntities_ { + public: + DataType& w_l = std::get<0>(this->_data); + DataType& w_r = std::get<1>(this->_data); + DataType& w_o = std::get<2>(this->_data); + DataType& w_4 = std::get<3>(this->_data); + DataType& sorted_1 = std::get<4>(this->_data); + DataType& sorted_2 = std::get<5>(this->_data); + DataType& sorted_3 = std::get<6>(this->_data); + DataType& sorted_4 = std::get<7>(this->_data); + DataType& sorted_accum = std::get<8>(this->_data); + DataType& z_perm = std::get<9>(this->_data); + DataType& z_lookup = std::get<10>(this->_data); + + std::vector get_wires() override { return { w_l, w_r, w_o, w_4 }; }; + // The sorted concatenations of table and witness data needed for plookup. + std::vector get_sorted_polynomials() { return { sorted_1, sorted_2, sorted_3, sorted_4 }; }; + }; + + /** + * @brief A base class labelling all entities (for instance, all of the polynomials used by the prover during + * sumcheck) in this Honk variant along with particular subsets of interest + * @details Used to build containers for: the prover's polynomial during sumcheck; the sumcheck's folded + * polynomials; the univariates consturcted during during sumcheck; the evaluations produced by sumcheck. + * + * Symbolically we have: AllEntities = PrecomputedEntities + WitnessEntities + "ShiftedEntities". It could be + * implemented as such, but we have this now. + */ + template + class AllEntities : public AllEntities_ { + public: + DataType& q_c = std::get<0>(this->_data); + DataType& q_l = std::get<1>(this->_data); + DataType& q_r = std::get<2>(this->_data); + DataType& q_o = std::get<3>(this->_data); + DataType& q_4 = std::get<4>(this->_data); + DataType& q_m = std::get<5>(this->_data); + DataType& q_arith = std::get<6>(this->_data); + DataType& q_sort = std::get<7>(this->_data); + DataType& q_elliptic = std::get<8>(this->_data); + DataType& q_aux = std::get<9>(this->_data); + DataType& q_lookup = std::get<10>(this->_data); + DataType& sigma_1 = std::get<11>(this->_data); + DataType& sigma_2 = std::get<12>(this->_data); + DataType& sigma_3 = std::get<13>(this->_data); + DataType& sigma_4 = std::get<14>(this->_data); + DataType& id_1 = std::get<15>(this->_data); + DataType& id_2 = std::get<16>(this->_data); + DataType& id_3 = std::get<17>(this->_data); + DataType& id_4 = std::get<18>(this->_data); + DataType& table_1 = std::get<19>(this->_data); + DataType& table_2 = std::get<20>(this->_data); + DataType& table_3 = std::get<21>(this->_data); + DataType& table_4 = std::get<22>(this->_data); + DataType& lagrange_first = std::get<23>(this->_data); + DataType& lagrange_last = std::get<24>(this->_data); + DataType& w_l = std::get<25>(this->_data); + DataType& w_r = std::get<26>(this->_data); + DataType& w_o = std::get<27>(this->_data); + DataType& w_4 = std::get<28>(this->_data); + DataType& sorted_1 = std::get<29>(this->_data); + DataType& sorted_2 = std::get<30>(this->_data); + DataType& sorted_3 = std::get<31>(this->_data); + DataType& sorted_4 = std::get<32>(this->_data); + DataType& sorted_accum = std::get<33>(this->_data); + DataType& z_perm = std::get<34>(this->_data); + DataType& z_lookup = std::get<35>(this->_data); + DataType& table_1_shift = std::get<36>(this->_data); + DataType& table_2_shift = std::get<37>(this->_data); + DataType& table_3_shift = std::get<38>(this->_data); + DataType& table_4_shift = std::get<39>(this->_data); + DataType& w_l_shift = std::get<40>(this->_data); + DataType& w_r_shift = std::get<41>(this->_data); + DataType& w_o_shift = std::get<42>(this->_data); + DataType& w_4_shift = std::get<43>(this->_data); + DataType& sorted_accum_shift = std::get<44>(this->_data); + DataType& z_perm_shift = std::get<45>(this->_data); + DataType& z_lookup_shift = std::get<46>(this->_data); + + std::vector get_wires() override { return { w_l, w_r, w_o, w_4 }; }; + // Gemini-specific getters. + std::vector get_unshifted() override + { + return { q_c, q_l, q_r, q_o, q_4, q_m, q_arith, q_sort, + q_elliptic, q_aux, q_lookup, sigma_1, sigma_2, sigma_3, sigma_4, id_1, + id_2, id_3, id_4, table_1, table_2, table_3, table_4, lagrange_first, + lagrange_last, w_l, w_r, w_o, w_4, sorted_1, sorted_2, sorted_3, + sorted_4, z_perm, z_lookup + + }; + }; + std::vector get_to_be_shifted() override { return { w_l, w_4, z_perm, z_lookup }; }; + std::vector get_shifted() override + { + return { w_l_shift, w_4_shift, z_perm_shift, z_lookup_shift }; + }; + + AllEntities() = default; + + AllEntities(const AllEntities& other) + : AllEntities_(other){}; + + AllEntities(AllEntities&& other) + : AllEntities_(other){}; + + AllEntities& operator=(const AllEntities& other) + { + if (this == &other) { + return *this; + } + AllEntities_::operator=(other); + return *this; + } + + AllEntities& operator=(AllEntities&& other) + { + AllEntities_::operator=(other); + return *this; + } + + ~AllEntities() = default; + }; + + public: + /** + * @brief The proving key is responsible for storing the polynomials used by the prover. + * @note TODO(Cody): Maybe multiple inheritance is the right thing here. In that case, nothing should eve inherit + * from ProvingKey. + */ + class ProvingKey : public ProvingKey_, + WitnessEntities> { + public: + // Expose constructors on the base class + using Base = ProvingKey_, + WitnessEntities>; + using Base::Base; + + std::vector memory_read_records; + std::vector memory_write_records; + + // The plookup wires that store plookup read data. + std::array get_table_column_wires() { return { w_l, w_r, w_o }; }; + }; + + /** + * @brief The verification key is responsible for storing the the commitments to the precomputed (non-witnessk) + * polynomials used by the verifier. + * + * @note Note the discrepancy with what sort of data is stored here vs in the proving key. We may want to resolve + * that, and split out separate PrecomputedPolynomials/Commitments data for clarity but also for portability of our + * circuits. + */ + using VerificationKey = VerificationKey_>; + + /** + * @brief A container for polynomials handles; only stores spans. + */ + using ProverPolynomials = AllEntities; + + /** + * @brief A container for polynomials produced after the first round of sumcheck. + * @todo TODO(#394) Use polynomial classes for guaranteed memory alignment. + */ + using FoldedPolynomials = AllEntities, PolynomialHandle>; + + /** + * @brief A container for univariates produced during the hot loop in sumcheck. + * @todo TODO(#390): Simplify this by moving MAX_RELATION_LENGTH? + */ + template + using ExtendedEdges = + AllEntities, sumcheck::Univariate>; + + /** + * @brief A container for the polynomials evaluations produced during sumcheck, which are purported to be the + * evaluations of polynomials committed in earlier rounds. + */ + class PurportedEvaluations : public AllEntities { + public: + using Base = AllEntities; + using Base::Base; + PurportedEvaluations(std::array _data_in) { this->_data = _data_in; } + }; + + /** + * @brief A container for commitment labels. + * @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It + * has, however, been useful during debugging to have these labels available. + * + */ + class CommitmentLabels : public AllEntities { + public: + CommitmentLabels() + { + w_l = "W_L"; + w_r = "W_R"; + w_o = "W_O"; + w_4 = "W_4"; + z_perm = "Z_PERM"; + z_lookup = "Z_LOOKUP"; + // The ones beginning with "__" are only used for debugging + q_c = "__Q_C"; + q_l = "__Q_L"; + q_r = "__Q_R"; + q_o = "__Q_O"; + q_4 = "__Q_4"; + q_m = "__Q_M"; + q_arith = "__Q_ARITH"; + q_sort = "__Q_SORT"; + q_elliptic = "__Q_ELLIPTIC"; + q_aux = "__Q_AUX"; + q_lookup = "__Q_LOOKUP"; + sigma_1 = "__SIGMA_1"; + sigma_2 = "__SIGMA_2"; + sigma_3 = "__SIGMA_3"; + sigma_4 = "__SIGMA_4"; + id_1 = "__ID_1"; + id_2 = "__ID_2"; + id_3 = "__ID_3"; + id_4 = "__ID_4"; + table_1 = "__TABLE_1"; + table_2 = "__TABLE_2"; + table_3 = "__TABLE_3"; + table_4 = "__TABLE_4"; + lagrange_first = "__LAGRANGE_FIRST"; + lagrange_last = "__LAGRANGE_LAST"; + sorted_1 = "__SORTED_1"; + sorted_2 = "__SORTED_2"; + sorted_3 = "__SORTED_3"; + sorted_4 = "__SORTED_4"; + sorted_accum = "__SORTED_ACCUM"; + table_1_shift = "__TABLE_1_SHIFT"; + table_2_shift = "__TABLE_2_SHIFT"; + table_3_shift = "__TABLE_3_SHIFT"; + table_4_shift = "__TABLE_4_SHIFT"; + w_l_shift = "__W_L_SHIFT"; + w_r_shift = "__W_R_SHIFT"; + w_o_shift = "__W_O_SHIFT"; + w_4_shift = "__W_4_SHIFT"; + sorted_accum_shift = "__SORTED_ACCUM_SHIFT"; + z_perm_shift = "__Z_PERM_SHIFT"; + z_lookup_shift = "__Z_LOOKUP_SHIFT"; + }; + }; + + /** + * @brief A container for all commitments used by the verifier. + */ + // class VerifierCommitments : public AllEntities { + // public: + // VerifierCommitments(std::shared_ptr verification_key) + // { + // } + // }; +}; + +} // namespace proof_system::honk::flavor diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/commitment_key.test.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/commitment_key.test.hpp index 0676a2631f2..991bc98386d 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/commitment_key.test.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/commitment_key.test.hpp @@ -14,7 +14,6 @@ #include "../oracle/oracle.hpp" #include "../../transcript/transcript_wrappers.hpp" -#include "../../proof_system/flavor/flavor.hpp" #include "claim.hpp" #include "commitment_key.hpp" diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp index 17d74eb9e94..2a9c7044018 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp @@ -7,9 +7,11 @@ #include "barretenberg/honk/pcs/commitment_key.hpp" #include "barretenberg/honk/pcs/commitment_key.test.hpp" using namespace barretenberg; -namespace proof_system::honk::pcs::ipa { +namespace proof_system::honk::pcs { -template class IpaCommitmentTest : public CommitmentTest { +class IPATests : public CommitmentTest { + public: + using Params = ipa::Params; using Fr = typename Params::Fr; using element = typename Params::Commitment; using affine_element = typename Params::C; @@ -18,9 +20,7 @@ template class IpaCommitmentTest : public CommitmentTest using Polynomial = barretenberg::Polynomial; }; -TYPED_TEST_SUITE(IpaCommitmentTest, IpaCommitmentSchemeParams); - -TYPED_TEST(IpaCommitmentTest, commit) +TEST_F(IPATests, Commit) { constexpr size_t n = 128; auto poly = this->random_polynomial(n); @@ -33,15 +33,15 @@ TYPED_TEST(IpaCommitmentTest, commit) EXPECT_EQ(expected.normalize(), commitment.normalize()); } -TYPED_TEST(IpaCommitmentTest, open) +TEST_F(IPATests, Open) { - using IPA = InnerProductArgument; + using IPA = ipa::InnerProductArgument; // generate a random polynomial, degree needs to be a power of two size_t n = 128; auto poly = this->random_polynomial(n); auto [x, eval] = this->random_eval(poly); auto commitment = this->commit(poly); - const OpeningPair opening_pair{ x, eval }; + const OpeningPair opening_pair{ x, eval }; // initialize empty prover transcript ProverTranscript prover_transcript; @@ -58,4 +58,4 @@ TYPED_TEST(IpaCommitmentTest, open) EXPECT_EQ(prover_transcript.get_manifest(), verifier_transcript.get_manifest()); } -} // namespace proof_system::honk::pcs::ipa +} // namespace proof_system::honk::pcs diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/composer_helper.lib.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/composer_helper.lib.hpp new file mode 100644 index 00000000000..24c89a3a063 --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/composer_helper.lib.hpp @@ -0,0 +1,37 @@ +#pragma once +#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" + +namespace proof_system::honk { + +/** + * @brief Computes the verification key. + * @details Does the following + * (1) commitments to the selector, permutation, and lagrange (first/last) polynomials, + * (2) sets the polynomial manifest using the data from proving key. + * + * @tparam Flavor + * @param proving_key A completely construted proving key. + * @param vrs The reference string used by the verifier + * @return std::shared_ptr + */ +template +std::shared_ptr compute_verification_key_common( + std::shared_ptr const& proving_key, + std::shared_ptr const& vrs) +{ + auto verification_key = std::make_shared( + proving_key->circuit_size, proving_key->num_public_inputs, vrs, proving_key->composer_type); + + auto commitment_key = typename Flavor::PCSParams::CK(proving_key->circuit_size, "../srs_db/ignition"); + + size_t poly_idx = 0; // TODO(#391) zip + for (auto& polynomial : proving_key) { + verification_key[poly_idx] = commitment_key.commit(polynomial); + ++polynomial_idx; + } + + return verification_key; +} + +} // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/program_settings.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/program_settings.hpp deleted file mode 100644 index b3df26bec66..00000000000 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/program_settings.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include - -#include "../../transcript/transcript_wrappers.hpp" -#include "../../plonk/proof_system/types/prover_settings.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" - -namespace proof_system::honk { - -// TODO(#221)(Luke/Cody): Shouldn't subclass plonk settings here. Also, define standard_settings for Honk prover. -class standard_verifier_settings : public plonk::standard_settings { - public: - typedef barretenberg::fr fr; - typedef transcript::StandardTranscript Transcript; - static constexpr size_t num_challenge_bytes = 16; - static constexpr transcript::HashType hash_type = transcript::HashType::PedersenBlake3s; - static constexpr size_t num_wires = proof_system::honk::StandardHonk::Arithmetization::num_wires; - static constexpr size_t num_polys = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; -}; - -} // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp index e728a40f75c..ca92ca8f271 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp @@ -1,35 +1,15 @@ #include "prover.hpp" -#include -#include #include "barretenberg/honk/proof_system/prover_library.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" -#include -#include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" // will go away #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" -#include "barretenberg/honk/pcs/commitment_key.hpp" -#include -#include -#include -#include -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/ecc/curves/bn254/g1.hpp" #include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" #include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" #include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" -#include "barretenberg/transcript/transcript_wrappers.hpp" -#include -#include "barretenberg/honk/pcs/claim.hpp" +#include "barretenberg/honk/flavor/standard.hpp" namespace proof_system::honk { -using Fr = barretenberg::fr; -using Commitment = barretenberg::g1::affine_element; -using Polynomial = barretenberg::Polynomial; -using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; - /** * Create Prover from proving key, witness and manifest. * @@ -38,34 +18,31 @@ using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; * * @tparam settings Settings class. * */ -template -Prover::Prover(std::vector&& wire_polys, - const std::shared_ptr input_key) - : wire_polynomials(wire_polys) - , key(input_key) - , queue(key, transcript) +template +StandardProver_::StandardProver_(const std::shared_ptr input_key) + : key(input_key) + , queue(input_key->circuit_size, transcript) { - // Note(luke): This could be done programmatically with some hacks but this isnt too bad and its nice to see the - // polys laid out explicitly. - prover_polynomials[POLYNOMIAL::Q_C] = key->polynomial_store.get("q_c_lagrange"); - prover_polynomials[POLYNOMIAL::Q_L] = key->polynomial_store.get("q_1_lagrange"); - prover_polynomials[POLYNOMIAL::Q_R] = key->polynomial_store.get("q_2_lagrange"); - prover_polynomials[POLYNOMIAL::Q_O] = key->polynomial_store.get("q_3_lagrange"); - prover_polynomials[POLYNOMIAL::Q_M] = key->polynomial_store.get("q_m_lagrange"); - prover_polynomials[POLYNOMIAL::SIGMA_1] = key->polynomial_store.get("sigma_1_lagrange"); - prover_polynomials[POLYNOMIAL::SIGMA_2] = key->polynomial_store.get("sigma_2_lagrange"); - prover_polynomials[POLYNOMIAL::SIGMA_3] = key->polynomial_store.get("sigma_3_lagrange"); - prover_polynomials[POLYNOMIAL::ID_1] = key->polynomial_store.get("id_1_lagrange"); - prover_polynomials[POLYNOMIAL::ID_2] = key->polynomial_store.get("id_2_lagrange"); - prover_polynomials[POLYNOMIAL::ID_3] = key->polynomial_store.get("id_3_lagrange"); - prover_polynomials[POLYNOMIAL::LAGRANGE_FIRST] = key->polynomial_store.get("L_first_lagrange"); - prover_polynomials[POLYNOMIAL::LAGRANGE_LAST] = key->polynomial_store.get("L_last_lagrange"); - prover_polynomials[POLYNOMIAL::W_L] = wire_polynomials[0]; - prover_polynomials[POLYNOMIAL::W_R] = wire_polynomials[1]; - prover_polynomials[POLYNOMIAL::W_O] = wire_polynomials[2]; + + prover_polynomials.q_c = key->q_c; + prover_polynomials.q_l = key->q_l; + prover_polynomials.q_r = key->q_r; + prover_polynomials.q_o = key->q_o; + prover_polynomials.q_m = key->q_m; + prover_polynomials.sigma_1 = key->sigma_1; + prover_polynomials.sigma_2 = key->sigma_2; + prover_polynomials.sigma_3 = key->sigma_3; + prover_polynomials.id_1 = key->id_1; + prover_polynomials.id_2 = key->id_2; + prover_polynomials.id_3 = key->id_3; + prover_polynomials.lagrange_first = key->lagrange_first; + prover_polynomials.lagrange_last = key->lagrange_last; + prover_polynomials.w_l = key->w_l; + prover_polynomials.w_r = key->w_r; + prover_polynomials.w_o = key->w_o; // Add public inputs to transcript from the second wire polynomial - std::span public_wires_source = prover_polynomials[POLYNOMIAL::W_R]; + std::span public_wires_source = prover_polynomials.w_r; for (size_t i = 0; i < key->num_public_inputs; ++i) { public_inputs.emplace_back(public_wires_source[i]); @@ -77,10 +54,13 @@ Prover::Prover(std::vector&& wire_polys, * - Add PI to transcript (I guess PI will stay in w_2 for now?) * * */ -template void Prover::compute_wire_commitments() +template void StandardProver_::compute_wire_commitments() { - for (size_t i = 0; i < settings::Arithmetization::num_wires; ++i) { - queue.add_commitment(wire_polynomials[i], "W_" + std::to_string(i + 1)); + size_t wire_idx = 0; // TODO(#391) zip + auto wire_polys = key->get_wires(); + for (auto& label : commitment_labels.get_wires()) { + queue.add_commitment(wire_polys[wire_idx], label); + ++wire_idx; } } @@ -88,7 +68,7 @@ template void Prover::compute_wire_commitments() * - Add circuit size, public input size, and public inputs to transcript * * */ -template void Prover::execute_preamble_round() +template void StandardProver_::execute_preamble_round() { const auto circuit_size = static_cast(key->circuit_size); const auto num_public_inputs = static_cast(key->num_public_inputs); @@ -105,7 +85,7 @@ template void Prover::execute_preamble_round() /** * - compute wire commitments * */ -template void Prover::execute_wire_commitments_round() +template void StandardProver_::execute_wire_commitments_round() { compute_wire_commitments(); } @@ -113,7 +93,7 @@ template void Prover::execute_wire_commitments_rou /** * For Standard Honk, this is a non-op (just like for Standard/Turbo Plonk). * */ -template void Prover::execute_tables_round() +template void StandardProver_::execute_tables_round() { // No operations are needed here for Standard Honk } @@ -122,26 +102,25 @@ template void Prover::execute_tables_round() * - Do Fiat-Shamir to get "beta" challenge (Note: gamma = beta^2) * - Compute grand product polynomial (permutation only) and commitment * */ -template void Prover::execute_grand_product_computation_round() +template void StandardProver_::execute_grand_product_computation_round() { // Compute and store parameters required by relations in Sumcheck auto [beta, gamma] = transcript.get_challenges("beta", "gamma"); - auto public_input_delta = compute_public_input_delta(public_inputs, beta, gamma, key->circuit_size); + auto public_input_delta = compute_public_input_delta(public_inputs, beta, gamma, key->circuit_size); - relation_parameters = sumcheck::RelationParameters{ + relation_parameters = sumcheck::RelationParameters{ .beta = beta, .gamma = gamma, .public_input_delta = public_input_delta, }; - z_permutation = - prover_library::compute_permutation_grand_product(key, wire_polynomials, beta, gamma); + key->z_perm = prover_library::compute_permutation_grand_product(key, beta, gamma); - queue.add_commitment(z_permutation, "Z_PERM"); + queue.add_commitment(key->z_perm, commitment_labels.z_perm); - prover_polynomials[POLYNOMIAL::Z_PERM] = z_permutation; - prover_polynomials[POLYNOMIAL::Z_PERM_SHIFT] = z_permutation.shifted(); + prover_polynomials.z_perm = key->z_perm; + prover_polynomials.z_perm_shift = key->z_perm.shifted(); } /** @@ -149,10 +128,10 @@ template void Prover::execute_grand_product_comput * - Run Sumcheck resulting in u = (u_1,...,u_d) challenges and all * evaluations at u being calculated. * */ -template void Prover::execute_relation_check_rounds() +template void StandardProver_::execute_relation_check_rounds() { - using Sumcheck = sumcheck::Sumcheck, + using Sumcheck = sumcheck::Sumcheck, sumcheck::ArithmeticRelation, sumcheck::GrandProductComputationRelation, sumcheck::GrandProductInitializationRelation>; @@ -167,22 +146,27 @@ template void Prover::execute_relation_check_round * - Compute d+1 Fold polynomials and their evaluations. * * */ -template void Prover::execute_univariatization_round() +template void StandardProver_::execute_univariatization_round() { - const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; - const size_t NUM_UNSHIFTED_POLYS = proof_system::honk::StandardArithmetization::NUM_UNSHIFTED_POLYNOMIALS; + const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; // Generate batching challenge ρ and powers 1,ρ,…,ρᵐ⁻¹ - Fr rho = transcript.get_challenge("rho"); - std::vector rhos = Gemini::powers_of_rho(rho, NUM_POLYNOMIALS); + FF rho = transcript.get_challenge("rho"); + std::vector rhos = Gemini::powers_of_rho(rho, NUM_POLYNOMIALS); // Batch the unshifted polynomials and the to-be-shifted polynomials using ρ Polynomial batched_poly_unshifted(key->circuit_size); // batched unshifted polynomials - for (size_t i = 0; i < NUM_UNSHIFTED_POLYS; ++i) { - batched_poly_unshifted.add_scaled(prover_polynomials[i], rhos[i]); + size_t poly_idx = 0; // TODO(#391) zip + for (auto& unshifted_poly : prover_polynomials.get_unshifted()) { + batched_poly_unshifted.add_scaled(unshifted_poly, rhos[poly_idx]); + ++poly_idx; } + Polynomial batched_poly_to_be_shifted(key->circuit_size); // batched to-be-shifted polynomials - batched_poly_to_be_shifted.add_scaled(prover_polynomials[POLYNOMIAL::Z_PERM], rhos[NUM_UNSHIFTED_POLYS]); + for (auto& to_be_shifted_poly : prover_polynomials.get_to_be_shifted()) { + batched_poly_to_be_shifted.add_scaled(to_be_shifted_poly, rhos[poly_idx]); + ++poly_idx; + }; // Compute d-1 polynomials Fold^(i), i = 1, ..., d-1. fold_polynomials = Gemini::compute_fold_polynomials( @@ -200,10 +184,9 @@ template void Prover::execute_univariatization_rou * - Compute and aggregate opening pairs (challenge, evaluation) for each of d Fold polynomials. * - Add d-many Fold evaluations a_i, i = 0, ..., d-1 to the transcript, excluding eval of Fold_{r}^(0) * */ -template void Prover::execute_pcs_evaluation_round() +template void StandardProver_::execute_pcs_evaluation_round() { - const Fr r_challenge = transcript.get_challenge("Gemini:r"); - + const FF r_challenge = transcript.get_challenge("Gemini:r"); gemini_output = Gemini::compute_fold_polynomial_evaluations( sumcheck_output.challenge_point, std::move(fold_polynomials), r_challenge); @@ -218,7 +201,7 @@ template void Prover::execute_pcs_evaluation_round * - Do Fiat-Shamir to get "nu" challenge. * - Compute commitment [Q]_1 * */ -template void Prover::execute_shplonk_batched_quotient_round() +template void StandardProver_::execute_shplonk_batched_quotient_round() { nu_challenge = transcript.get_challenge("Shplonk:nu"); @@ -233,9 +216,9 @@ template void Prover::execute_shplonk_batched_quot * - Do Fiat-Shamir to get "z" challenge. * - Compute polynomial Q(X) - Q_z(X) * */ -template void Prover::execute_shplonk_partial_evaluation_round() +template void StandardProver_::execute_shplonk_partial_evaluation_round() { - const Fr z_challenge = transcript.get_challenge("Shplonk:z"); + const FF z_challenge = transcript.get_challenge("Shplonk:z"); shplonk_output = Shplonk::compute_partially_evaluated_batched_quotient( gemini_output.opening_pairs, gemini_output.witnesses, std::move(batched_quotient_Q), nu_challenge, z_challenge); } @@ -244,19 +227,19 @@ template void Prover::execute_shplonk_partial_eval * - Compute KZG quotient commitment [W]_1. * * */ -template void Prover::execute_kzg_round() +template void StandardProver_::execute_kzg_round() { quotient_W = KZG::compute_opening_proof_polynomial(shplonk_output.opening_pair, shplonk_output.witness); queue.add_commitment(quotient_W, "KZG:W"); } -template plonk::proof& Prover::export_proof() +template plonk::proof& StandardProver_::export_proof() { proof.proof_data = transcript.proof_data; return proof; } -template plonk::proof& Prover::construct_proof() +template plonk::proof& StandardProver_::construct_proof() { // Add circuit size and public input size to transcript. execute_preamble_round(); @@ -306,6 +289,6 @@ template plonk::proof& Prover::construct_proof() return export_proof(); } -template class Prover; +template class StandardProver_; } // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp index 2a0e4de3146..7c7d1d0bb8c 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp @@ -1,40 +1,33 @@ #pragma once -#include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/honk/pcs/shplonk/shplonk.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" -#include -#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" -#include "barretenberg/honk/pcs/commitment_key.hpp" #include "barretenberg/plonk/proof_system/types/proof.hpp" -#include "barretenberg/plonk/proof_system/types/program_settings.hpp" #include "barretenberg/honk/pcs/gemini/gemini.hpp" #include "barretenberg/honk/pcs/shplonk/shplonk_single.hpp" #include "barretenberg/honk/pcs/kzg/kzg.hpp" #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include "barretenberg/honk/sumcheck/sumcheck_output.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include "barretenberg/honk/pcs/claim.hpp" #include "barretenberg/honk/proof_system/prover_library.hpp" #include "barretenberg/honk/proof_system/work_queue.hpp" +#include "barretenberg/honk/flavor/standard.hpp" namespace proof_system::honk { -using Fr = barretenberg::fr; -using Polynomial = Polynomial; +// We won't compile this class with honk::flavor::Ultra, but we will like want to compile it (at least for testing) +// with a flavor that uses the curve Grumpkin, or a flavor that does/does not have zk, etc. +template concept StandardFlavor = IsAnyOf; -template class Prover { +template class StandardProver_ { + + using FF = typename Flavor::FF; + using PCSParams = typename Flavor::PCSParams; + using ProvingKey = typename Flavor::ProvingKey; + using Polynomial = typename Flavor::Polynomial; + using ProverPolynomials = typename Flavor::ProverPolynomials; + using CommitmentLabels = typename Flavor::CommitmentLabels; public: - Prover(std::vector&& wire_polys, std::shared_ptr input_key = nullptr); + explicit StandardProver_(std::shared_ptr input_key = nullptr); void execute_preamble_round(); void execute_wire_commitments_round(); @@ -54,47 +47,44 @@ template class Prover { plonk::proof& export_proof(); plonk::proof& construct_proof(); - ProverTranscript transcript; - - std::vector public_inputs; + ProverTranscript transcript; - sumcheck::RelationParameters relation_parameters; + std::vector public_inputs; - std::vector wire_polynomials; - barretenberg::polynomial z_permutation; + sumcheck::RelationParameters relation_parameters; - std::shared_ptr key; + std::shared_ptr key; // Container for spans of all polynomials required by the prover (i.e. all multivariates evaluated by Sumcheck). - std::array, honk::StandardArithmetization::POLYNOMIAL::COUNT> prover_polynomials; + ProverPolynomials prover_polynomials; + + CommitmentLabels commitment_labels; // Container for d + 1 Fold polynomials produced by Gemini std::vector fold_polynomials; Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk - Fr nu_challenge; // needed in both Shplonk rounds + FF nu_challenge; // needed in both Shplonk rounds Polynomial quotient_W; - work_queue queue; - - // This makes 'settings' accesible from Prover - using settings_ = settings; + work_queue queue; - sumcheck::SumcheckOutput sumcheck_output; - pcs::gemini::ProverOutput gemini_output; - pcs::shplonk::ProverOutput shplonk_output; + sumcheck::SumcheckOutput sumcheck_output; + pcs::gemini::ProverOutput gemini_output; + pcs::shplonk::ProverOutput shplonk_output; - using Gemini = pcs::gemini::MultilinearReductionScheme; - using Shplonk = pcs::shplonk::SingleBatchOpeningScheme; - using KZG = pcs::kzg::UnivariateOpeningScheme; + using Gemini = pcs::gemini::MultilinearReductionScheme; + using Shplonk = pcs::shplonk::SingleBatchOpeningScheme; + using KZG = pcs::kzg::UnivariateOpeningScheme; private: plonk::proof proof; }; -extern template class Prover; +extern template class StandardProver_; -using StandardProver = Prover; +using StandardProver = StandardProver_; +// using GrumpkinStandardProver = StandardProver_; // e.g. } // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.cpp index 753bee2b924..87ee1631bed 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.cpp @@ -1,19 +1,16 @@ #include "prover_library.hpp" -#include "barretenberg/plonk/proof_system/types/prover_settings.hpp" +#include "barretenberg/honk/flavor/standard.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" #include #include namespace proof_system::honk::prover_library { -using Fr = barretenberg::fr; -using Polynomial = barretenberg::Polynomial; - /** * @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 - * + * @details (This description assumes Flavor::NUM_WIRES 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) + γ) @@ -25,55 +22,55 @@ using Polynomial = barretenberg::Polynomial; * 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 1) Compute the 2*Flavor::NUM_WIRES length-n polynomials A_i and B_i + * Step 2) Compute the 2*Flavor::NUM_WIRES 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) + * + * @todo TODO(#222)(luke): Parallelize */ -// TODO(#222)(luke): Parallelize -template -Polynomial compute_permutation_grand_product(std::shared_ptr& key, - std::vector& wire_polynomials, - Fr beta, - Fr gamma) + +template +typename Flavor::Polynomial compute_permutation_grand_product(std::shared_ptr& key, + typename Flavor::FF beta, + typename Flavor::FF gamma) { using barretenberg::polynomial_arithmetic::copy_polynomial; + using FF = typename Flavor::FF; + using Polynomial = typename Flavor::Polynomial; + + auto wire_polynomials = key->get_wires(); // TODO(luke): instantiate z_perm here then make the 0th accum a span of it? avoid extra memory. // Allocate accumulator polynomials that will serve as scratch space - std::array numerator_accumulator; - std::array denominator_accumulator; - for (size_t i = 0; i < program_width; ++i) { + std::array numerator_accumulator; + std::array denominator_accumulator; + for (size_t i = 0; i < Flavor::NUM_WIRES; ++i) { numerator_accumulator[i] = Polynomial{ key->circuit_size }; denominator_accumulator[i] = Polynomial{ key->circuit_size }; } // Populate wire and permutation polynomials - std::array, program_width> wires; - std::array, program_width> sigmas; - std::array, program_width> ids; - for (size_t i = 0; i < program_width; ++i) { - wires[i] = wire_polynomials[i]; - sigmas[i] = key->polynomial_store.get("sigma_" + std::to_string(i + 1) + "_lagrange"); - ids[i] = key->polynomial_store.get("id_" + std::to_string(i + 1) + "_lagrange"); - } + auto ids = key->get_id_polynomials(); + auto sigmas = key->get_sigma_polynomials(); // Step (1) // TODO(#222)(kesha): Change the order to engage automatic prefetching and get rid of redundant computation for (size_t i = 0; i < key->circuit_size; ++i) { - for (size_t k = 0; k < program_width; ++k) { - numerator_accumulator[k][i] = wires[k][i] + (ids[k][i] * beta) + gamma; // w_k(i) + β.id_k(i) + γ - denominator_accumulator[k][i] = wires[k][i] + (sigmas[k][i] * beta) + gamma; // w_k(i) + β.σ_k(i) + γ + for (size_t k = 0; k < Flavor::NUM_WIRES; ++k) { + numerator_accumulator[k][i] = wire_polynomials[k][i] + (ids[k][i] * beta) + gamma; // w_k(i) + β.id_k(i) + γ + denominator_accumulator[k][i] = + wire_polynomials[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 k = 0; k < Flavor::NUM_WIRES; ++k) { for (size_t i = 0; i < key->circuit_size - 1; ++i) { numerator_accumulator[k][i + 1] *= numerator_accumulator[k][i]; denominator_accumulator[k][i + 1] *= denominator_accumulator[k][i]; @@ -82,7 +79,7 @@ Polynomial compute_permutation_grand_product(std::shared_ptr // Step (3) for (size_t i = 0; i < key->circuit_size; ++i) { - for (size_t k = 1; k < program_width; ++k) { + for (size_t k = 1; k < Flavor::NUM_WIRES; ++k) { numerator_accumulator[0][i] *= numerator_accumulator[k][i]; denominator_accumulator[0][i] *= denominator_accumulator[k][i]; } @@ -93,8 +90,8 @@ Polynomial compute_permutation_grand_product(std::shared_ptr // denominator_accumulator[0][i]. At the end of this computation, the quotient numerator_accumulator[0] / // denominator_accumulator[0] is stored in numerator_accumulator[0]. // Note: Since numerator_accumulator[0][i] corresponds to z_lookup[i+1], we only iterate up to i = (n - 2). - Fr* inversion_coefficients = &denominator_accumulator[1][0]; // arbitrary scratch space - Fr inversion_accumulator = Fr::one(); + FF* inversion_coefficients = &denominator_accumulator[1][0]; // arbitrary scratch space + FF inversion_accumulator = FF::one(); for (size_t i = 0; i < key->circuit_size - 1; ++i) { inversion_coefficients[i] = numerator_accumulator[0][i] * inversion_accumulator; inversion_accumulator *= denominator_accumulator[0][i]; @@ -181,15 +178,19 @@ Polynomial compute_permutation_grand_product(std::shared_ptr * @param gamma * @return Polynomial */ -Polynomial compute_lookup_grand_product(std::shared_ptr& key, - std::vector& wire_polynomials, - Polynomial& sorted_list_accumulator, - Fr eta, - Fr beta, - Fr gamma) +template +typename Flavor::Polynomial compute_lookup_grand_product(std::shared_ptr& key, + typename Flavor::Polynomial& sorted_list_accumulator, + typename Flavor::FF eta, + typename Flavor::FF beta, + typename Flavor::FF gamma) + { - const Fr eta_sqr = eta.sqr(); - const Fr eta_cube = eta_sqr * eta; + using FF = typename Flavor::FF; + using Polynomial = typename Flavor::Polynomial; + + const FF eta_sqr = eta.sqr(); + const FF eta_cube = eta_sqr * eta; const size_t circuit_size = key->circuit_size; @@ -203,37 +204,35 @@ Polynomial compute_lookup_grand_product(std::shared_ptr& key } // Obtain column step size values that have been stored in repurposed selctors - std::span column_1_step_size = key->polynomial_store.get("q_2_lagrange"); - std::span column_2_step_size = key->polynomial_store.get("q_m_lagrange"); - std::span column_3_step_size = key->polynomial_store.get("q_c_lagrange"); - - // Utilize three wires; this is not tied to program width - std::array, 3> wires; - for (size_t i = 0; i < 3; ++i) { - wires[i] = wire_polynomials[i]; - } + std::span column_1_step_size = key->q_r; + std::span column_2_step_size = key->q_m; + std::span column_3_step_size = key->q_c; + + // We utilize three wires even when more are available. + // TODO(#389): const correctness + std::array, 3> wires = key->get_table_column_wires(); // Note: the number of table polys is related to program width but '4' is the only value supported - std::array, 4> tables{ - key->polynomial_store.get("table_value_1_lagrange"), - key->polynomial_store.get("table_value_2_lagrange"), - key->polynomial_store.get("table_value_3_lagrange"), - key->polynomial_store.get("table_value_4_lagrange"), + std::array, 4> tables{ + key->table_1, + key->table_2, + key->table_3, + key->table_4, }; - std::span lookup_selector = key->polynomial_store.get("table_type_lagrange"); - std::span lookup_index_selector = key->polynomial_store.get("q_3_lagrange"); + std::span lookup_selector = key->q_lookup; + std::span lookup_index_selector = key->q_o; - const Fr beta_plus_one = beta + Fr(1); // (1 + β) - const Fr gamma_times_beta_plus_one = gamma * beta_plus_one; // γ(1 + β) + const FF beta_plus_one = beta + FF(1); // (1 + β) + const FF gamma_times_beta_plus_one = gamma * beta_plus_one; // γ(1 + β) // Step (1) - Fr T0; // intermediate value for various calculations below + FF T0; // intermediate value for various calculations below // Note: block_mask is used for efficient modulus, i.e. i % N := i & (N-1), for N = 2^k const size_t block_mask = circuit_size - 1; // Initialize 't(X)' to be used in an expression of the form t(X) + β*t(Xω) - Fr next_table = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_sqr + tables[3][0] * eta_cube; + FF next_table = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_sqr + tables[3][0] * eta_cube; for (size_t i = 0; i < circuit_size; ++i) { @@ -290,7 +289,7 @@ Polynomial compute_lookup_grand_product(std::shared_ptr& key // Step (3) // Compute * ∏_{j& key Polynomial z_lookup(key->circuit_size); // Initialize 0th coefficient to 0 to ensure z_perm is left-shiftable via division by X in gemini - z_lookup[0] = Fr::zero(); + z_lookup[0] = FF::zero(); barretenberg::polynomial_arithmetic::copy_polynomial( accumulators[0].data(), &z_lookup[1], key->circuit_size - 1, key->circuit_size - 1); @@ -327,20 +326,25 @@ Polynomial compute_lookup_grand_product(std::shared_ptr& key * @param eta random challenge * @return Polynomial */ -Polynomial compute_sorted_list_accumulator(std::shared_ptr& key, - std::vector& sorted_list_polynomials, - Fr eta) +template +typename Flavor::Polynomial compute_sorted_list_accumulator( + std::shared_ptr& key, + std::vector& sorted_list_polynomials, + typename Flavor::FF eta) { + using FF = typename Flavor::FF; + using Polynomial = typename Flavor::Polynomial; + const size_t circuit_size = key->circuit_size; - barretenberg::polynomial sorted_list_accumulator(sorted_list_polynomials[0]); - std::span s_2 = sorted_list_polynomials[1]; - std::span s_3 = sorted_list_polynomials[2]; - std::span s_4 = sorted_list_polynomials[3]; + Polynomial sorted_list_accumulator(sorted_list_polynomials[0]); + std::span s_2 = sorted_list_polynomials[1]; + std::span s_3 = sorted_list_polynomials[2]; + std::span s_4 = sorted_list_polynomials[3]; // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) for (size_t i = 0; i < circuit_size; ++i) { - Fr T0 = s_4[i]; + FF T0 = s_4[i]; T0 *= eta; T0 += s_3[i]; T0 *= eta; @@ -352,9 +356,21 @@ Polynomial compute_sorted_list_accumulator(std::shared_ptr& return sorted_list_accumulator; } -template Polynomial compute_permutation_grand_product( - std::shared_ptr&, std::vector&, Fr, Fr); -template Polynomial compute_permutation_grand_product( - std::shared_ptr&, std::vector&, Fr, Fr); +template honk::flavor::Standard::Polynomial compute_permutation_grand_product( + std::shared_ptr&, honk::flavor::Standard::FF, honk::flavor::Standard::FF); + +template honk::flavor::Ultra::Polynomial compute_permutation_grand_product( + std::shared_ptr&, honk::flavor::Ultra::FF, honk::flavor::Ultra::FF); + +template typename honk::flavor::Ultra::Polynomial compute_lookup_grand_product( + std::shared_ptr& key, + typename honk::flavor::Ultra::Polynomial& sorted_list_accumulator, + typename honk::flavor::Ultra::FF eta, + typename honk::flavor::Ultra::FF beta, + typename honk::flavor::Ultra::FF gamma); +template typename honk::flavor::Ultra::Polynomial compute_sorted_list_accumulator( + std::shared_ptr& key, + std::vector& sorted_list_polynomials, + typename honk::flavor::Ultra::FF eta); } // namespace proof_system::honk::prover_library diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.hpp index c88a089f850..7f496034259 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.hpp @@ -7,24 +7,22 @@ namespace proof_system::honk::prover_library { -using Fr = barretenberg::fr; -using Polynomial = barretenberg::Polynomial; +template +typename Flavor::Polynomial compute_permutation_grand_product(std::shared_ptr& key, + typename Flavor::FF beta, + typename Flavor::FF gamma); -template -Polynomial compute_permutation_grand_product(std::shared_ptr& key, - std::vector& wire_polynomials, - Fr beta, - Fr gamma); +template +typename Flavor::Polynomial compute_lookup_grand_product(std::shared_ptr& key, + typename Flavor::Polynomial& sorted_list_accumulator, + typename Flavor::FF eta, + typename Flavor::FF beta, + typename Flavor::FF gamma); -Polynomial compute_lookup_grand_product(std::shared_ptr& key, - std::vector& wire_polynomials, - Polynomial& sorted_list_accumulator, - Fr eta, - Fr beta, - Fr gamma); - -Polynomial compute_sorted_list_accumulator(std::shared_ptr& key, - std::vector& sorted_list_polynomials, - Fr eta); +template +typename Flavor::Polynomial compute_sorted_list_accumulator( + std::shared_ptr& key, + std::vector& sorted_list_polynomials, + typename Flavor::FF eta); } // namespace proof_system::honk::prover_library diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp index f62380ebc94..9a33d3ce8ac 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp @@ -1,4 +1,6 @@ -#include "barretenberg/plonk/proof_system/types/prover_settings.hpp" + +#include "barretenberg/honk/flavor/standard.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" #include "prover.hpp" #include "prover_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" @@ -33,6 +35,14 @@ template class ProverLibraryTests : public testing::Test { return random_polynomial; } + static void populate_span(auto& polynomial_view, const auto& polynomial) + { + ASSERT(polynomial_view.size() <= polynomial.size()); + for (size_t idx = 0; idx < polynomial.size(); idx++) { + polynomial_view[idx] = polynomial[idx]; + } + }; + /** * @brief Check consistency of the computation of the permutation grand product polynomial z_permutation. * @details This test compares a simple, unoptimized, easily readable calculation of the grand product z_permutation @@ -41,7 +51,7 @@ template class ProverLibraryTests : public testing::Test { * @note This test does confirm the correctness of z_permutation, only that the two implementations yield an * identical result. */ - template static void test_permutation_grand_product_construction() + template static void test_permutation_grand_product_construction() { // Define some mock inputs for proving key constructor static const size_t num_gates = 8; @@ -49,7 +59,7 @@ template class ProverLibraryTests : public testing::Test { auto reference_string = std::make_shared(num_gates + 1, "../srs_db/ignition"); // Instatiate a proving_key and make a pointer to it. This will be used to instantiate a Prover. - auto proving_key = std::make_shared( + auto proving_key = std::make_shared( num_gates, num_public_inputs, reference_string, ComposerType::STANDARD_HONK); // static const size_t program_width = StandardProver::settings_::program_width; @@ -60,16 +70,18 @@ template class ProverLibraryTests : public testing::Test { std::vector wires; std::vector sigmas; std::vector ids; - for (size_t i = 0; i < program_width; ++i) { + + auto wire_polynomials = proving_key->get_wires(); + auto sigma_polynomials = proving_key->get_sigma_polynomials(); + auto id_polynomials = proving_key->get_id_polynomials(); + for (size_t i = 0; i < Flavor::NUM_WIRES; ++i) { wires.emplace_back(get_random_polynomial(num_gates)); sigmas.emplace_back(get_random_polynomial(num_gates)); ids.emplace_back(get_random_polynomial(num_gates)); - // Add sigma/ID polys to proving_key; to be used by the prover in constructing it's own z_perm - std::string sigma_label = "sigma_" + std::to_string(i + 1) + "_lagrange"; - proving_key->polynomial_store.put(sigma_label, Polynomial{ sigmas[i] }); - std::string id_label = "id_" + std::to_string(i + 1) + "_lagrange"; - proving_key->polynomial_store.put(id_label, Polynomial{ ids[i] }); + populate_span(wire_polynomials[i], wires[i]); + populate_span(sigma_polynomials[i], sigmas[i]); + populate_span(id_polynomials[i], ids[i]); } // Get random challenges @@ -77,14 +89,13 @@ template class ProverLibraryTests : public testing::Test { auto gamma = FF::random_element(); // Method 1: Compute z_perm using 'compute_grand_product_polynomial' as the prover would in practice - Polynomial z_permutation = - prover_library::compute_permutation_grand_product(proving_key, wires, beta, gamma); + Polynomial z_permutation = prover_library::compute_permutation_grand_product(proving_key, beta, gamma); // Method 2: Compute z_perm locally using the simplest non-optimized syntax possible. The comment below, // which describes the computation in 4 steps, is adapted from a similar comment in // compute_grand_product_polynomial. /* - * Assume program_width 3. Z_perm may be defined in terms of its values + * Assume Flavor::NUM_WIRES 3. Z_perm may be defined in terms of its values * on X_i = 0,1,...,n-1 as Z_perm[0] = 0 and for i = 1:n-1 * * (w_1(j) + β⋅id_1(j) + γ) ⋅ (w_2(j) + β⋅id_2(j) + γ) ⋅ (w_3(j) + β⋅id_3(j) + γ) @@ -98,37 +109,37 @@ template class ProverLibraryTests : public testing::Test { * 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 1) Compute the 2*Flavor::NUM_WIRES length-n polynomials A_i and B_i + * Step 2) Compute the 2*Flavor::NUM_WIRES 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) */ // Make scratch space for the numerator and denominator accumulators. - std::array, program_width> numererator_accum; - std::array, program_width> denominator_accum; + std::array, Flavor::NUM_WIRES> numerator_accum; + std::array, Flavor::NUM_WIRES> denominator_accum; // Step (1) for (size_t i = 0; i < proving_key->circuit_size; ++i) { - for (size_t k = 0; k < program_width; ++k) { - numererator_accum[k][i] = wires[k][i] + (ids[k][i] * beta) + gamma; // w_k(i) + β.id_k(i) + γ + for (size_t k = 0; k < Flavor::NUM_WIRES; ++k) { + numerator_accum[k][i] = wires[k][i] + (ids[k][i] * beta) + gamma; // w_k(i) + β.id_k(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 k = 0; k < Flavor::NUM_WIRES; ++k) { for (size_t i = 0; i < proving_key->circuit_size - 1; ++i) { - numererator_accum[k][i + 1] *= numererator_accum[k][i]; + numerator_accum[k][i + 1] *= numerator_accum[k][i]; denominator_accum[k][i + 1] *= denominator_accum[k][i]; } } // Step (3) for (size_t i = 0; i < proving_key->circuit_size; ++i) { - for (size_t k = 1; k < program_width; ++k) { - numererator_accum[0][i] *= numererator_accum[k][i]; + for (size_t k = 1; k < Flavor::NUM_WIRES; ++k) { + numerator_accum[0][i] *= numerator_accum[k][i]; denominator_accum[0][i] *= denominator_accum[k][i]; } } @@ -138,7 +149,7 @@ template class ProverLibraryTests : public testing::Test { z_permutation_expected[0] = FF::zero(); // Z_0 = 1 // Note: in practice, we replace this expensive element-wise division with Montgomery batch inversion for (size_t i = 0; i < proving_key->circuit_size - 1; ++i) { - z_permutation_expected[i + 1] = numererator_accum[0][i] / denominator_accum[0][i]; + z_permutation_expected[i + 1] = numerator_accum[0][i] / denominator_accum[0][i]; } // Check consistency between locally computed z_perm and the one computed by the prover library @@ -161,36 +172,44 @@ template class ProverLibraryTests : public testing::Test { auto reference_string = std::make_shared(circuit_size + 1, "../srs_db/ignition"); // Instatiate a proving_key and make a pointer to it. This will be used to instantiate a Prover. - auto proving_key = std::make_shared( + using Flavor = honk::flavor::Ultra; + auto proving_key = std::make_shared( circuit_size, num_public_inputs, reference_string, ComposerType::STANDARD_HONK); // Construct mock wire and permutation polynomials. - // Note: for the purpose of checking the consistency between two methods of computing z_perm, these polynomials - // can simply be random. We're not interested in the particular properties of the result. + // Note: for the purpose of checking the consistency between two methods of computing z_lookup, these + // polynomials can simply be random. We're not interested in the particular properties of the result. std::vector wires; - for (size_t i = 0; i < 3; ++i) { - wires.emplace_back(get_random_polynomial(circuit_size)); + auto wire_polynomials = proving_key->get_wires(); + // Note(luke): Use of 3 wires is fundamental to the structure of the tables and should not be tied to NUM_WIRES + // for now + for (size_t i = 0; i < 3; ++i) { // TODO(Cody): will this test ever generalize? + Polynomial random_polynomial = get_random_polynomial(circuit_size); + wires.emplace_back(random_polynomial); + populate_span(wire_polynomials[i], random_polynomial); } + std::vector tables; - for (size_t i = 0; i < 4; ++i) { - tables.emplace_back(get_random_polynomial(circuit_size)); - std::string label = "table_value_" + std::to_string(i + 1) + "_lagrange"; - proving_key->polynomial_store.put(label, Polynomial{ tables[i] }); + auto table_polynomials = proving_key->get_table_polynomials(); + for (auto& table_polynomial : table_polynomials) { + Polynomial random_polynomial = get_random_polynomial(circuit_size); + tables.emplace_back(random_polynomial); + populate_span(table_polynomial, random_polynomial); } - auto s_lagrange = get_random_polynomial(circuit_size); + auto sorted_batched = get_random_polynomial(circuit_size); auto column_1_step_size = get_random_polynomial(circuit_size); auto column_2_step_size = get_random_polynomial(circuit_size); auto column_3_step_size = get_random_polynomial(circuit_size); auto lookup_index_selector = get_random_polynomial(circuit_size); auto lookup_selector = get_random_polynomial(circuit_size); - proving_key->polynomial_store.put("s_lagrange", Polynomial{ s_lagrange }); - proving_key->polynomial_store.put("q_2_lagrange", Polynomial{ column_1_step_size }); - proving_key->polynomial_store.put("q_m_lagrange", Polynomial{ column_2_step_size }); - proving_key->polynomial_store.put("q_c_lagrange", Polynomial{ column_3_step_size }); - proving_key->polynomial_store.put("q_3_lagrange", Polynomial{ lookup_index_selector }); - proving_key->polynomial_store.put("table_type_lagrange", Polynomial{ lookup_selector }); + // populate_span(proving_key->sorted_batched, sorted_batched); + populate_span(proving_key->q_r, column_1_step_size); + populate_span(proving_key->q_m, column_2_step_size); + populate_span(proving_key->q_c, column_3_step_size); + populate_span(proving_key->q_o, lookup_index_selector); + populate_span(proving_key->q_lookup, lookup_selector); // Get random challenges auto beta = FF::random_element(); @@ -199,7 +218,7 @@ template class ProverLibraryTests : public testing::Test { // Method 1: Compute z_lookup using the prover library method Polynomial z_lookup = - prover_library::compute_lookup_grand_product(proving_key, wires, s_lagrange, eta, beta, gamma); + prover_library::compute_lookup_grand_product(proving_key, sorted_batched, eta, beta, gamma); // Method 2: Compute the lookup grand product polynomial Z_lookup: // @@ -245,7 +264,7 @@ template class ProverLibraryTests : public testing::Test { accumulators[2][i] = FF::one() + beta; // s + βs(Xω) + γ(1 + β) - accumulators[3][i] = s_lagrange[i] + beta * s_lagrange[shift_idx] + gamma * (FF::one() + beta); + accumulators[3][i] = sorted_batched[i] + beta * sorted_batched[shift_idx] + gamma * (FF::one() + beta); // Set t(X_i) for next iteration table_i = table_i_plus_1; @@ -288,7 +307,8 @@ template class ProverLibraryTests : public testing::Test { static const size_t circuit_size = 8; static const size_t num_public_inputs = 0; auto reference_string = std::make_shared(circuit_size + 1, "../srs_db/ignition"); - auto proving_key = std::make_shared( + using Flavor = honk::flavor::Ultra; + auto proving_key = std::make_shared( circuit_size, num_public_inputs, reference_string, ComposerType::STANDARD_HONK); // Get random challenge eta @@ -302,7 +322,7 @@ template class ProverLibraryTests : public testing::Test { // Method 1: computed sorted list accumulator polynomial using prover library method Polynomial sorted_list_accumulator = - prover_library::compute_sorted_list_accumulator(proving_key, sorted_list_polynomials, eta); + prover_library::compute_sorted_list_accumulator(proving_key, sorted_list_polynomials, eta); // Method 2: Compute local sorted list accumulator simply and inefficiently const FF eta_sqr = eta.sqr(); @@ -325,8 +345,8 @@ TYPED_TEST_SUITE(ProverLibraryTests, FieldTypes); TYPED_TEST(ProverLibraryTests, PermutationGrandProduct) { - TestFixture::template test_permutation_grand_product_construction(); - TestFixture::template test_permutation_grand_product_construction(); + TestFixture::template test_permutation_grand_product_construction(); + TestFixture::template test_permutation_grand_product_construction(); } TYPED_TEST(ProverLibraryTests, LookupGrandProduct) diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp index 769e744a6d3..5a641d3b563 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp @@ -1,26 +1,4 @@ #include "ultra_prover.hpp" -#include -#include -#include "barretenberg/honk/proof_system/prover_library.hpp" -#include "barretenberg/honk/sumcheck/sumcheck.hpp" -#include -#include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" // will go away -#include "barretenberg/honk/utils/power_polynomial.hpp" -#include "barretenberg/honk/pcs/commitment_key.hpp" -#include -#include -#include -#include -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/ecc/curves/bn254/g1.hpp" -#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" -#include "barretenberg/transcript/transcript_wrappers.hpp" -#include -#include "barretenberg/honk/pcs/claim.hpp" namespace proof_system::honk { @@ -32,25 +10,23 @@ namespace proof_system::honk { * * @tparam settings Settings class. * */ -template -UltraHonkProver::UltraHonkProver(std::vector&& wire_polys, - std::shared_ptr input_key) - : wire_polynomials(wire_polys) - , key(input_key) - , queue(key, transcript) +template +UltraProver_::UltraProver_(std::shared_ptr input_key) + : key(input_key) + , queue(input_key->circuit_size, transcript) {} -template plonk::proof& UltraHonkProver::export_proof() +template plonk::proof& UltraProver_::export_proof() { proof.proof_data = transcript.proof_data; return proof; } -template plonk::proof& UltraHonkProver::construct_proof() +template plonk::proof& UltraProver_::construct_proof() { return export_proof(); } -template class UltraHonkProver; +template class UltraProver_; } // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp index b645e5863f3..3c782432d61 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp @@ -1,54 +1,30 @@ #pragma once -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/honk/pcs/shplonk/shplonk.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" -#include -#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" -#include "barretenberg/honk/pcs/commitment_key.hpp" +#include "barretenberg/honk/proof_system/work_queue.hpp" #include "barretenberg/plonk/proof_system/types/proof.hpp" -#include "barretenberg/plonk/proof_system/types/program_settings.hpp" -#include "barretenberg/honk/pcs/gemini/gemini.hpp" -#include "barretenberg/honk/pcs/shplonk/shplonk_single.hpp" -#include "barretenberg/honk/pcs/kzg/kzg.hpp" #include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/honk/sumcheck/sumcheck.hpp" -#include "barretenberg/honk/sumcheck/sumcheck_output.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include "barretenberg/honk/pcs/claim.hpp" -#include "barretenberg/honk/proof_system/prover_library.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" namespace proof_system::honk { -// TODO(luke): The naming here is awkward. The Standard Honk prover is called "Prover" and aliased as StandardProver. To -// be consistent with that convention outside of the prover class itself, I've called this class UltraHonkProver and use -// the alias UltraProver externally. Resolve. -template class UltraHonkProver { +// We won't compile this class with honk::flavor::Standard, but we will like want to compile it (at least for testing) +// with a flavor that uses the curve Grumpkin, or a flavor that does/does not have zk, etc. +template concept UltraFlavor = IsAnyOf; +template class UltraProver_ { - using Fr = barretenberg::fr; - using Polynomial = barretenberg::Polynomial; - using Commitment = barretenberg::g1::affine_element; - using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; + using FF = typename Flavor::FF; + using PCSParams = typename Flavor::PCSParams; + using ProvingKey = typename Flavor::ProvingKey; + using Polynomial = typename Flavor::Polynomial; public: - UltraHonkProver(std::vector&& wire_polys, - std::shared_ptr input_key = nullptr); + UltraProver_(std::shared_ptr input_key = nullptr); plonk::proof& export_proof(); plonk::proof& construct_proof(); - ProverTranscript transcript; + ProverTranscript transcript; - std::vector wire_polynomials; - - std::shared_ptr key; + std::shared_ptr key; work_queue queue; @@ -56,8 +32,8 @@ template class UltraHonkProver { plonk::proof proof; }; -extern template class UltraHonkProver; +extern template class UltraProver_; -using UltraProver = UltraHonkProver; +using UltraProver = UltraProver_; } // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp index b26f10fa473..6238f6e2e1f 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp @@ -1,45 +1,29 @@ -#include -#include "barretenberg/common/throw_or_abort.hpp" -#include -#include -#include "barretenberg/honk/transcript/transcript.hpp" #include "./verifier.hpp" -#include "barretenberg/plonk/proof_system/public_inputs/public_inputs.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/honk/pcs/commitment_key.hpp" -#include "barretenberg/honk/pcs/gemini/gemini.hpp" -#include "barretenberg/honk/pcs/kzg/kzg.hpp" +#include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" -#include "barretenberg/proof_system/polynomial_store/polynomial_store.hpp" -#include "barretenberg/ecc/curves/bn254/fq12.hpp" -#include "barretenberg/ecc/curves/bn254/pairing.hpp" +#include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/ecc/curves/bn254/scalar_multiplication/scalar_multiplication.hpp" -#include "barretenberg/polynomials/polynomial_arithmetic.hpp" -#include "barretenberg/proof_system/composer/permutation_helper.hpp" -#include -#include -#include #include "barretenberg/honk/utils/power_polynomial.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" #include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" using namespace barretenberg; using namespace proof_system::honk::sumcheck; namespace proof_system::honk { -template -Verifier::Verifier(std::shared_ptr verifier_key) +template +StandardVerifier_::StandardVerifier_(std::shared_ptr verifier_key) : key(verifier_key) {} -template -Verifier::Verifier(Verifier&& other) +template +StandardVerifier_::StandardVerifier_(StandardVerifier_&& other) : key(other.key) , kate_verification_key(std::move(other.kate_verification_key)) {} -template Verifier& Verifier::operator=(Verifier&& other) +template StandardVerifier_& StandardVerifier_::operator=(StandardVerifier_&& other) { key = other.key; kate_verification_key = (std::move(other.kate_verification_key)); @@ -74,22 +58,22 @@ template Verifier& Verifier bool Verifier::verify_proof(const plonk::proof& proof) +template bool StandardVerifier_::verify_proof(const plonk::proof& proof) { - using FF = typename program_settings::fr; - using Commitment = barretenberg::g1::element; - using CommitmentAffine = barretenberg::g1::affine_element; + using FF = typename Flavor::FF; + using GroupElement = typename Flavor::GroupElement; + using Commitment = typename Flavor::Commitment; using Gemini = pcs::gemini::MultilinearReductionScheme; using Shplonk = pcs::shplonk::SingleBatchOpeningScheme; using KZG = pcs::kzg::UnivariateOpeningScheme; - const size_t NUM_POLYNOMIALS = honk::StandardArithmetization::NUM_POLYNOMIALS; - const size_t NUM_UNSHIFTED = honk::StandardArithmetization::NUM_UNSHIFTED_POLYNOMIALS; - const size_t NUM_PRECOMPUTED = honk::StandardArithmetization::NUM_PRECOMPUTED_POLYNOMIALS; - - constexpr auto num_wires = program_settings::num_wires; + using VerifierCommitments = typename Flavor::VerifierCommitments; + using CommitmentLabels = typename Flavor::CommitmentLabels; transcript = VerifierTranscript{ proof.proof_data }; + auto commitments = VerifierCommitments(key); + auto commitment_labels = CommitmentLabels(); + // TODO(Adrian): Change the initialization of the transcript to take the VK hash? const auto circuit_size = transcript.template receive_from_prover("circuit_size"); const auto public_input_size = transcript.template receive_from_prover("public_input_size"); @@ -108,10 +92,9 @@ template bool Verifier::verify_pro } // Get commitments to the wires - std::array wire_commitments; - for (size_t i = 0; i < num_wires; ++i) { - wire_commitments[i] = transcript.template receive_from_prover("W_" + std::to_string(i + 1)); - } + commitments.w_l = transcript.template receive_from_prover(commitment_labels.w_l); + commitments.w_r = transcript.template receive_from_prover(commitment_labels.w_r); + commitments.w_o = transcript.template receive_from_prover(commitment_labels.w_o); // Get permutation challenges auto [beta, gamma] = transcript.get_challenges("beta", "gamma"); @@ -125,16 +108,14 @@ template bool Verifier::verify_pro }; // Get commitment to Z_PERM - auto z_permutation_commitment = transcript.template receive_from_prover("Z_PERM"); - - // // TODO(Cody): Compute some basic public polys like id(X), pow(X), and any required Lagrange polys + commitments.z_perm = transcript.template receive_from_prover(commitment_labels.z_perm); // Execute Sumcheck Verifier - auto sumcheck = Sumcheck, - ArithmeticRelation, - GrandProductComputationRelation, - GrandProductInitializationRelation>(circuit_size, transcript); + honk::sumcheck::ArithmeticRelation, + honk::sumcheck::GrandProductComputationRelation, + honk::sumcheck::GrandProductInitializationRelation>(circuit_size, transcript); std::optional sumcheck_output = sumcheck.execute_verifier(relation_parameters); // If Sumcheck does not return an output, sumcheck verification has failed @@ -142,40 +123,40 @@ template bool Verifier::verify_pro return false; } - auto [multivariate_challenge, multivariate_evaluations] = *sumcheck_output; + auto [multivariate_challenge, purported_evaluations] = *sumcheck_output; // Execute Gemini/Shplonk verification: // Construct inputs for Gemini verifier: // - Multivariate opening point u = (u_0, ..., u_{d-1}) // - batched unshifted and to-be-shifted polynomial commitments - auto batched_commitment_unshifted = Commitment::zero(); - auto batched_commitment_to_be_shifted = Commitment::zero(); + auto batched_commitment_unshifted = GroupElement::zero(); + auto batched_commitment_to_be_shifted = GroupElement::zero(); // Compute powers of batching challenge rho - Fr rho = transcript.get_challenge("rho"); - std::vector rhos = Gemini::powers_of_rho(rho, NUM_POLYNOMIALS); + FF rho = transcript.get_challenge("rho"); + std::vector rhos = Gemini::powers_of_rho(rho, Flavor::NUM_ALL_ENTITIES); // Compute batched multivariate evaluation - Fr batched_evaluation = Fr::zero(); - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - batched_evaluation += multivariate_evaluations[i] * rhos[i]; + FF batched_evaluation = FF::zero(); + size_t evaluation_idx = 0; + for (auto& value : purported_evaluations.get_unshifted_then_shifted()) { + batched_evaluation += value * rhos[evaluation_idx]; + ++evaluation_idx; } // Construct batched commitment for NON-shifted polynomials - for (size_t i = 0; i < NUM_PRECOMPUTED; ++i) { - auto commitment = key->commitments[honk::StandardArithmetization::ENUM_TO_COMM[i]]; - batched_commitment_unshifted += commitment * rhos[i]; + size_t commitment_idx = 0; + for (auto& commitment : commitments.get_unshifted()) { + batched_commitment_unshifted += commitment * rhos[commitment_idx]; + ++commitment_idx; } - // add wire commitments - for (size_t i = 0; i < num_wires; ++i) { - batched_commitment_unshifted += wire_commitments[i] * rhos[NUM_PRECOMPUTED + i]; - } - // add z_permutation commitment - batched_commitment_unshifted += z_permutation_commitment * rhos[NUM_PRECOMPUTED + num_wires]; // Construct batched commitment for to-be-shifted polynomials - batched_commitment_to_be_shifted = z_permutation_commitment * rhos[NUM_UNSHIFTED]; + for (auto& commitment : commitments.get_to_be_shifted()) { + batched_commitment_to_be_shifted += commitment * rhos[commitment_idx]; + ++commitment_idx; + } // Produce a Gemini claim consisting of: // - d+1 commitments [Fold_{r}^(0)], [Fold_{-r}^(0)], and [Fold^(l)], l = 1:d-1 @@ -196,6 +177,6 @@ template bool Verifier::verify_pro return kzg_claim.verify(kate_verification_key); } -template class Verifier; +template class StandardVerifier_; } // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp index ed4fe608a1f..c62f4c3a27b 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp @@ -1,38 +1,33 @@ #pragma once +#include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/plonk/proof_system/types/proof.hpp" -#include "./program_settings.hpp" -#include "barretenberg/plonk/proof_system/verification_key/verification_key.hpp" -#include "barretenberg/transcript/manifest.hpp" -#include "barretenberg/plonk/proof_system/commitment_scheme/commitment_scheme.hpp" -#include "../sumcheck/sumcheck.hpp" -#include "../sumcheck/relations/arithmetic_relation.hpp" -#include "barretenberg/honk/pcs/commitment_key.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" -#include "barretenberg/honk/pcs/gemini/gemini.hpp" -#include "barretenberg/honk/pcs/shplonk/shplonk_single.hpp" -#include "barretenberg/honk/pcs/kzg/kzg.hpp" +#include "barretenberg/honk/sumcheck/sumcheck.hpp" namespace proof_system::honk { -template class Verifier { +template class StandardVerifier_ { + using FF = typename Flavor::FF; + using Commitment = typename Flavor::Commitment; + using VerificationKey = typename Flavor::VerificationKey; + using PCSVerificationKey = typename Flavor::PCSParams::VK; public: - Verifier(std::shared_ptr verifier_key = nullptr); - Verifier(Verifier&& other); - Verifier(const Verifier& other) = delete; - Verifier& operator=(const Verifier& other) = delete; - Verifier& operator=(Verifier&& other); + StandardVerifier_(std::shared_ptr verifier_key = nullptr); + StandardVerifier_(StandardVerifier_&& other); + StandardVerifier_(const StandardVerifier_& other) = delete; + StandardVerifier_& operator=(const StandardVerifier_& other) = delete; + StandardVerifier_& operator=(StandardVerifier_&& other); bool verify_proof(const plonk::proof& proof); - std::shared_ptr key; - std::map kate_g1_elements; - std::map kate_fr_elements; - std::shared_ptr kate_verification_key; - VerifierTranscript transcript; + std::shared_ptr key; + std::map kate_g1_elements; + std::map kate_fr_elements; + std::shared_ptr kate_verification_key; + VerifierTranscript transcript; }; -extern template class Verifier; +extern template class StandardVerifier_; -typedef Verifier StandardVerifier; +using StandardVerifier = StandardVerifier_; } // namespace proof_system::honk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.test.cpp deleted file mode 100644 index 903ea36adba..00000000000 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.test.cpp +++ /dev/null @@ -1,228 +0,0 @@ -#include "barretenberg/numeric/bitop/get_msb.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" -#include "prover.hpp" -#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" -#include "barretenberg/transcript/transcript.hpp" -#include "verifier.hpp" -#include "barretenberg/ecc/curves/bn254/scalar_multiplication/scalar_multiplication.hpp" -#include -#include "barretenberg/srs/reference_string/file_reference_string.hpp" -#include "barretenberg/polynomials/polynomial_arithmetic.hpp" -#include "barretenberg/plonk/proof_system/commitment_scheme/kate_commitment_scheme.hpp" -#include "barretenberg/proof_system/composer/permutation_helper.hpp" -#include - -using namespace barretenberg; -using namespace proof_system::honk; - -namespace test_honk_verifier { - -template class VerifierTests : public testing::Test { - public: - static transcript::Manifest create_manifest(const size_t num_public_inputs, const size_t num_sumcheck_rounds) - { - return honk::StandardHonk::create_manifest(num_public_inputs, num_sumcheck_rounds); - } - - static StandardVerifier generate_verifier(std::shared_ptr circuit_proving_key) - { - std::array poly_coefficients; - poly_coefficients[0] = circuit_proving_key->polynomial_store.get("q_1_lagrange").get_coefficients(); - poly_coefficients[1] = circuit_proving_key->polynomial_store.get("q_2_lagrange").get_coefficients(); - poly_coefficients[2] = circuit_proving_key->polynomial_store.get("q_3_lagrange").get_coefficients(); - poly_coefficients[3] = circuit_proving_key->polynomial_store.get("q_m_lagrange").get_coefficients(); - poly_coefficients[4] = circuit_proving_key->polynomial_store.get("q_c_lagrange").get_coefficients(); - poly_coefficients[5] = circuit_proving_key->polynomial_store.get("sigma_1_lagrange").get_coefficients(); - poly_coefficients[6] = circuit_proving_key->polynomial_store.get("sigma_2_lagrange").get_coefficients(); - poly_coefficients[7] = circuit_proving_key->polynomial_store.get("sigma_3_lagrange").get_coefficients(); - - std::vector commitments; - scalar_multiplication::pippenger_runtime_state prover(circuit_proving_key->circuit_size); - commitments.resize(8); - - for (size_t i = 0; i < 8; ++i) { - commitments[i] = g1::affine_element( - scalar_multiplication::pippenger(poly_coefficients[i], - circuit_proving_key->reference_string->get_monomial_points(), - circuit_proving_key->circuit_size, - prover)); - } - - auto crs = std::make_shared("../srs_db/ignition"); - auto circuit_verification_key = - std::make_shared(circuit_proving_key->circuit_size, - circuit_proving_key->num_public_inputs, - crs, - circuit_proving_key->composer_type); - - circuit_verification_key->commitments.insert({ "Q_1", commitments[0] }); - circuit_verification_key->commitments.insert({ "Q_2", commitments[1] }); - circuit_verification_key->commitments.insert({ "Q_3", commitments[2] }); - circuit_verification_key->commitments.insert({ "Q_M", commitments[3] }); - circuit_verification_key->commitments.insert({ "Q_C", commitments[4] }); - - circuit_verification_key->commitments.insert({ "SIGMA_1", commitments[5] }); - circuit_verification_key->commitments.insert({ "SIGMA_2", commitments[6] }); - circuit_verification_key->commitments.insert({ "SIGMA_3", commitments[7] }); - - StandardVerifier verifier(circuit_verification_key); - - // std::unique_ptr> kate_commitment_scheme = - // std::make_unique>(); - // verifier.commitment_scheme = std::move(kate_commitment_scheme); - - return verifier; - } - - // Note: this example is adapted from a corresponding PlonK verifier test. - static StandardProver generate_test_data(const size_t n) - { - // Create some constraints that satisfy our arithmetic circuit relation - // even indices = mul gates, odd incides = add gates - - auto crs = std::make_shared(n + 1, "../srs_db/ignition"); - std::shared_ptr proving_key = - std::make_shared(n, 0, crs, ComposerType::STANDARD_HONK); - - polynomial w_l(n); - polynomial w_r(n); - polynomial w_o(n); - polynomial q_l(n); - polynomial q_r(n); - polynomial q_o(n); - polynomial q_c(n); - polynomial q_m(n); - - fr T0; - for (size_t i = 0; i < n / 4; ++i) { - w_l.at(2 * i) = fr::random_element(); - w_r.at(2 * i) = fr::random_element(); - w_o.at(2 * i) = w_l.at(2 * i) * w_r.at(2 * i); - w_o[2 * i] = w_o[2 * i] + w_l[2 * i]; - w_o[2 * i] = w_o[2 * i] + w_r[2 * i]; - w_o[2 * i] = w_o[2 * i] + fr::one(); - q_l.at(2 * i) = fr::one(); - q_r.at(2 * i) = fr::one(); - q_o.at(2 * i) = fr::neg_one(); - q_c.at(2 * i) = fr::one(); - q_m.at(2 * i) = fr::one(); - - w_l.at(2 * i + 1) = fr::random_element(); - w_r.at(2 * i + 1) = fr::random_element(); - w_o.at(2 * i + 1) = fr::random_element(); - - T0 = w_l.at(2 * i + 1) + w_r.at(2 * i + 1); - q_c.at(2 * i + 1) = T0 + w_o.at(2 * i + 1); - q_c.at(2 * i + 1).self_neg(); - q_l.at(2 * i + 1) = fr::one(); - q_r.at(2 * i + 1) = fr::one(); - q_o.at(2 * i + 1) = fr::one(); - q_m.at(2 * i + 1) = fr::zero(); - } - size_t shift = n / 2; - polynomial_arithmetic::copy_polynomial(&w_l.at(0), &w_l.at(shift), shift, shift); - polynomial_arithmetic::copy_polynomial(&w_r.at(0), &w_r.at(shift), shift, shift); - polynomial_arithmetic::copy_polynomial(&w_o.at(0), &w_o.at(shift), shift, shift); - polynomial_arithmetic::copy_polynomial(&q_m.at(0), &q_m.at(shift), shift, shift); - polynomial_arithmetic::copy_polynomial(&q_l.at(0), &q_l.at(shift), shift, shift); - polynomial_arithmetic::copy_polynomial(&q_r.at(0), &q_r.at(shift), shift, shift); - polynomial_arithmetic::copy_polynomial(&q_o.at(0), &q_o.at(shift), shift, shift); - polynomial_arithmetic::copy_polynomial(&q_c.at(0), &q_c.at(shift), shift, shift); - - std::vector sigma_1_mapping; - std::vector sigma_2_mapping; - std::vector sigma_3_mapping; - // create basic permutation - second half of witness vector is a copy of the first half - sigma_1_mapping.resize(n); - sigma_2_mapping.resize(n); - sigma_3_mapping.resize(n); - - for (size_t i = 0; i < n / 2; ++i) { - sigma_1_mapping[shift + i] = (uint32_t)i; - sigma_2_mapping[shift + i] = (uint32_t)i + (1U << 30U); - sigma_3_mapping[shift + i] = (uint32_t)i + (1U << 31U); - sigma_1_mapping[i] = (uint32_t)(i + shift); - sigma_2_mapping[i] = (uint32_t)(i + shift) + (1U << 30U); - sigma_3_mapping[i] = (uint32_t)(i + shift) + (1U << 31U); - } - // make last permutation the same as identity permutation - // we are setting the permutation in the last 4 gates as identity permutation since - // we are cutting out 4 roots as of now. - size_t num_roots_cut_out_of_the_vanishing_polynomial = 4; - for (uint32_t j = 0; j < num_roots_cut_out_of_the_vanishing_polynomial; ++j) { - sigma_1_mapping[shift - 1 - j] = (uint32_t)shift - 1 - j; - sigma_2_mapping[shift - 1 - j] = (uint32_t)shift - 1 - j + (1U << 30U); - sigma_3_mapping[shift - 1 - j] = (uint32_t)shift - 1 - j + (1U << 31U); - sigma_1_mapping[n - 1 - j] = (uint32_t)n - 1 - j; - sigma_2_mapping[n - 1 - j] = (uint32_t)n - 1 - j + (1U << 30U); - sigma_3_mapping[n - 1 - j] = (uint32_t)n - 1 - j + (1U << 31U); - } - - polynomial sigma_1(proving_key->circuit_size); - polynomial sigma_2(proving_key->circuit_size); - polynomial sigma_3(proving_key->circuit_size); - - // plonk::compute_permutation_lagrange_base_single(sigma_1, sigma_1_mapping, - // proving_key->small_domain); plonk::compute_permutation_lagrange_base_single(sigma_2, - // sigma_2_mapping, proving_key->small_domain); - // plonk::compute_permutation_lagrange_base_single(sigma_3, sigma_3_mapping, - // proving_key->small_domain); - - polynomial sigma_1_lagrange_base(sigma_1, proving_key->circuit_size); - polynomial sigma_2_lagrange_base(sigma_2, proving_key->circuit_size); - polynomial sigma_3_lagrange_base(sigma_3, proving_key->circuit_size); - - proving_key->polynomial_store.put("sigma_1_lagrange", std::move(sigma_1_lagrange_base)); - proving_key->polynomial_store.put("sigma_2_lagrange", std::move(sigma_2_lagrange_base)); - proving_key->polynomial_store.put("sigma_3_lagrange", std::move(sigma_3_lagrange_base)); - - compute_standard_honk_id_polynomials<3>(proving_key); - compute_first_and_last_lagrange_polynomials(proving_key); - - proving_key->polynomial_store.put("w_1_lagrange", std::move(w_l)); - proving_key->polynomial_store.put("w_2_lagrange", std::move(w_r)); - proving_key->polynomial_store.put("w_3_lagrange", std::move(w_o)); - - proving_key->polynomial_store.put("q_1_lagrange", std::move(q_l)); - proving_key->polynomial_store.put("q_2_lagrange", std::move(q_r)); - proving_key->polynomial_store.put("q_3_lagrange", std::move(q_o)); - proving_key->polynomial_store.put("q_m_lagrange", std::move(q_m)); - proving_key->polynomial_store.put("q_c_lagrange", std::move(q_c)); - - // TODO(#223)(Cody): This should be more generic - std::vector witness_polynomials; - auto prover = StandardProver(std::move(witness_polynomials), proving_key); - - std::unique_ptr kate_commitment_key = - std::make_unique(proving_key->circuit_size, "../srs_db/ignition"); - - return prover; - } -}; - -using FieldTypes = testing::Types; -TYPED_TEST_SUITE(VerifierTests, FieldTypes); - -// This test is modeled after a corresponding test for the Plonk Verifier. As is the case there, this test relies on -// valid proof construction which makes the scope quite large. Not really a unit test but a nice test nonetheless. -// TODO(#223)(Luke/Cody): Make this a meaningful test (or remove altogether) -TYPED_TEST(VerifierTests, VerifyArithmeticProofSmall) -{ - GTEST_SKIP() << "It's good to have a standalone test, but for now we just rely on composer tests."; - size_t n = 8; - - StandardProver prover = TestFixture::generate_test_data(n); - - StandardVerifier verifier = TestFixture::generate_verifier(prover.key); - - // construct proof - plonk::proof proof = prover.construct_proof(); - - // verify proof - bool result = verifier.verify_proof(proof); - - EXPECT_EQ(result, true); -} - -} // namespace test_honk_verifier diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/work_queue.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/work_queue.hpp index c666053adce..bbb6867b793 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/work_queue.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/proof_system/work_queue.hpp @@ -1,7 +1,6 @@ #pragma once #include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include #include @@ -30,24 +29,18 @@ template class work_queue { }; private: - std::shared_ptr proving_key; // TODO(luke): Consider handling all transcript interactions in the prover rather than embedding them in the queue. proof_system::honk::ProverTranscript& transcript; CommitmentKey commitment_key; std::vector work_item_queue; public: - explicit work_queue(std::shared_ptr& proving_key, - proof_system::honk::ProverTranscript& prover_transcript) - : proving_key(proving_key) - , transcript(prover_transcript) - , commitment_key(proving_key->circuit_size, - "../srs_db/ignition"){}; // TODO(luke): make this properly parameterized + explicit work_queue(size_t circuit_size, proof_system::honk::ProverTranscript& prover_transcript) + : transcript(prover_transcript) + , commitment_key(circuit_size, "../srs_db/ignition"){}; // TODO(luke): make this properly parameterized work_queue(const work_queue& other) = default; work_queue(work_queue&& other) noexcept = default; - work_queue& operator=(const work_queue& other) = delete; - work_queue& operator=(work_queue&& other) = delete; ~work_queue() = default; [[nodiscard]] work_item_info get_queued_work_item_info() const diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp index d30650154a0..3e40df01134 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/polynomials/multivariates.test.cpp @@ -5,17 +5,16 @@ #include #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/numeric/random/engine.hpp" +#include "barretenberg/honk/flavor/standard.hpp" using namespace proof_system::honk::sumcheck; namespace test_sumcheck_polynomials { -template class MultivariatesTests : public testing::Test {}; +template class MultivariatesTests : public testing::Test {}; -using FieldTypes = testing::Types; -using Transcript = proof_system::honk::ProverTranscript; -TYPED_TEST_SUITE(MultivariatesTests, FieldTypes); +using Flavors = testing::Types; -#define MULTIVARIATES_TESTS_TYPE_ALIASES using FF = TypeParam; +TYPED_TEST_SUITE(MultivariatesTests, Flavors); /* * We represent a bivariate f0 as f0(X0, X1). The indexing starts from 0 to match with the round number in sumcheck. @@ -45,7 +44,9 @@ TYPED_TEST_SUITE(MultivariatesTests, FieldTypes); */ TYPED_TEST(MultivariatesTests, FoldTwoRoundsSpecial) { - MULTIVARIATES_TESTS_TYPE_ALIASES + using Flavor = TypeParam; + using FF = typename Flavor::FF; + using Transcript = honk::ProverTranscript; // values here are chosen to check another test const size_t multivariate_d(2); @@ -59,8 +60,8 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsSpecial) std::array f0 = { v00, v10, v01, v11 }; auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = honk::ProverTranscript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto transcript = Transcript::init_empty(); + auto sumcheck = Sumcheck(multivariate_n, transcript); FF round_challenge_0 = { 0x6c7301b49d85a46c, 0x44311531e39c64f6, 0xb13d66d8d6c1a24c, 0x04410c360230a295 }; round_challenge_0.self_to_montgomery_form(); @@ -81,7 +82,9 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsSpecial) TYPED_TEST(MultivariatesTests, FoldTwoRoundsGeneric) { - MULTIVARIATES_TESTS_TYPE_ALIASES + using Flavor = TypeParam; + using FF = typename Flavor::FF; + using Transcript = honk::ProverTranscript; const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); @@ -94,8 +97,8 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsGeneric) std::array f0 = { v00, v10, v01, v11 }; auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = honk::ProverTranscript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto transcript = Transcript::init_empty(); + auto sumcheck = Sumcheck(multivariate_n, transcript); FF round_challenge_0 = FF::random_element(); FF expected_lo = v00 * (FF(1) - round_challenge_0) + v10 * round_challenge_0; @@ -136,7 +139,9 @@ TYPED_TEST(MultivariatesTests, FoldTwoRoundsGeneric) */ TYPED_TEST(MultivariatesTests, FoldThreeRoundsSpecial) { - MULTIVARIATES_TESTS_TYPE_ALIASES + using Flavor = TypeParam; + using FF = typename Flavor::FF; + using Transcript = honk::ProverTranscript; const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -153,8 +158,8 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsSpecial) std::array f0 = { v000, v100, v010, v110, v001, v101, v011, v111 }; auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = honk::ProverTranscript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto transcript = Transcript::init_empty(); + auto sumcheck = Sumcheck(multivariate_n, transcript); FF round_challenge_0 = 1; FF expected_q1 = v000 * (FF(1) - round_challenge_0) + v100 * round_challenge_0; // 2 @@ -185,7 +190,9 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsSpecial) TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) { - MULTIVARIATES_TESTS_TYPE_ALIASES + using Flavor = TypeParam; + using FF = typename Flavor::FF; + using Transcript = honk::ProverTranscript; const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -202,8 +209,8 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) std::array f0 = { v000, v100, v010, v110, v001, v101, v011, v111 }; auto full_polynomials = std::array, 1>({ f0 }); - auto transcript = honk::ProverTranscript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto transcript = Transcript::init_empty(); + auto sumcheck = Sumcheck(multivariate_n, transcript); FF round_challenge_0 = FF::random_element(); FF expected_q1 = v000 * (FF(1) - round_challenge_0) + v100 * round_challenge_0; @@ -234,7 +241,10 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGeneric) TYPED_TEST(MultivariatesTests, FoldThreeRoundsGenericMultiplePolys) { - MULTIVARIATES_TESTS_TYPE_ALIASES + using Flavor = TypeParam; + using FF = typename Flavor::FF; + using Transcript = honk::ProverTranscript; + const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); std::array v000; @@ -261,8 +271,8 @@ TYPED_TEST(MultivariatesTests, FoldThreeRoundsGenericMultiplePolys) std::array f2 = { v000[2], v100[2], v010[2], v110[2], v001[2], v101[2], v011[2], v111[2] }; auto full_polynomials = std::array, 3>{ f0, f1, f2 }; - auto transcript = honk::ProverTranscript::init_empty(); - auto sumcheck = Sumcheck(multivariate_n, transcript); + auto transcript = Transcript::init_empty(); + auto sumcheck = Sumcheck(multivariate_n, transcript); std::array expected_q1; std::array expected_q2; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp index 55947abeb45..e7d095119c8 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp @@ -2,7 +2,6 @@ #include #include -#include "barretenberg/honk/flavor/flavor.hpp" #include "../polynomials/univariate.hpp" #include "relation.hpp" @@ -12,7 +11,6 @@ template class ArithmeticRelation { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 4; - using MULTIVARIATE = StandardHonk::MULTIVARIATE; // could just get from StandardArithmetization /** * @brief Expression for the StandardArithmetic gate. @@ -32,14 +30,14 @@ template class ArithmeticRelation { // OPTIMIZATION?: Karatsuba in general, at least for some degrees? // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both - auto w_l = UnivariateView(extended_edges[MULTIVARIATE::W_L]); - auto w_r = UnivariateView(extended_edges[MULTIVARIATE::W_R]); - auto w_o = UnivariateView(extended_edges[MULTIVARIATE::W_O]); - auto q_m = UnivariateView(extended_edges[MULTIVARIATE::Q_M]); - auto q_l = UnivariateView(extended_edges[MULTIVARIATE::Q_L]); - auto q_r = UnivariateView(extended_edges[MULTIVARIATE::Q_R]); - auto q_o = UnivariateView(extended_edges[MULTIVARIATE::Q_O]); - auto q_c = UnivariateView(extended_edges[MULTIVARIATE::Q_C]); + auto w_l = UnivariateView(extended_edges.w_l); + auto w_r = UnivariateView(extended_edges.w_r); + auto w_o = UnivariateView(extended_edges.w_o); + auto q_m = UnivariateView(extended_edges.q_m); + auto q_l = UnivariateView(extended_edges.q_l); + auto q_r = UnivariateView(extended_edges.q_r); + auto q_o = UnivariateView(extended_edges.q_o); + auto q_c = UnivariateView(extended_edges.q_c); auto tmp = w_l * (q_m * w_r + q_l); tmp += q_r * w_r; @@ -53,14 +51,14 @@ template class ArithmeticRelation { const auto& purported_evaluations, const RelationParameters&) const { - 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]; + auto w_l = purported_evaluations.w_l; + auto w_r = purported_evaluations.w_r; + auto w_o = purported_evaluations.w_o; + auto q_m = purported_evaluations.q_m; + auto q_l = purported_evaluations.q_l; + auto q_r = purported_evaluations.q_r; + auto q_o = purported_evaluations.q_o; + auto q_c = purported_evaluations.q_c; full_honk_relation_value += w_l * (q_m * w_r + q_l); full_honk_relation_value += q_r * w_r; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp index cdf89004d43..ff2bc0ea8f8 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp @@ -1,6 +1,5 @@ #pragma once #include "relation.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" #include "../polynomials/univariate.hpp" // TODO(luke): change name of this file to permutation_grand_product_relation(s).hpp and move 'init' relation into it. @@ -10,7 +9,6 @@ template class GrandProductComputationRelation { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 5; - using MULTIVARIATE = StandardHonk::MULTIVARIATE; /** * @brief Compute contribution of the permutation relation for a given edge (internal function) @@ -39,19 +37,19 @@ template class GrandProductComputationRelation { const auto& gamma = relation_parameters.gamma; const auto& public_input_delta = relation_parameters.public_input_delta; - auto w_1 = UnivariateView(extended_edges[MULTIVARIATE::W_L]); - auto w_2 = UnivariateView(extended_edges[MULTIVARIATE::W_R]); - auto w_3 = UnivariateView(extended_edges[MULTIVARIATE::W_O]); - auto sigma_1 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_1]); - auto sigma_2 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_2]); - auto sigma_3 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_3]); - auto id_1 = UnivariateView(extended_edges[MULTIVARIATE::ID_1]); - auto id_2 = UnivariateView(extended_edges[MULTIVARIATE::ID_2]); - auto id_3 = UnivariateView(extended_edges[MULTIVARIATE::ID_3]); - auto z_perm = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM]); - auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); - auto lagrange_first = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_FIRST]); - auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + auto w_1 = UnivariateView(extended_edges.w_l); + auto w_2 = UnivariateView(extended_edges.w_r); + auto w_3 = UnivariateView(extended_edges.w_o); + auto sigma_1 = UnivariateView(extended_edges.sigma_1); + auto sigma_2 = UnivariateView(extended_edges.sigma_2); + auto sigma_3 = UnivariateView(extended_edges.sigma_3); + auto id_1 = UnivariateView(extended_edges.id_1); + auto id_2 = UnivariateView(extended_edges.id_2); + auto id_3 = UnivariateView(extended_edges.id_3); + auto z_perm = UnivariateView(extended_edges.z_perm); + auto z_perm_shift = UnivariateView(extended_edges.z_perm_shift); + auto lagrange_first = UnivariateView(extended_edges.lagrange_first); + auto lagrange_last = UnivariateView(extended_edges.lagrange_last); // Contribution (1) evals += (((z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * @@ -69,19 +67,19 @@ template class GrandProductComputationRelation { const auto& gamma = relation_parameters.gamma; const auto& public_input_delta = relation_parameters.public_input_delta; - 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_2]; - auto id_3 = purported_evaluations[MULTIVARIATE::ID_3]; - auto z_perm = purported_evaluations[MULTIVARIATE::Z_PERM]; - auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; - auto lagrange_first = purported_evaluations[MULTIVARIATE::LAGRANGE_FIRST]; - auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; + auto w_1 = purported_evaluations.w_l; + auto w_2 = purported_evaluations.w_r; + auto w_3 = purported_evaluations.w_o; + auto sigma_1 = purported_evaluations.sigma_1; + auto sigma_2 = purported_evaluations.sigma_2; + auto sigma_3 = purported_evaluations.sigma_3; + auto id_1 = purported_evaluations.id_1; + auto id_2 = purported_evaluations.id_2; + auto id_3 = purported_evaluations.id_3; + auto z_perm = purported_evaluations.z_perm; + auto z_perm_shift = purported_evaluations.z_perm_shift; + auto lagrange_first = purported_evaluations.lagrange_first; + auto lagrange_last = purported_evaluations.lagrange_last; // Contribution (1) full_honk_relation_value += @@ -98,7 +96,6 @@ template class UltraGrandProductComputationRelation { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; - using MULTIVARIATE = proof_system::honk::UltraArithmetization::POLYNOMIAL; /** * @brief Compute contribution of the permutation relation for a given edge (internal function) @@ -120,22 +117,22 @@ template class UltraGrandProductComputationRelation { const auto& gamma = relation_parameters.gamma; const auto& public_input_delta = relation_parameters.public_input_delta; - auto w_1 = UnivariateView(extended_edges[MULTIVARIATE::W_L]); - auto w_2 = UnivariateView(extended_edges[MULTIVARIATE::W_R]); - auto w_3 = UnivariateView(extended_edges[MULTIVARIATE::W_O]); - auto w_4 = UnivariateView(extended_edges[MULTIVARIATE::W_4]); - auto sigma_1 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_1]); - auto sigma_2 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_2]); - auto sigma_3 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_3]); - auto sigma_4 = UnivariateView(extended_edges[MULTIVARIATE::SIGMA_4]); - auto id_1 = UnivariateView(extended_edges[MULTIVARIATE::ID_1]); - auto id_2 = UnivariateView(extended_edges[MULTIVARIATE::ID_2]); - auto id_3 = UnivariateView(extended_edges[MULTIVARIATE::ID_3]); - auto id_4 = UnivariateView(extended_edges[MULTIVARIATE::ID_4]); - auto z_perm = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM]); - auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); - auto lagrange_first = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_FIRST]); - auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + auto w_1 = UnivariateView(extended_edges.w_l); + auto w_2 = UnivariateView(extended_edges.w_r); + auto w_3 = UnivariateView(extended_edges.w_o); + auto w_4 = UnivariateView(extended_edges.w_4); + auto sigma_1 = UnivariateView(extended_edges.sigma_1); + auto sigma_2 = UnivariateView(extended_edges.sigma_2); + auto sigma_3 = UnivariateView(extended_edges.sigma_3); + auto sigma_4 = UnivariateView(extended_edges.sigma_4); + auto id_1 = UnivariateView(extended_edges.id_1); + auto id_2 = UnivariateView(extended_edges.id_2); + auto id_3 = UnivariateView(extended_edges.id_3); + auto id_4 = UnivariateView(extended_edges.id_4); + auto z_perm = UnivariateView(extended_edges.z_perm); + auto z_perm_shift = UnivariateView(extended_edges.z_perm_shift); + auto lagrange_first = UnivariateView(extended_edges.lagrange_first); + auto lagrange_last = UnivariateView(extended_edges.lagrange_last); // Contribution (1) evals += (((z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * @@ -153,22 +150,22 @@ template class UltraGrandProductComputationRelation { const auto& gamma = relation_parameters.gamma; const auto& public_input_delta = relation_parameters.public_input_delta; - 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 w_4 = purported_evaluations[MULTIVARIATE::W_4]; - 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 sigma_4 = purported_evaluations[MULTIVARIATE::SIGMA_4]; - auto id_1 = purported_evaluations[MULTIVARIATE::ID_1]; - auto id_2 = purported_evaluations[MULTIVARIATE::ID_2]; - auto id_3 = purported_evaluations[MULTIVARIATE::ID_3]; - auto id_4 = purported_evaluations[MULTIVARIATE::ID_4]; - auto z_perm = purported_evaluations[MULTIVARIATE::Z_PERM]; - auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; - auto lagrange_first = purported_evaluations[MULTIVARIATE::LAGRANGE_FIRST]; - auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; + auto w_1 = purported_evaluations.w_l; + auto w_2 = purported_evaluations.w_r; + auto w_3 = purported_evaluations.w_o; + auto w_4 = purported_evaluations.w_4; + auto sigma_1 = purported_evaluations.sigma_1; + auto sigma_2 = purported_evaluations.sigma_2; + auto sigma_3 = purported_evaluations.sigma_3; + auto sigma_4 = purported_evaluations.sigma_4; + auto id_1 = purported_evaluations.id_1; + auto id_2 = purported_evaluations.id_2; + auto id_3 = purported_evaluations.id_3; + auto id_4 = purported_evaluations.id_4; + auto z_perm = purported_evaluations.z_perm; + auto z_perm_shift = purported_evaluations.z_perm_shift; + auto lagrange_first = purported_evaluations.lagrange_first; + auto lagrange_last = purported_evaluations.lagrange_last; // Contribution (1) full_honk_relation_value += diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp index 6aa7d9f3b27..0fd8fbd6067 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp @@ -1,6 +1,5 @@ #pragma once #include "relation.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" #include "../polynomials/univariate.hpp" namespace proof_system::honk::sumcheck { @@ -9,7 +8,6 @@ template class GrandProductInitializationRelation { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 3; - using MULTIVARIATE = StandardHonk::MULTIVARIATE; // could just get from StandardArithmetization /** * @brief Add contribution of the permutation relation for a given edge @@ -29,8 +27,8 @@ template class GrandProductInitializationRelation { const RelationParameters&, const FF& scaling_factor) const { - auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); - auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + auto z_perm_shift = UnivariateView(extended_edges.z_perm_shift); + auto lagrange_last = UnivariateView(extended_edges.lagrange_last); evals += (lagrange_last * z_perm_shift) * scaling_factor; }; @@ -39,8 +37,8 @@ template class GrandProductInitializationRelation { auto& purported_evaluations, const RelationParameters&) const { - auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; - auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; + auto z_perm_shift = purported_evaluations.z_perm_shift; + auto lagrange_last = purported_evaluations.lagrange_last; full_honk_relation_value += lagrange_last * z_perm_shift; }; @@ -53,7 +51,6 @@ template class UltraGrandProductInitializationRelation { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 3; - using MULTIVARIATE = UltraArithmetization::POLYNOMIAL; // could just get from StandardArithmetization /** * @brief Add contribution of the permutation relation for a given edge @@ -73,8 +70,8 @@ template class UltraGrandProductInitializationRelation { const RelationParameters&, const FF& scaling_factor) const { - auto z_perm_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_PERM_SHIFT]); - auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + auto z_perm_shift = UnivariateView(extended_edges.z_perm_shift); + auto lagrange_last = UnivariateView(extended_edges.lagrange_last); evals += (lagrange_last * z_perm_shift) * scaling_factor; }; @@ -83,8 +80,8 @@ template class UltraGrandProductInitializationRelation { auto& purported_evaluations, const RelationParameters&) const { - auto z_perm_shift = purported_evaluations[MULTIVARIATE::Z_PERM_SHIFT]; - auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; + auto z_perm_shift = purported_evaluations.z_perm_shift; + auto lagrange_last = purported_evaluations.lagrange_last; full_honk_relation_value += lagrange_last * z_perm_shift; }; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp index a7495eee31f..32830a8dc3f 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp @@ -1,15 +1,16 @@ #pragma once #include "relation.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" #include "../polynomials/univariate.hpp" +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused-parameter" + namespace proof_system::honk::sumcheck { template class LookupGrandProductComputationRelation { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; // deg(z_lookup * column_selector * wire * q_lookup * table) = 5 - using MULTIVARIATE = proof_system::honk::UltraArithmetization::POLYNOMIAL; /** * @brief Compute contribution of the lookup grand prod relation for a given edge (internal function) @@ -44,38 +45,38 @@ template class LookupGrandProductComputationRelation { const auto eta_sqr = eta * eta; const auto eta_cube = eta_sqr * eta; - auto w_1 = UnivariateView(extended_edges[MULTIVARIATE::W_L]); - auto w_2 = UnivariateView(extended_edges[MULTIVARIATE::W_R]); - auto w_3 = UnivariateView(extended_edges[MULTIVARIATE::W_O]); + auto w_1 = UnivariateView(extended_edges.w_l); + auto w_2 = UnivariateView(extended_edges.w_r); + auto w_3 = UnivariateView(extended_edges.w_o); - auto w_1_shift = UnivariateView(extended_edges[MULTIVARIATE::W_1_SHIFT]); - auto w_2_shift = UnivariateView(extended_edges[MULTIVARIATE::W_2_SHIFT]); - auto w_3_shift = UnivariateView(extended_edges[MULTIVARIATE::W_3_SHIFT]); + auto w_1_shift = UnivariateView(extended_edges.w_l_shift); + auto w_2_shift = UnivariateView(extended_edges.w_r_shift); + auto w_3_shift = UnivariateView(extended_edges.w_o_shift); - auto table_1 = UnivariateView(extended_edges[MULTIVARIATE::TABLE_1]); - auto table_2 = UnivariateView(extended_edges[MULTIVARIATE::TABLE_2]); - auto table_3 = UnivariateView(extended_edges[MULTIVARIATE::TABLE_3]); - auto table_4 = UnivariateView(extended_edges[MULTIVARIATE::TABLE_4]); + auto table_1 = UnivariateView(extended_edges.table_1); + auto table_2 = UnivariateView(extended_edges.table_2); + auto table_3 = UnivariateView(extended_edges.table_3); + auto table_4 = UnivariateView(extended_edges.table_4); - auto table_1_shift = UnivariateView(extended_edges[MULTIVARIATE::TABLE_1_SHIFT]); - auto table_2_shift = UnivariateView(extended_edges[MULTIVARIATE::TABLE_2_SHIFT]); - auto table_3_shift = UnivariateView(extended_edges[MULTIVARIATE::TABLE_3_SHIFT]); - auto table_4_shift = UnivariateView(extended_edges[MULTIVARIATE::TABLE_4_SHIFT]); + auto table_1_shift = UnivariateView(extended_edges.table_1_shift); + auto table_2_shift = UnivariateView(extended_edges.table_2_shift); + auto table_3_shift = UnivariateView(extended_edges.table_3_shift); + auto table_4_shift = UnivariateView(extended_edges.table_4_shift); - auto s_accum = UnivariateView(extended_edges[MULTIVARIATE::S_ACCUM]); - auto s_accum_shift = UnivariateView(extended_edges[MULTIVARIATE::S_ACCUM_SHIFT]); + auto s_accum = UnivariateView(extended_edges.sorted_accum); + auto s_accum_shift = UnivariateView(extended_edges.sorted_accum_shift); - auto z_lookup = UnivariateView(extended_edges[MULTIVARIATE::Z_LOOKUP]); - auto z_lookup_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_LOOKUP_SHIFT]); + auto z_lookup = UnivariateView(extended_edges.z_lookup); + auto z_lookup_shift = UnivariateView(extended_edges.z_lookup_shift); - auto table_index = UnivariateView(extended_edges[MULTIVARIATE::Q_O]); - auto column_1_step_size = UnivariateView(extended_edges[MULTIVARIATE::Q_R]); - auto column_2_step_size = UnivariateView(extended_edges[MULTIVARIATE::Q_M]); - auto column_3_step_size = UnivariateView(extended_edges[MULTIVARIATE::Q_C]); - auto q_lookup = UnivariateView(extended_edges[MULTIVARIATE::QLOOKUPTYPE]); + auto table_index = UnivariateView(extended_edges.q_o); + auto column_1_step_size = UnivariateView(extended_edges.q_r); + auto column_2_step_size = UnivariateView(extended_edges.q_m); + auto column_3_step_size = UnivariateView(extended_edges.q_c); + auto q_lookup = UnivariateView(extended_edges.q_lookup); - auto lagrange_first = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_FIRST]); - auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + auto lagrange_first = UnivariateView(extended_edges.lagrange_first); + auto lagrange_last = UnivariateView(extended_edges.lagrange_last); // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η²(w_3 + q_c*w_3_shift) + η³q_index. auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + @@ -111,37 +112,38 @@ template class LookupGrandProductComputationRelation { const auto eta_sqr = eta * eta; const auto eta_cube = eta_sqr * eta; - 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 w_1 = purported_evaluations.w_l; + auto w_2 = purported_evaluations.w_r; + auto w_3 = purported_evaluations.w_o; + + auto w_1_shift = purported_evaluations.w_l_shift; + auto w_2_shift = purported_evaluations.w_r_shift; + auto w_3_shift = purported_evaluations.w_o_shift; - auto w_1_shift = purported_evaluations[MULTIVARIATE::W_1_SHIFT]; - auto w_2_shift = purported_evaluations[MULTIVARIATE::W_2_SHIFT]; - auto w_3_shift = purported_evaluations[MULTIVARIATE::W_3_SHIFT]; + auto table_1 = purported_evaluations.table_1; + auto table_2 = purported_evaluations.table_2; + auto table_3 = purported_evaluations.table_3; + auto table_4 = purported_evaluations.table_4; - auto table_1 = purported_evaluations[MULTIVARIATE::TABLE_1]; - auto table_2 = purported_evaluations[MULTIVARIATE::TABLE_2]; - auto table_3 = purported_evaluations[MULTIVARIATE::TABLE_3]; - auto table_4 = purported_evaluations[MULTIVARIATE::TABLE_4]; + auto table_1_shift = purported_evaluations.table_1_shift; + auto table_2_shift = purported_evaluations.table_2_shift; + auto table_3_shift = purported_evaluations.table_3_shift; + auto table_4_shift = purported_evaluations.table_4_shift; - auto table_1_shift = purported_evaluations[MULTIVARIATE::TABLE_1_SHIFT]; - auto table_2_shift = purported_evaluations[MULTIVARIATE::TABLE_2_SHIFT]; - auto table_3_shift = purported_evaluations[MULTIVARIATE::TABLE_3_SHIFT]; - auto table_4_shift = purported_evaluations[MULTIVARIATE::TABLE_4_SHIFT]; + auto s_accum = purported_evaluations.sorted_accum; + auto s_accum_shift = purported_evaluations.sorted_accum_shift; - auto s_accum = purported_evaluations[MULTIVARIATE::S_ACCUM]; - auto s_accum_shift = purported_evaluations[MULTIVARIATE::S_ACCUM_SHIFT]; - auto z_lookup = purported_evaluations[MULTIVARIATE::Z_LOOKUP]; - auto z_lookup_shift = purported_evaluations[MULTIVARIATE::Z_LOOKUP_SHIFT]; + auto z_lookup = purported_evaluations.z_lookup; + auto z_lookup_shift = purported_evaluations.z_lookup_shift; - auto table_index = purported_evaluations[MULTIVARIATE::Q_O]; - auto column_1_step_size = purported_evaluations[MULTIVARIATE::Q_R]; - auto column_2_step_size = purported_evaluations[MULTIVARIATE::Q_M]; - auto column_3_step_size = purported_evaluations[MULTIVARIATE::Q_C]; - auto q_lookup = purported_evaluations[MULTIVARIATE::QLOOKUPTYPE]; + auto table_index = purported_evaluations.q_o; + auto column_1_step_size = purported_evaluations.q_r; + auto column_2_step_size = purported_evaluations.q_m; + auto column_3_step_size = purported_evaluations.q_c; + auto q_lookup = purported_evaluations.q_lookup; - auto lagrange_first = purported_evaluations[MULTIVARIATE::LAGRANGE_FIRST]; - auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; + auto lagrange_first = purported_evaluations.lagrange_first; + auto lagrange_last = purported_evaluations.lagrange_last; // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η²(w_3 + q_c*w_3_shift) + η³q_index. auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + @@ -168,7 +170,6 @@ template class LookupGrandProductInitializationRelation { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 3; // deg(lagrange_last * z_lookup_shift) = 2 - using MULTIVARIATE = proof_system::honk::UltraArithmetization::POLYNOMIAL; /** * @brief Compute contribution of the lookup grand prod relation for a given edge (internal function) @@ -186,8 +187,8 @@ template class LookupGrandProductInitializationRelation { const RelationParameters& /*unused*/, const FF& scaling_factor) const { - auto z_lookup_shift = UnivariateView(extended_edges[MULTIVARIATE::Z_LOOKUP_SHIFT]); - auto lagrange_last = UnivariateView(extended_edges[MULTIVARIATE::LAGRANGE_LAST]); + auto z_lookup_shift = UnivariateView(extended_edges.z_lookup_shift); + auto lagrange_last = UnivariateView(extended_edges.lagrange_last); evals += (lagrange_last * z_lookup_shift) * scaling_factor; }; @@ -196,8 +197,8 @@ template class LookupGrandProductInitializationRelation { auto& purported_evaluations, const RelationParameters& /*unused*/) const { - auto z_lookup_shift = purported_evaluations[MULTIVARIATE::Z_LOOKUP_SHIFT]; - auto lagrange_last = purported_evaluations[MULTIVARIATE::LAGRANGE_LAST]; + auto z_lookup_shift = purported_evaluations.z_lookup_shift; + auto lagrange_last = purported_evaluations.lagrange_last; full_honk_relation_value += lagrange_last * z_lookup_shift; }; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp index fb7a5875d77..be3cce97088 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_consistency.test.cpp @@ -1,8 +1,8 @@ #include "barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp" #include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp" +#include "barretenberg/honk/flavor/standard.hpp" #include "relation.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" #include "arithmetic_relation.hpp" #include "grand_product_initialization_relation.hpp" #include "grand_product_computation_relation.hpp" @@ -29,64 +29,28 @@ static const size_t INPUT_UNIVARIATE_LENGTH = 2; namespace proof_system::honk_relation_tests { -template class RelationConsistency : public testing::Test { +class StandardRelationConsistency : public testing::Test { public: - template using Univariate = Univariate; - template using UnivariateView = UnivariateView; - using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; + using Flavor = honk::flavor::Standard; + using FF = typename Flavor::FF; + using PurportedEvaluations = typename Flavor::PurportedEvaluations; + // TODO(#390): Move MAX_RELATION_LENGTH into Flavor and simplify this. + + template using ExtendedEdges = typename Flavor::template ExtendedEdges; + // TODO(#225)(Adrian): Accept FULL_RELATION_LENGTH as a template parameter for this function only, so that the test // can decide to which degree the polynomials must be extended. Possible accept an existing list of "edges" and // extend them to the degree. template - static std::array, NUM_POLYNOMIALS> compute_mock_extended_edges( - std::array, NUM_POLYNOMIALS>& input_univariates) + static void compute_mock_extended_edges( + ExtendedEdges& extended_edges, + std::array, NUM_POLYNOMIALS>& input_edges) { BarycentricData barycentric_2_to_max = BarycentricData(); - std::array, NUM_POLYNOMIALS> extended_univariates; for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - extended_univariates[i] = barycentric_2_to_max.extend(input_univariates[i]); + extended_edges[i] = barycentric_2_to_max.extend(input_edges[i]); } - auto w_l = Univariate(extended_univariates[0]); - auto w_r = Univariate(extended_univariates[1]); - auto w_o = Univariate(extended_univariates[2]); - auto z_perm = Univariate(extended_univariates[3]); - auto z_perm_shift = Univariate(extended_univariates[4]); // this is not real shifted data - auto q_m = Univariate(extended_univariates[5]); - auto q_l = Univariate(extended_univariates[6]); - auto q_r = Univariate(extended_univariates[7]); - auto q_o = Univariate(extended_univariates[8]); - auto q_c = Univariate(extended_univariates[9]); - auto sigma_1 = Univariate(extended_univariates[10]); - auto sigma_2 = Univariate(extended_univariates[11]); - auto sigma_3 = Univariate(extended_univariates[12]); - auto id_1 = Univariate(extended_univariates[13]); - auto id_2 = Univariate(extended_univariates[14]); - auto id_3 = Univariate(extended_univariates[15]); - auto lagrange_first = Univariate(extended_univariates[16]); - auto lagrange_last = Univariate(extended_univariates[17]); - // Construct extended edges array in order determined by enum - std::array, NUM_POLYNOMIALS> extended_edges; - extended_edges[POLYNOMIAL::W_L] = w_l; - extended_edges[POLYNOMIAL::W_R] = w_r; - extended_edges[POLYNOMIAL::W_O] = w_o; - extended_edges[POLYNOMIAL::Z_PERM] = z_perm; - extended_edges[POLYNOMIAL::Z_PERM_SHIFT] = z_perm_shift; - extended_edges[POLYNOMIAL::Q_M] = q_m; - extended_edges[POLYNOMIAL::Q_L] = q_l; - extended_edges[POLYNOMIAL::Q_R] = q_r; - extended_edges[POLYNOMIAL::Q_O] = q_o; - extended_edges[POLYNOMIAL::Q_C] = q_c; - extended_edges[POLYNOMIAL::SIGMA_1] = sigma_1; - extended_edges[POLYNOMIAL::SIGMA_2] = sigma_2; - extended_edges[POLYNOMIAL::SIGMA_3] = sigma_3; - extended_edges[POLYNOMIAL::ID_1] = id_1; - extended_edges[POLYNOMIAL::ID_2] = id_2; - extended_edges[POLYNOMIAL::ID_3] = id_3; - extended_edges[POLYNOMIAL::LAGRANGE_FIRST] = lagrange_first; - extended_edges[POLYNOMIAL::LAGRANGE_LAST] = lagrange_last; - - return extended_edges; } /** @@ -117,14 +81,15 @@ template class RelationConsistency : public testing::Test { * @param i index of the evaluations we want to take from each univariate * @return std::array such that result[j] = univariates[j].value_at(i) */ - template - static std::array transposed_univariate_array_at( - const std::array, NUM_UNIVARIATES>& univariates, size_t i) + template + static PurportedEvaluations transposed_univariate_array_at(ExtendedEdges univariates, size_t i) { ASSERT(i < univariate_length); - std::array result; - for (size_t j = 0; j < NUM_UNIVARIATES; ++j) { - result[j] = univariates[j].value_at(i); + std::array result; + size_t result_idx = 0; // TODO(#391) zip + for (auto& univariate : univariates) { + result[result_idx] = univariate.value_at(i); + ++result_idx; } return result; }; @@ -141,19 +106,18 @@ template class RelationConsistency : public testing::Test { * @param extended_edges * @param relation_parameters */ - template - static void validate_evaluations( - const Univariate& expected_evals, - const auto relation, - const std::array, NUM_POLYNOMIALS>& extended_edges, - const RelationParameters& relation_parameters) + template + static void validate_evaluations(const Univariate& expected_evals, + const auto relation, + const ExtendedEdges& extended_edges, + const RelationParameters& relation_parameters) { // Compute the expression index-by-index - Univariate expected_evals_index{ 0 }; + Univariate expected_evals_index{ 0 }; for (size_t i = 0; i < FULL_RELATION_LENGTH; ++i) { // Get an array of the same size as `extended_edges` with only the i-th element of each extended edge. - std::array evals_i = transposed_univariate_array_at(extended_edges, i); + PurportedEvaluations evals_i = transposed_univariate_array_at(extended_edges, i); // Evaluate the relation relation.add_full_relation_value_contribution( expected_evals_index.value_at(i), evals_i, relation_parameters); @@ -161,93 +125,90 @@ template class RelationConsistency : public testing::Test { EXPECT_EQ(expected_evals, expected_evals_index); // Compute the expression using the class, that converts the extended edges to UnivariateView - auto expected_evals_view = Univariate(0); + auto expected_evals_view = Univariate(0); // The scaling factor is essentially 1 since we are working with degree 1 univariates relation.add_edge_contribution(expected_evals_view, extended_edges, relation_parameters, 1); // Tiny hack to reduce `expected_evals` to be of size `relation.RELATION_LENGTH` - Univariate expected_evals_restricted{ UnivariateView( - expected_evals) }; + Univariate expected_evals_restricted{ + UnivariateView(expected_evals) + }; EXPECT_EQ(expected_evals_restricted, expected_evals_view); }; }; -using FieldTypes = testing::Types; -TYPED_TEST_SUITE(RelationConsistency, FieldTypes); - -#define SUMCHECK_RELATION_TYPE_ALIASES using FF = TypeParam; -TYPED_TEST(RelationConsistency, ArithmeticRelation) +TEST_F(StandardRelationConsistency, ArithmeticRelation) { - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::StandardArithmetization::POLYNOMIAL; - + using Flavor = honk::flavor::Standard; + using FF = typename Flavor::FF; static constexpr size_t FULL_RELATION_LENGTH = 5; - static const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; + using ExtendedEdges = typename Flavor::template ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); + const auto relation_parameters = compute_mock_relation_parameters(); auto run_test = [&relation_parameters](bool is_random_input) { - std::array, NUM_POLYNOMIALS> extended_edges; std::array, NUM_POLYNOMIALS> input_polynomials; + ExtendedEdges extended_edges; if (!is_random_input) { // evaluation form, i.e. input_univariate(0) = 1, input_univariate(1) = 2,.. The polynomial is x+1. for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = Univariate({ 1, 2 }); } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + compute_mock_extended_edges(extended_edges, input_polynomials); } else { // input_univariates are random polynomials of degree one for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + compute_mock_extended_edges(extended_edges, input_polynomials); }; auto relation = ArithmeticRelation(); // Manually compute the expected edge contribution - const auto& w_l = extended_edges[MULTIVARIATE::W_L]; - const auto& w_r = extended_edges[MULTIVARIATE::W_R]; - const auto& w_o = extended_edges[MULTIVARIATE::W_O]; - const auto& q_m = extended_edges[MULTIVARIATE::Q_M]; - const auto& q_l = extended_edges[MULTIVARIATE::Q_L]; - const auto& q_r = extended_edges[MULTIVARIATE::Q_R]; - const auto& q_o = extended_edges[MULTIVARIATE::Q_O]; - const auto& q_c = extended_edges[MULTIVARIATE::Q_C]; + const auto& w_l = extended_edges.w_l; + const auto& w_r = extended_edges.w_r; + const auto& w_o = extended_edges.w_o; + const auto& q_m = extended_edges.q_m; + const auto& q_l = extended_edges.q_l; + const auto& q_r = extended_edges.q_r; + const auto& q_o = extended_edges.q_o; + const auto& q_c = extended_edges.q_c; // We first compute the evaluations using UnivariateViews, with the provided hard-coded formula. // Ensure that expression changes are detected. // expected_evals, length 4, extends to { { 5, 22, 57, 116, 205} } for input polynomial {1, 2} auto expected_evals = (q_m * w_r * w_l) + (q_r * w_r) + (q_l * w_l) + (q_o * w_o) + (q_c); - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; run_test(/* is_random_input=*/true); run_test(/* is_random_input=*/false); }; -TYPED_TEST(RelationConsistency, GrandProductComputationRelation) +TEST_F(StandardRelationConsistency, GrandProductComputationRelation) { - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::StandardArithmetization::POLYNOMIAL; - + using Flavor = honk::flavor::Standard; + using FF = typename Flavor::FF; static constexpr size_t FULL_RELATION_LENGTH = 5; - static const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; + using ExtendedEdges = typename Flavor::template ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); + const auto relation_parameters = compute_mock_relation_parameters(); auto run_test = [&relation_parameters](bool is_random_input) { - std::array, NUM_POLYNOMIALS> extended_edges; + ExtendedEdges extended_edges; std::array, NUM_POLYNOMIALS> input_polynomials; if (!is_random_input) { // evaluation form, i.e. input_univariate(0) = 1, input_univariate(1) = 2,.. The polynomial is x+1. for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = Univariate({ 1, 2 }); } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + compute_mock_extended_edges(extended_edges, input_polynomials); } else { // input_univariates are random polynomials of degree one for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + compute_mock_extended_edges(extended_edges, input_polynomials); }; auto relation = GrandProductComputationRelation(); @@ -261,19 +222,19 @@ TYPED_TEST(RelationConsistency, GrandProductComputationRelation) // auto z_perm_shift = Univariate({ 1, 4, 9, 16, 25 }); // X^2 // Manually compute the expected edge contribution - const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; - const auto& w_2 = extended_edges[MULTIVARIATE::W_R]; - const auto& w_3 = extended_edges[MULTIVARIATE::W_O]; - const auto& sigma_1 = extended_edges[MULTIVARIATE::SIGMA_1]; - const auto& sigma_2 = extended_edges[MULTIVARIATE::SIGMA_2]; - const auto& sigma_3 = extended_edges[MULTIVARIATE::SIGMA_3]; - const auto& id_1 = extended_edges[MULTIVARIATE::ID_1]; - const auto& id_2 = extended_edges[MULTIVARIATE::ID_2]; - const auto& id_3 = extended_edges[MULTIVARIATE::ID_3]; - const auto& z_perm = extended_edges[MULTIVARIATE::Z_PERM]; - const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; - const auto& lagrange_first = extended_edges[MULTIVARIATE::LAGRANGE_FIRST]; - const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; + const auto& w_1 = extended_edges.w_l; + const auto& w_2 = extended_edges.w_r; + const auto& w_3 = extended_edges.w_o; + const auto& sigma_1 = extended_edges.sigma_1; + const auto& sigma_2 = extended_edges.sigma_2; + const auto& sigma_3 = extended_edges.sigma_3; + const auto& id_1 = extended_edges.id_1; + const auto& id_2 = extended_edges.id_2; + const auto& id_3 = extended_edges.id_3; + const auto& z_perm = extended_edges.z_perm; + const auto& z_perm_shift = extended_edges.z_perm_shift; + const auto& lagrange_first = extended_edges.lagrange_first; + const auto& lagrange_last = extended_edges.lagrange_last; // We first compute the evaluations using UnivariateViews, with the provided hard-coded formula. // Ensure that expression changes are detected. @@ -283,317 +244,50 @@ TYPED_TEST(RelationConsistency, GrandProductComputationRelation) (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma); - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; run_test(/* is_random_input=*/true); run_test(/* is_random_input=*/false); }; -TYPED_TEST(RelationConsistency, GrandProductInitializationRelation) +TEST_F(StandardRelationConsistency, GrandProductInitializationRelation) { - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::StandardArithmetization::POLYNOMIAL; - + using Flavor = honk::flavor::Standard; + using FF = typename Flavor::FF; static constexpr size_t FULL_RELATION_LENGTH = 5; - static const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; + using ExtendedEdges = typename Flavor::template ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); + const auto relation_parameters = compute_mock_relation_parameters(); auto run_test = [&relation_parameters](bool is_random_input) { - std::array, NUM_POLYNOMIALS> extended_edges; + ExtendedEdges extended_edges; std::array, NUM_POLYNOMIALS> input_polynomials; if (!is_random_input) { // evaluation form, i.e. input_univariate(0) = 1, input_univariate(1) = 2,.. The polynomial is x+1. for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = Univariate({ 1, 2 }); } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + compute_mock_extended_edges(extended_edges, input_polynomials); } else { // input_univariates are random polynomials of degree one for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); + compute_mock_extended_edges(extended_edges, input_polynomials); }; auto relation = GrandProductInitializationRelation(); - const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; - const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; + const auto& z_perm_shift = extended_edges.z_perm_shift; + const auto& lagrange_last = extended_edges.lagrange_last; // We first compute the evaluations using UnivariateViews, with the provided hard-coded formula. // Ensure that expression changes are detected. // expected_evals, lenght 3 (coeff form = x^2 + x), extends to { { 0, 2, 6, 12, 20 } } auto expected_evals = z_perm_shift * lagrange_last; - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); }; run_test(/* is_random_input=*/true); run_test(/* is_random_input=*/false); }; -TYPED_TEST(RelationConsistency, UltraArithmeticRelation) -{ - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; - - static constexpr size_t FULL_RELATION_LENGTH = 6; - static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; - - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); - std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; - - // input_univariates are random polynomials of degree one - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); - } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); - - auto relation = UltraArithmeticRelation(); - - // Extract the extended edges for manual computation of relation contribution - const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; - const auto& w_2 = extended_edges[MULTIVARIATE::W_R]; - const auto& w_3 = extended_edges[MULTIVARIATE::W_O]; - const auto& w_4 = extended_edges[MULTIVARIATE::W_4]; - const auto& w_4_shift = extended_edges[MULTIVARIATE::W_4_SHIFT]; - const auto& q_m = extended_edges[MULTIVARIATE::Q_M]; - const auto& q_l = extended_edges[MULTIVARIATE::Q_L]; - const auto& q_r = extended_edges[MULTIVARIATE::Q_R]; - const auto& q_o = extended_edges[MULTIVARIATE::Q_O]; - const auto& q_4 = extended_edges[MULTIVARIATE::Q_4]; - const auto& q_c = extended_edges[MULTIVARIATE::Q_C]; - const auto& q_arith = extended_edges[MULTIVARIATE::QARITH]; - - static const FF neg_half = FF(-2).invert(); - - auto expected_evals = (q_arith - 3) * (q_m * w_2 * w_1) * neg_half; - expected_evals += (q_l * w_1) + (q_r * w_2) + (q_o * w_3) + (q_4 * w_4) + q_c; - expected_evals += (q_arith - 1) * w_4_shift; - expected_evals *= q_arith; - - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); -}; - -TYPED_TEST(RelationConsistency, UltraArithmeticRelationSecondary) -{ - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; - - static constexpr size_t FULL_RELATION_LENGTH = 6; - static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; - - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); - std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; - - // input_univariates are random polynomials of degree one - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); - } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); - - auto relation = UltraArithmeticRelationSecondary(); - - // Extract the extended edges for manual computation of relation contribution - const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; - const auto& w_4 = extended_edges[MULTIVARIATE::W_4]; - const auto& w_1_shift = extended_edges[MULTIVARIATE::W_1_SHIFT]; - const auto& q_m = extended_edges[MULTIVARIATE::Q_M]; - const auto& q_arith = extended_edges[MULTIVARIATE::QARITH]; - - auto expected_evals = (w_1 + w_4 - w_1_shift + q_m); - expected_evals *= (q_arith - 2) * (q_arith - 1) * q_arith; - - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); -}; - -TYPED_TEST(RelationConsistency, UltraGrandProductInitializationRelation) -{ - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; - - static constexpr size_t FULL_RELATION_LENGTH = 6; - static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; - - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); - std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; - - // input_univariates are random polynomials of degree one - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); - } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); - - auto relation = UltraGrandProductInitializationRelation(); - - // Extract the extended edges for manual computation of relation contribution - const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; - const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; - - // Compute the expected result using a simple to read version of the relation expression - auto expected_evals = z_perm_shift * lagrange_last; - - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); -}; - -TYPED_TEST(RelationConsistency, UltraGrandProductComputationRelation) -{ - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; - - static constexpr size_t FULL_RELATION_LENGTH = 6; - static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; - - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); - std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; - - // input_univariates are random polynomials of degree one - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); - } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); - - auto relation = UltraGrandProductComputationRelation(); - - const auto& beta = relation_parameters.beta; - const auto& gamma = relation_parameters.gamma; - const auto& public_input_delta = relation_parameters.public_input_delta; - - // Extract the extended edges for manual computation of relation contribution - const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; - const auto& w_2 = extended_edges[MULTIVARIATE::W_R]; - const auto& w_3 = extended_edges[MULTIVARIATE::W_O]; - const auto& w_4 = extended_edges[MULTIVARIATE::W_4]; - const auto& sigma_1 = extended_edges[MULTIVARIATE::SIGMA_1]; - const auto& sigma_2 = extended_edges[MULTIVARIATE::SIGMA_2]; - const auto& sigma_3 = extended_edges[MULTIVARIATE::SIGMA_3]; - const auto& sigma_4 = extended_edges[MULTIVARIATE::SIGMA_4]; - const auto& id_1 = extended_edges[MULTIVARIATE::ID_1]; - const auto& id_2 = extended_edges[MULTIVARIATE::ID_2]; - const auto& id_3 = extended_edges[MULTIVARIATE::ID_3]; - const auto& id_4 = extended_edges[MULTIVARIATE::ID_4]; - const auto& z_perm = extended_edges[MULTIVARIATE::Z_PERM]; - const auto& z_perm_shift = extended_edges[MULTIVARIATE::Z_PERM_SHIFT]; - const auto& lagrange_first = extended_edges[MULTIVARIATE::LAGRANGE_FIRST]; - const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; - - // Compute the expected result using a simple to read version of the relation expression - auto expected_evals = (z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * - (w_3 + id_3 * beta + gamma) * (w_4 + id_4 * beta + gamma) - - (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * - (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma) * - (w_4 + sigma_4 * beta + gamma); - - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); -}; - -TYPED_TEST(RelationConsistency, LookupGrandProductComputationRelation) -{ - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; - - static constexpr size_t FULL_RELATION_LENGTH = 6; - static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; - - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); - std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; - - // input_univariates are random polynomials of degree one - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); - } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); - - auto relation = LookupGrandProductComputationRelation(); - - const auto eta = relation_parameters.eta; - const auto beta = relation_parameters.beta; - const auto gamma = relation_parameters.gamma; - auto grand_product_delta = relation_parameters.lookup_grand_product_delta; - - // Extract the extended edges for manual computation of relation contribution - auto one_plus_beta = FF::one() + beta; - auto gamma_by_one_plus_beta = gamma * one_plus_beta; - auto eta_sqr = eta * eta; - auto eta_cube = eta_sqr * eta; - - const auto& w_1 = extended_edges[MULTIVARIATE::W_L]; - const auto& w_2 = extended_edges[MULTIVARIATE::W_R]; - const auto& w_3 = extended_edges[MULTIVARIATE::W_O]; - - const auto& w_1_shift = extended_edges[MULTIVARIATE::W_1_SHIFT]; - const auto& w_2_shift = extended_edges[MULTIVARIATE::W_2_SHIFT]; - const auto& w_3_shift = extended_edges[MULTIVARIATE::W_3_SHIFT]; - - const auto& table_1 = extended_edges[MULTIVARIATE::TABLE_1]; - const auto& table_2 = extended_edges[MULTIVARIATE::TABLE_2]; - const auto& table_3 = extended_edges[MULTIVARIATE::TABLE_3]; - const auto& table_4 = extended_edges[MULTIVARIATE::TABLE_4]; - - const auto& table_1_shift = extended_edges[MULTIVARIATE::TABLE_1_SHIFT]; - const auto& table_2_shift = extended_edges[MULTIVARIATE::TABLE_2_SHIFT]; - const auto& table_3_shift = extended_edges[MULTIVARIATE::TABLE_3_SHIFT]; - const auto& table_4_shift = extended_edges[MULTIVARIATE::TABLE_4_SHIFT]; - - const auto& s_accum = extended_edges[MULTIVARIATE::S_ACCUM]; - const auto& s_accum_shift = extended_edges[MULTIVARIATE::S_ACCUM_SHIFT]; - const auto& z_lookup = extended_edges[MULTIVARIATE::Z_LOOKUP]; - const auto& z_lookup_shift = extended_edges[MULTIVARIATE::Z_LOOKUP_SHIFT]; - - const auto& table_index = extended_edges[MULTIVARIATE::Q_O]; - const auto& column_1_step_size = extended_edges[MULTIVARIATE::Q_R]; - const auto& column_2_step_size = extended_edges[MULTIVARIATE::Q_M]; - const auto& column_3_step_size = extended_edges[MULTIVARIATE::Q_C]; - const auto& q_lookup = extended_edges[MULTIVARIATE::QLOOKUPTYPE]; - - const auto& lagrange_first = extended_edges[MULTIVARIATE::LAGRANGE_FIRST]; - const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; - - auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + - (w_3 + column_3_step_size * w_3_shift) * eta_sqr + table_index * eta_cube; - - auto table_accum = table_1 + table_2 * eta + table_3 * eta_sqr + table_4 * eta_cube; - auto table_accum_shift = table_1_shift + table_2_shift * eta + table_3_shift * eta_sqr + table_4_shift * eta_cube; - - // Compute the expected result using a simple to read version of the relation expression - auto expected_evals = (z_lookup + lagrange_first) * (q_lookup * wire_accum + gamma) * - (table_accum + table_accum_shift * beta + gamma_by_one_plus_beta) * one_plus_beta; - expected_evals -= (z_lookup_shift + lagrange_last * grand_product_delta) * - (s_accum + s_accum_shift * beta + gamma_by_one_plus_beta); - - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); -}; - -TYPED_TEST(RelationConsistency, LookupGrandProductInitializationRelation) -{ - SUMCHECK_RELATION_TYPE_ALIASES - using MULTIVARIATE = honk::UltraArithmetization::POLYNOMIAL; - - static constexpr size_t FULL_RELATION_LENGTH = 6; - static const size_t NUM_POLYNOMIALS = proof_system::honk::UltraArithmetization::COUNT; - - const auto relation_parameters = TestFixture::compute_mock_relation_parameters(); - std::array, NUM_POLYNOMIALS> extended_edges; - std::array, NUM_POLYNOMIALS> input_polynomials; - - // input_univariates are random polynomials of degree one - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); - } - extended_edges = TestFixture::template compute_mock_extended_edges(input_polynomials); - - auto relation = LookupGrandProductInitializationRelation(); - - // Extract the extended edges for manual computation of relation contribution - const auto& z_lookup_shift = extended_edges[MULTIVARIATE::Z_LOOKUP_SHIFT]; - const auto& lagrange_last = extended_edges[MULTIVARIATE::LAGRANGE_LAST]; - - // Compute the expected result using a simple to read version of the relation expression - auto expected_evals = z_lookup_shift * lagrange_last; - - TestFixture::template validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); -}; - } // namespace proof_system::honk_relation_tests diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp index 39b9971d4c6..b71d4fa938a 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/relation_correctness.test.cpp @@ -1,24 +1,15 @@ +#include + #include "barretenberg/honk/composer/ultra_honk_composer.hpp" #include "barretenberg/honk/composer/standard_honk_composer.hpp" #include "barretenberg/honk/proof_system/prover_library.hpp" #include "barretenberg/honk/sumcheck/relations/relation.hpp" +#include "barretenberg/honk/sumcheck/relations/arithmetic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" #include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp" #include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp" -#include "barretenberg/numeric/uint256/uint256.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" -#include -#include -#include "barretenberg/honk/proof_system/prover.hpp" -#include "barretenberg/honk/sumcheck/sumcheck_round.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_computation_relation.hpp" -#include "barretenberg/honk/sumcheck/relations/grand_product_initialization_relation.hpp" #include "barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp" -#include "barretenberg/honk/utils/grand_product_delta.hpp" -#include "barretenberg/polynomials/polynomial.hpp" - -#include -#include -#include using namespace proof_system::honk; @@ -36,9 +27,13 @@ namespace test_honk_relations { */ TEST(RelationCorrectness, StandardRelationCorrectness) { + using Flavor = honk::flavor::Standard; + using FF = typename Flavor::FF; + using ProverPolynomials = typename Flavor::ProverPolynomials; + using PurportedEvaluations = typename Flavor::PurportedEvaluations; + // Create a composer and a dummy circuit with a few gates auto composer = StandardHonkComposer(); - static const size_t num_wires = StandardHonkComposer::num_wires; fr a = fr::one(); // Using the public variable to check that public_input_delta is computed and added to the relation correctly uint32_t a_idx = composer.add_public_variable(a); @@ -62,56 +57,57 @@ TEST(RelationCorrectness, StandardRelationCorrectness) // Compute public input delta const auto public_inputs = composer.circuit_constructor.get_public_inputs(); auto public_input_delta = - honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); + honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); - sumcheck::RelationParameters params{ + sumcheck::RelationParameters params{ .beta = beta, .gamma = gamma, .public_input_delta = public_input_delta, }; - constexpr size_t num_polynomials = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; // Compute grand product polynomial polynomial z_permutation = - prover_library::compute_permutation_grand_product(prover.key, prover.wire_polynomials, beta, gamma); + prover_library::compute_permutation_grand_product(prover.key, beta, gamma); // Create an array of spans to the underlying polynomials to more easily // get the transposition. // Ex: polynomial_spans[3][i] returns the i-th coefficient of the third polynomial // in the list below - std::array, num_polynomials> evaluations_array; - - using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; - evaluations_array[POLYNOMIAL::W_L] = prover.wire_polynomials[0]; - evaluations_array[POLYNOMIAL::W_R] = prover.wire_polynomials[1]; - evaluations_array[POLYNOMIAL::W_O] = prover.wire_polynomials[2]; - evaluations_array[POLYNOMIAL::Z_PERM] = z_permutation; - evaluations_array[POLYNOMIAL::Z_PERM_SHIFT] = z_permutation.shifted(); - evaluations_array[POLYNOMIAL::Q_M] = prover.key->polynomial_store.get("q_m_lagrange"); - evaluations_array[POLYNOMIAL::Q_L] = prover.key->polynomial_store.get("q_1_lagrange"); - evaluations_array[POLYNOMIAL::Q_R] = prover.key->polynomial_store.get("q_2_lagrange"); - evaluations_array[POLYNOMIAL::Q_O] = prover.key->polynomial_store.get("q_3_lagrange"); - evaluations_array[POLYNOMIAL::Q_C] = prover.key->polynomial_store.get("q_c_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_1] = prover.key->polynomial_store.get("sigma_1_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_2] = prover.key->polynomial_store.get("sigma_2_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_3] = prover.key->polynomial_store.get("sigma_3_lagrange"); - evaluations_array[POLYNOMIAL::ID_1] = prover.key->polynomial_store.get("id_1_lagrange"); - evaluations_array[POLYNOMIAL::ID_2] = prover.key->polynomial_store.get("id_2_lagrange"); - evaluations_array[POLYNOMIAL::ID_3] = prover.key->polynomial_store.get("id_3_lagrange"); - evaluations_array[POLYNOMIAL::LAGRANGE_FIRST] = prover.key->polynomial_store.get("L_first_lagrange"); - evaluations_array[POLYNOMIAL::LAGRANGE_LAST] = prover.key->polynomial_store.get("L_last_lagrange"); + ProverPolynomials prover_polynomials; + + prover_polynomials.w_l = prover.key->w_l; + prover_polynomials.w_r = prover.key->w_r; + prover_polynomials.w_o = prover.key->w_o; + prover_polynomials.z_perm = z_permutation; + prover_polynomials.z_perm_shift = z_permutation.shifted(); + prover_polynomials.q_m = prover.key->q_m; + prover_polynomials.q_l = prover.key->q_l; + prover_polynomials.q_r = prover.key->q_r; + prover_polynomials.q_o = prover.key->q_o; + prover_polynomials.q_c = prover.key->q_c; + prover_polynomials.sigma_1 = prover.key->sigma_1; + prover_polynomials.sigma_2 = prover.key->sigma_2; + prover_polynomials.sigma_3 = prover.key->sigma_3; + prover_polynomials.id_1 = prover.key->id_1; + prover_polynomials.id_2 = prover.key->id_2; + prover_polynomials.id_3 = prover.key->id_3; + prover_polynomials.lagrange_first = prover.key->lagrange_first; + prover_polynomials.lagrange_last = prover.key->lagrange_last; // Construct the round for applying sumcheck relations and results for storing computed results - auto relations = std::tuple(honk::sumcheck::ArithmeticRelation(), - honk::sumcheck::GrandProductComputationRelation(), - honk::sumcheck::GrandProductInitializationRelation()); + auto relations = std::tuple(honk::sumcheck::ArithmeticRelation(), + honk::sumcheck::GrandProductComputationRelation(), + honk::sumcheck::GrandProductInitializationRelation()); fr result = 0; for (size_t i = 0; i < prover.key->circuit_size; i++) { // Compute an array containing all the evaluations at a given row i - std::array evaluations_at_index_i; - for (size_t j = 0; j < num_polynomials; ++j) { - evaluations_at_index_i[j] = evaluations_array[j][i]; + + PurportedEvaluations evaluations_at_index_i; + size_t poly_idx = 0; + for (auto& polynomial : prover_polynomials) { + evaluations_at_index_i[poly_idx] = polynomial[i]; + ++poly_idx; } // For each relation, call the `accumulate_relation_evaluation` over all witness/selector values at the @@ -142,11 +138,14 @@ TEST(RelationCorrectness, StandardRelationCorrectness) // TODO(luke): Ensure all relations are added as they are implemented for Ultra Honk TEST(RelationCorrectness, UltraRelationCorrectness) { + using Flavor = honk::flavor::Ultra; + using FF = typename Flavor::FF; + using ProverPolynomials = typename Flavor::ProverPolynomials; + using PurportedEvaluations = typename Flavor::PurportedEvaluations; + // Create a composer and a dummy circuit with a few gates auto composer = UltraHonkComposer(); - static const size_t num_wires = 4; - barretenberg::fr pedersen_input_value = fr::random_element(); fr a = fr::one(); // Using the public variable to check that public_input_delta is computed and added to the relation correctly @@ -197,11 +196,11 @@ TEST(RelationCorrectness, UltraRelationCorrectness) // Compute public input delta const auto public_inputs = composer.circuit_constructor.get_public_inputs(); auto public_input_delta = - honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); + honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); auto lookup_grand_product_delta = - honk::compute_lookup_grand_product_delta(beta, gamma, prover.key->circuit_size); + honk::compute_lookup_grand_product_delta(beta, gamma, prover.key->circuit_size); - sumcheck::RelationParameters params{ + sumcheck::RelationParameters params{ .eta = eta, .beta = beta, .gamma = gamma, @@ -209,105 +208,99 @@ TEST(RelationCorrectness, UltraRelationCorrectness) .lookup_grand_product_delta = lookup_grand_product_delta, }; - constexpr size_t num_polynomials = proof_system::honk::UltraArithmetization::COUNT; - - // Compute permutation grand product polynomial - auto z_permutation = - prover_library::compute_permutation_grand_product(prover.key, prover.wire_polynomials, beta, gamma); + // Compute grand product polynomial + auto z_permutation = prover_library::compute_permutation_grand_product(prover.key, beta, gamma); // Construct local sorted_list_polynomials to pass to compute_sorted_list_accumulator() + // TODO(luke): this clunkiness can be cleaned up once we decide where the sorted polynomials will be stored: proving + // key or prover std::vector sorted_list_polynomials; + auto sorted_polynomials = prover.key->get_sorted_polynomials(); for (size_t i = 0; i < 4; ++i) { - std::string label = "s_" + std::to_string(i + 1) + "_lagrange"; - sorted_list_polynomials.emplace_back(prover.key->polynomial_store.get(label)); + sorted_list_polynomials.emplace_back(prover.key->circuit_size); + for (size_t j = 0; j < prover.key->circuit_size; ++j) { + sorted_list_polynomials[i][j] = sorted_polynomials[i][j]; + } } + // Compute sorted witness-table accumulator auto sorted_list_accumulator = - prover_library::compute_sorted_list_accumulator(prover.key, sorted_list_polynomials, eta); + prover_library::compute_sorted_list_accumulator(prover.key, sorted_list_polynomials, eta); // Compute lookup grand product polynomial - auto z_lookup = prover_library::compute_lookup_grand_product( - prover.key, prover.wire_polynomials, sorted_list_accumulator, eta, beta, gamma); + auto z_lookup = + prover_library::compute_lookup_grand_product(prover.key, sorted_list_accumulator, eta, beta, gamma); // Create an array of spans to the underlying polynomials to more easily // get the transposition. // Ex: polynomial_spans[3][i] returns the i-th coefficient of the third polynomial // in the list below - std::array, num_polynomials> evaluations_array; - - using POLYNOMIAL = proof_system::honk::UltraArithmetization::POLYNOMIAL; - evaluations_array[POLYNOMIAL::W_L] = prover.wire_polynomials[0]; - evaluations_array[POLYNOMIAL::W_R] = prover.wire_polynomials[1]; - evaluations_array[POLYNOMIAL::W_O] = prover.wire_polynomials[2]; - evaluations_array[POLYNOMIAL::W_4] = prover.wire_polynomials[3]; - evaluations_array[POLYNOMIAL::W_1_SHIFT] = prover.wire_polynomials[0].shifted(); - evaluations_array[POLYNOMIAL::W_2_SHIFT] = prover.wire_polynomials[1].shifted(); - evaluations_array[POLYNOMIAL::W_3_SHIFT] = prover.wire_polynomials[2].shifted(); - evaluations_array[POLYNOMIAL::W_4_SHIFT] = prover.wire_polynomials[3].shifted(); - - evaluations_array[POLYNOMIAL::S_1] = prover.key->polynomial_store.get("s_1_lagrange"); - evaluations_array[POLYNOMIAL::S_2] = prover.key->polynomial_store.get("s_2_lagrange"); - evaluations_array[POLYNOMIAL::S_3] = prover.key->polynomial_store.get("s_3_lagrange"); - evaluations_array[POLYNOMIAL::S_4] = prover.key->polynomial_store.get("s_4_lagrange"); - - evaluations_array[POLYNOMIAL::S_ACCUM] = sorted_list_accumulator; - evaluations_array[POLYNOMIAL::S_ACCUM_SHIFT] = sorted_list_accumulator.shifted(); - - evaluations_array[POLYNOMIAL::Z_PERM] = z_permutation; - evaluations_array[POLYNOMIAL::Z_PERM_SHIFT] = z_permutation.shifted(); - - evaluations_array[POLYNOMIAL::Z_LOOKUP] = z_lookup; - evaluations_array[POLYNOMIAL::Z_LOOKUP_SHIFT] = z_lookup.shifted(); - - evaluations_array[POLYNOMIAL::Q_M] = prover.key->polynomial_store.get("q_m_lagrange"); - evaluations_array[POLYNOMIAL::Q_L] = prover.key->polynomial_store.get("q_1_lagrange"); - evaluations_array[POLYNOMIAL::Q_R] = prover.key->polynomial_store.get("q_2_lagrange"); - evaluations_array[POLYNOMIAL::Q_O] = prover.key->polynomial_store.get("q_3_lagrange"); - evaluations_array[POLYNOMIAL::Q_4] = prover.key->polynomial_store.get("q_4_lagrange"); - evaluations_array[POLYNOMIAL::Q_C] = prover.key->polynomial_store.get("q_c_lagrange"); - evaluations_array[POLYNOMIAL::QARITH] = prover.key->polynomial_store.get("q_arith_lagrange"); - evaluations_array[POLYNOMIAL::QSORT] = prover.key->polynomial_store.get("q_sort_lagrange"); - evaluations_array[POLYNOMIAL::QELLIPTIC] = prover.key->polynomial_store.get("q_elliptic_lagrange"); - evaluations_array[POLYNOMIAL::QAUX] = prover.key->polynomial_store.get("q_aux_lagrange"); - evaluations_array[POLYNOMIAL::QLOOKUPTYPE] = prover.key->polynomial_store.get("table_type_lagrange"); - - evaluations_array[POLYNOMIAL::SIGMA_1] = prover.key->polynomial_store.get("sigma_1_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_2] = prover.key->polynomial_store.get("sigma_2_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_3] = prover.key->polynomial_store.get("sigma_3_lagrange"); - evaluations_array[POLYNOMIAL::SIGMA_4] = prover.key->polynomial_store.get("sigma_4_lagrange"); - - evaluations_array[POLYNOMIAL::ID_1] = prover.key->polynomial_store.get("id_1_lagrange"); - evaluations_array[POLYNOMIAL::ID_2] = prover.key->polynomial_store.get("id_2_lagrange"); - evaluations_array[POLYNOMIAL::ID_3] = prover.key->polynomial_store.get("id_3_lagrange"); - evaluations_array[POLYNOMIAL::ID_4] = prover.key->polynomial_store.get("id_4_lagrange"); - - evaluations_array[POLYNOMIAL::TABLE_1] = prover.key->polynomial_store.get("table_value_1_lagrange"); - evaluations_array[POLYNOMIAL::TABLE_2] = prover.key->polynomial_store.get("table_value_2_lagrange"); - evaluations_array[POLYNOMIAL::TABLE_3] = prover.key->polynomial_store.get("table_value_3_lagrange"); - evaluations_array[POLYNOMIAL::TABLE_4] = prover.key->polynomial_store.get("table_value_4_lagrange"); - - evaluations_array[POLYNOMIAL::TABLE_1_SHIFT] = prover.key->polynomial_store.get("table_value_1_lagrange").shifted(); - evaluations_array[POLYNOMIAL::TABLE_2_SHIFT] = prover.key->polynomial_store.get("table_value_2_lagrange").shifted(); - evaluations_array[POLYNOMIAL::TABLE_3_SHIFT] = prover.key->polynomial_store.get("table_value_3_lagrange").shifted(); - evaluations_array[POLYNOMIAL::TABLE_4_SHIFT] = prover.key->polynomial_store.get("table_value_4_lagrange").shifted(); - - evaluations_array[POLYNOMIAL::LAGRANGE_FIRST] = prover.key->polynomial_store.get("L_first_lagrange"); - evaluations_array[POLYNOMIAL::LAGRANGE_LAST] = prover.key->polynomial_store.get("L_last_lagrange"); + ProverPolynomials prover_polynomials; + + prover_polynomials.w_l = prover.key->w_l; + prover_polynomials.w_r = prover.key->w_r; + prover_polynomials.w_o = prover.key->w_o; + prover_polynomials.w_4 = prover.key->w_4; + prover_polynomials.w_l_shift = prover.key->w_l.shifted(); + prover_polynomials.w_r_shift = prover.key->w_r.shifted(); + prover_polynomials.w_o_shift = prover.key->w_o.shifted(); + prover_polynomials.w_4_shift = prover.key->w_4.shifted(); + prover_polynomials.sorted_1 = prover.key->sorted_1; + prover_polynomials.sorted_2 = prover.key->sorted_2; + prover_polynomials.sorted_3 = prover.key->sorted_3; + prover_polynomials.sorted_4 = prover.key->sorted_4; + prover_polynomials.sorted_accum = sorted_list_accumulator; + prover_polynomials.sorted_accum_shift = sorted_list_accumulator.shifted(); + prover_polynomials.table_1 = prover.key->table_1; + prover_polynomials.table_2 = prover.key->table_2; + prover_polynomials.table_3 = prover.key->table_3; + prover_polynomials.table_4 = prover.key->table_4; + prover_polynomials.table_1_shift = prover.key->table_1.shifted(); + prover_polynomials.table_2_shift = prover.key->table_2.shifted(); + prover_polynomials.table_3_shift = prover.key->table_3.shifted(); + prover_polynomials.table_4_shift = prover.key->table_4.shifted(); + prover_polynomials.z_perm = z_permutation; + prover_polynomials.z_perm_shift = z_permutation.shifted(); + prover_polynomials.z_lookup = z_lookup; + prover_polynomials.z_lookup_shift = z_lookup.shifted(); + prover_polynomials.q_m = prover.key->q_m; + prover_polynomials.q_l = prover.key->q_l; + prover_polynomials.q_r = prover.key->q_r; + prover_polynomials.q_o = prover.key->q_o; + prover_polynomials.q_c = prover.key->q_c; + prover_polynomials.q_4 = prover.key->q_4; + prover_polynomials.q_arith = prover.key->q_arith; + prover_polynomials.q_sort = prover.key->q_sort; + prover_polynomials.q_elliptic = prover.key->q_elliptic; + prover_polynomials.q_aux = prover.key->q_aux; + prover_polynomials.q_lookup = prover.key->q_lookup; + prover_polynomials.sigma_1 = prover.key->sigma_1; + prover_polynomials.sigma_2 = prover.key->sigma_2; + prover_polynomials.sigma_3 = prover.key->sigma_3; + prover_polynomials.sigma_4 = prover.key->sigma_4; + prover_polynomials.id_1 = prover.key->id_1; + prover_polynomials.id_2 = prover.key->id_2; + prover_polynomials.id_3 = prover.key->id_3; + prover_polynomials.id_4 = prover.key->id_4; + prover_polynomials.lagrange_first = prover.key->lagrange_first; + prover_polynomials.lagrange_last = prover.key->lagrange_last; // Construct the round for applying sumcheck relations and results for storing computed results - auto relations = std::tuple(honk::sumcheck::UltraArithmeticRelation(), - honk::sumcheck::UltraArithmeticRelationSecondary(), - honk::sumcheck::UltraGrandProductInitializationRelation(), - honk::sumcheck::UltraGrandProductComputationRelation(), - honk::sumcheck::LookupGrandProductComputationRelation(), - honk::sumcheck::LookupGrandProductInitializationRelation()); + auto relations = std::tuple(honk::sumcheck::UltraArithmeticRelation(), + honk::sumcheck::UltraArithmeticRelationSecondary(), + honk::sumcheck::UltraGrandProductInitializationRelation(), + honk::sumcheck::UltraGrandProductComputationRelation(), + honk::sumcheck::LookupGrandProductComputationRelation(), + honk::sumcheck::LookupGrandProductInitializationRelation()); fr result = 0; for (size_t i = 0; i < prover.key->circuit_size; i++) { // Compute an array containing all the evaluations at a given row i - std::array evaluations_at_index_i; - for (size_t j = 0; j < num_polynomials; ++j) { - evaluations_at_index_i[j] = evaluations_array[j][i]; + PurportedEvaluations evaluations_at_index_i; + size_t poly_idx = 0; + for (auto& polynomial : prover_polynomials) { + evaluations_at_index_i[poly_idx] = polynomial[i]; + ++poly_idx; } // For each relation, call the `accumulate_relation_evaluation` over all witness/selector values at the diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp index 2df6efc2c7a..dd5aa02b85c 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp @@ -2,7 +2,6 @@ #include #include -#include "barretenberg/honk/flavor/flavor.hpp" #include "../polynomials/univariate.hpp" #include "relation.hpp" @@ -12,7 +11,6 @@ template class UltraArithmeticRelation { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 6; // degree(q_arith^2 * q_m * w_r * w_l) = 5 - using MULTIVARIATE = UltraArithmetization::POLYNOMIAL; /** * @brief Expression for the Ultra Arithmetic gate. @@ -35,18 +33,18 @@ template class UltraArithmeticRelation { // OPTIMIZATION?: Karatsuba in general, at least for some degrees? // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both - auto w_l = UnivariateView(extended_edges[MULTIVARIATE::W_L]); - auto w_r = UnivariateView(extended_edges[MULTIVARIATE::W_R]); - auto w_o = UnivariateView(extended_edges[MULTIVARIATE::W_O]); - auto w_4 = UnivariateView(extended_edges[MULTIVARIATE::W_4]); - auto w_4_shift = UnivariateView(extended_edges[MULTIVARIATE::W_4_SHIFT]); - auto q_m = UnivariateView(extended_edges[MULTIVARIATE::Q_M]); - auto q_l = UnivariateView(extended_edges[MULTIVARIATE::Q_L]); - auto q_r = UnivariateView(extended_edges[MULTIVARIATE::Q_R]); - auto q_o = UnivariateView(extended_edges[MULTIVARIATE::Q_O]); - auto q_4 = UnivariateView(extended_edges[MULTIVARIATE::Q_4]); - auto q_c = UnivariateView(extended_edges[MULTIVARIATE::Q_C]); - auto q_arith = UnivariateView(extended_edges[MULTIVARIATE::QARITH]); + auto w_l = UnivariateView(extended_edges.w_l); + auto w_r = UnivariateView(extended_edges.w_r); + auto w_o = UnivariateView(extended_edges.w_o); + auto w_4 = UnivariateView(extended_edges.w_4); + auto w_4_shift = UnivariateView(extended_edges.w_4_shift); + auto q_m = UnivariateView(extended_edges.q_m); + auto q_l = UnivariateView(extended_edges.q_l); + auto q_r = UnivariateView(extended_edges.q_r); + auto q_o = UnivariateView(extended_edges.q_o); + auto q_4 = UnivariateView(extended_edges.q_4); + auto q_c = UnivariateView(extended_edges.q_c); + auto q_arith = UnivariateView(extended_edges.q_arith); static const FF neg_half = FF(-2).invert(); @@ -62,18 +60,18 @@ template class UltraArithmeticRelation { const auto& purported_evaluations, const RelationParameters&) const { - 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 w_4 = purported_evaluations[MULTIVARIATE::W_4]; - auto w_4_shift = purported_evaluations[MULTIVARIATE::W_4_SHIFT]; - 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_4 = purported_evaluations[MULTIVARIATE::Q_4]; - auto q_c = purported_evaluations[MULTIVARIATE::Q_C]; - auto q_arith = purported_evaluations[MULTIVARIATE::QARITH]; + auto w_l = purported_evaluations.w_l; + auto w_r = purported_evaluations.w_r; + auto w_o = purported_evaluations.w_o; + auto w_4 = purported_evaluations.w_4; + auto w_4_shift = purported_evaluations.w_4_shift; + auto q_m = purported_evaluations.q_m; + auto q_l = purported_evaluations.q_l; + auto q_r = purported_evaluations.q_r; + auto q_o = purported_evaluations.q_o; + auto q_4 = purported_evaluations.q_4; + auto q_c = purported_evaluations.q_c; + auto q_arith = purported_evaluations.q_arith; static const FF neg_half = FF(-2).invert(); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp index 0189d779f35..84bb0ce60c0 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp @@ -2,7 +2,6 @@ #include #include -#include "barretenberg/honk/flavor/flavor.hpp" #include "../polynomials/univariate.hpp" #include "relation.hpp" @@ -13,7 +12,6 @@ template class UltraArithmeticRelationSecondary { public: // 1 + polynomial degree of this relation static constexpr size_t RELATION_LENGTH = 5; // degree(q_arith^3 * w_l) = 4 - using MULTIVARIATE = UltraArithmetization::POLYNOMIAL; /** * @brief Expression for the Ultra Arithmetic gate. @@ -34,11 +32,11 @@ template class UltraArithmeticRelationSecondary { // OPTIMIZATION?: Karatsuba in general, at least for some degrees? // See https://hackmd.io/xGLuj6biSsCjzQnYN-pEiA?both - auto w_l = UnivariateView(extended_edges[MULTIVARIATE::W_L]); - auto w_4 = UnivariateView(extended_edges[MULTIVARIATE::W_4]); - auto w_l_shift = UnivariateView(extended_edges[MULTIVARIATE::W_1_SHIFT]); - auto q_m = UnivariateView(extended_edges[MULTIVARIATE::Q_M]); - auto q_arith = UnivariateView(extended_edges[MULTIVARIATE::QARITH]); + auto w_l = UnivariateView(extended_edges.w_l); + auto w_4 = UnivariateView(extended_edges.w_4); + auto w_l_shift = UnivariateView(extended_edges.w_l_shift); + auto q_m = UnivariateView(extended_edges.q_m); + auto q_arith = UnivariateView(extended_edges.q_arith); auto tmp = w_l + w_4 - w_l_shift + q_m; tmp *= (q_arith - 2); @@ -52,11 +50,11 @@ template class UltraArithmeticRelationSecondary { const auto& purported_evaluations, const RelationParameters&) const { - auto w_l = purported_evaluations[MULTIVARIATE::W_L]; - auto w_4 = purported_evaluations[MULTIVARIATE::W_4]; - auto w_l_shift = purported_evaluations[MULTIVARIATE::W_1_SHIFT]; - auto q_m = purported_evaluations[MULTIVARIATE::Q_M]; - auto q_arith = purported_evaluations[MULTIVARIATE::QARITH]; + auto w_l = purported_evaluations.w_l; + auto w_4 = purported_evaluations.w_4; + auto w_l_shift = purported_evaluations.w_l_shift; + auto q_m = purported_evaluations.q_m; + auto q_arith = purported_evaluations.q_arith; auto tmp = w_l + w_4 - w_l_shift + q_m; tmp *= (q_arith - 2); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp new file mode 100644 index 00000000000..9e394e2f971 --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/relations/ultra_relation_consistency.test.cpp @@ -0,0 +1,405 @@ +#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation.hpp" +#include "barretenberg/honk/sumcheck/relations/ultra_arithmetic_relation_secondary.hpp" +#include "barretenberg/honk/sumcheck/relations/lookup_grand_product_relation.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" +#include "relation.hpp" +#include "arithmetic_relation.hpp" +#include "grand_product_initialization_relation.hpp" +#include "grand_product_computation_relation.hpp" +#include "../polynomials/univariate.hpp" +#include "../polynomials/barycentric_data.hpp" + +#include "barretenberg/ecc/curves/bn254/fr.hpp" +#include "barretenberg/numeric/random/engine.hpp" + +#include +#include +using namespace proof_system::honk::sumcheck; +/** + * We want to test if all three relations (namely, ArithmeticRelation, GrandProductComputationRelation, + * GrandProductInitializationRelation) provide correct contributions by manually computing their + * contributions with deterministic and random inputs. The relations are supposed to work with + * univariates (edges) of degree one (length 2) and spit out polynomials of corresponding degrees. We have + * MAX_RELATION_LENGTH = 5, meaning the output of a relation can atmost be a degree 5 polynomial. Hence, + * we use a method compute_mock_extended_edges() which starts with degree one input polynomial (two evaluation + points), + * extends them (using barycentric formula) to six evaluation points, and stores them to an array of polynomials. + */ +static const size_t INPUT_UNIVARIATE_LENGTH = 2; + +namespace proof_system::honk_relation_tests { + +class UltraRelationConsistency : public testing::Test { + public: + using Flavor = honk::flavor::Ultra; + using FF = typename Flavor::FF; + using PurportedEvaluations = typename Flavor::PurportedEvaluations; + + // TODO(#390): Move MAX_RELATION_LENGTH into Flavor and simplify this. + template using ExtendedEdges = typename Flavor::template ExtendedEdges; + + // TODO(#225)(Adrian): Accept FULL_RELATION_LENGTH as a template parameter for this function only, so that the test + // can decide to which degree the polynomials must be extended. Possible accept an existing list of "edges" and + // extend them to the degree. + template + static void compute_mock_extended_edges( + ExtendedEdges& extended_edges, + std::array, NUM_POLYNOMIALS>& input_edges) + { + BarycentricData barycentric_2_to_max = + BarycentricData(); + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + extended_edges[i] = barycentric_2_to_max.extend(input_edges[i]); + } + } + + /** + * @brief Returns randomly sampled parameters to feed to the relations. + * + * @return RelationParameters + */ + RelationParameters compute_mock_relation_parameters() + { + return { .beta = FF::random_element(), + .gamma = FF::random_element(), + .public_input_delta = FF::random_element() }; + } + + /** + * @brief Given an array of Univariates, create a new array containing only the i-th evaluations + * of all the univariates. + * + * @note Not really optimized, mainly used for testing that the relations evaluate to the same value when + * evaluated as Univariates, Expressions, or index-by-index + * @todo(Adrian) Maybe this is more helpful as part of a `check_logic` function. + * + * @tparam NUM_UNIVARIATES number of univariates in the input array (deduced from `univariates`) + * @tparam univariate_length number of evaluations (deduced from `univariates`) + * @param univariates array of Univariates + * @param i index of the evaluations we want to take from each univariate + * @return std::array such that result[j] = univariates[j].value_at(i) + */ + template + static PurportedEvaluations transposed_univariate_array_at(ExtendedEdges univariates, size_t i) + { + ASSERT(i < univariate_length); + std::array result; + size_t result_idx = 0; // TODO(#391) zip + for (auto& univariate : univariates) { + result[result_idx] = univariate.value_at(i); + ++result_idx; + } + return result; + }; + + /** + * @brief Compute the evaluation of a `relation` in different ways, comparing it to the provided `expected_evals` + * + * @details Check both `add_full_relation_value_contribution` and `add_edge_contribution` by comparing the result to + * the `expected_evals` computed by the caller. + * Ensures that the relations compute the same result as the expression given in the tests. + * + * @param expected_evals Relation evaluation computed by the caller. + * @param relation being tested + * @param extended_edges + * @param relation_parameters + */ + template + static void validate_evaluations(const Univariate& expected_evals, + const auto relation, + const ExtendedEdges& extended_edges, + const RelationParameters& relation_parameters) + { + + // Compute the expression index-by-index + Univariate expected_evals_index{ 0 }; + for (size_t i = 0; i < FULL_RELATION_LENGTH; ++i) { + // Get an array of the same size as `extended_edges` with only the i-th element of each extended edge. + PurportedEvaluations evals_i = transposed_univariate_array_at(extended_edges, i); + // Evaluate the relation + relation.add_full_relation_value_contribution( + expected_evals_index.value_at(i), evals_i, relation_parameters); + } + EXPECT_EQ(expected_evals, expected_evals_index); + + // Compute the expression using the class, that converts the extended edges to UnivariateView + auto expected_evals_view = Univariate(0); + // The scaling factor is essentially 1 since we are working with degree 1 univariates + relation.add_edge_contribution(expected_evals_view, extended_edges, relation_parameters, 1); + + // Tiny hack to reduce `expected_evals` to be of size `relation.RELATION_LENGTH` + Univariate expected_evals_restricted{ + UnivariateView(expected_evals) + }; + EXPECT_EQ(expected_evals_restricted, expected_evals_view); + }; +}; + +TEST_F(UltraRelationConsistency, UltraArithmeticRelation) +{ + using Flavor = honk::flavor::Ultra; + using FF = typename Flavor::FF; + static constexpr size_t FULL_RELATION_LENGTH = 6; + using ExtendedEdges = typename Flavor::template ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + + const auto relation_parameters = compute_mock_relation_parameters(); + ExtendedEdges extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + compute_mock_extended_edges(extended_edges, input_polynomials); + + auto relation = UltraArithmeticRelation(); + + // Extract the extended edges for manual computation of relation contribution + const auto& w_1 = extended_edges.w_l; + const auto& w_2 = extended_edges.w_r; + const auto& w_3 = extended_edges.w_o; + const auto& w_4 = extended_edges.w_4; + const auto& w_4_shift = extended_edges.w_4_shift; + const auto& q_m = extended_edges.q_m; + const auto& q_l = extended_edges.q_l; + const auto& q_r = extended_edges.q_r; + const auto& q_o = extended_edges.q_o; + const auto& q_4 = extended_edges.q_4; + const auto& q_c = extended_edges.q_c; + const auto& q_arith = extended_edges.q_arith; + + static const FF neg_half = FF(-2).invert(); + + auto expected_evals = (q_arith - 3) * (q_m * w_2 * w_1) * neg_half; + expected_evals += (q_l * w_1) + (q_r * w_2) + (q_o * w_3) + (q_4 * w_4) + q_c; + expected_evals += (q_arith - 1) * w_4_shift; + expected_evals *= q_arith; + + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +TEST_F(UltraRelationConsistency, UltraArithmeticRelationSecondary) +{ + using Flavor = honk::flavor::Ultra; + using FF = typename Flavor::FF; + static constexpr size_t FULL_RELATION_LENGTH = 6; + using ExtendedEdges = typename Flavor::template ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + + const auto relation_parameters = compute_mock_relation_parameters(); + ExtendedEdges extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + compute_mock_extended_edges(extended_edges, input_polynomials); + + auto relation = UltraArithmeticRelationSecondary(); + + // Extract the extended edges for manual computation of relation contribution + const auto& w_1 = extended_edges.w_l; + const auto& w_4 = extended_edges.w_4; + const auto& w_l_shift = extended_edges.w_l_shift; + const auto& q_m = extended_edges.q_m; + const auto& q_arith = extended_edges.q_arith; + + auto expected_evals = (w_1 + w_4 - w_l_shift + q_m); + expected_evals *= (q_arith - 2) * (q_arith - 1) * q_arith; + + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +TEST_F(UltraRelationConsistency, UltraGrandProductInitializationRelation) +{ + using Flavor = honk::flavor::Ultra; + using FF = typename Flavor::FF; + using Flavor = honk::flavor::Ultra; + static constexpr size_t FULL_RELATION_LENGTH = 6; + using ExtendedEdges = typename Flavor::ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + auto relation_parameters = compute_mock_relation_parameters(); + ExtendedEdges extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + compute_mock_extended_edges(extended_edges, input_polynomials); + + auto relation = UltraGrandProductInitializationRelation(); + + // Extract the extended edges for manual computation of relation contribution + const auto& z_perm_shift = extended_edges.z_perm_shift; + const auto& lagrange_last = extended_edges.lagrange_last; + + // Compute the expected result using a simple to read version of the relation expression + auto expected_evals = z_perm_shift * lagrange_last; + + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +TEST_F(UltraRelationConsistency, UltraGrandProductComputationRelation) +{ + using Flavor = honk::flavor::Ultra; + using FF = typename Flavor::FF; + using Flavor = honk::flavor::Ultra; + static constexpr size_t FULL_RELATION_LENGTH = 6; + using ExtendedEdges = typename Flavor::template ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + auto relation_parameters = compute_mock_relation_parameters(); + ExtendedEdges extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + compute_mock_extended_edges(extended_edges, input_polynomials); + + auto relation = UltraGrandProductComputationRelation(); + + const auto& beta = relation_parameters.beta; + const auto& gamma = relation_parameters.gamma; + const auto& public_input_delta = relation_parameters.public_input_delta; + + // Extract the extended edges for manual computation of relation contribution + const auto& w_1 = extended_edges.w_l; + const auto& w_2 = extended_edges.w_r; + const auto& w_3 = extended_edges.w_o; + const auto& w_4 = extended_edges.w_4; + const auto& sigma_1 = extended_edges.sigma_1; + const auto& sigma_2 = extended_edges.sigma_2; + const auto& sigma_3 = extended_edges.sigma_3; + const auto& sigma_4 = extended_edges.sigma_4; + const auto& id_1 = extended_edges.id_1; + const auto& id_2 = extended_edges.id_2; + const auto& id_3 = extended_edges.id_3; + const auto& id_4 = extended_edges.id_4; + const auto& z_perm = extended_edges.z_perm; + const auto& z_perm_shift = extended_edges.z_perm_shift; + const auto& lagrange_first = extended_edges.lagrange_first; + const auto& lagrange_last = extended_edges.lagrange_last; + + // Compute the expected result using a simple to read version of the relation expression + auto expected_evals = (z_perm + lagrange_first) * (w_1 + id_1 * beta + gamma) * (w_2 + id_2 * beta + gamma) * + (w_3 + id_3 * beta + gamma) * (w_4 + id_4 * beta + gamma) - + (z_perm_shift + lagrange_last * public_input_delta) * (w_1 + sigma_1 * beta + gamma) * + (w_2 + sigma_2 * beta + gamma) * (w_3 + sigma_3 * beta + gamma) * + (w_4 + sigma_4 * beta + gamma); + + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +TEST_F(UltraRelationConsistency, LookupGrandProductComputationRelation) +{ + using Flavor = honk::flavor::Ultra; + using FF = typename Flavor::FF; + using Flavor = honk::flavor::Ultra; + static constexpr size_t FULL_RELATION_LENGTH = 6; + using ExtendedEdges = typename Flavor::ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + auto relation_parameters = compute_mock_relation_parameters(); + ExtendedEdges extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + compute_mock_extended_edges(extended_edges, input_polynomials); + + auto relation = LookupGrandProductComputationRelation(); + + const auto eta = relation_parameters.eta; + const auto beta = relation_parameters.beta; + const auto gamma = relation_parameters.gamma; + auto grand_product_delta = relation_parameters.lookup_grand_product_delta; + + // Extract the extended edges for manual computation of relation contribution + auto one_plus_beta = FF::one() + beta; + auto gamma_by_one_plus_beta = gamma * one_plus_beta; + auto eta_sqr = eta * eta; + auto eta_cube = eta_sqr * eta; + + const auto& w_1 = extended_edges.w_l; + const auto& w_2 = extended_edges.w_r; + const auto& w_3 = extended_edges.w_o; + + const auto& w_1_shift = extended_edges.w_l_shift; + const auto& w_2_shift = extended_edges.w_r_shift; + const auto& w_3_shift = extended_edges.w_o_shift; + + const auto& table_1 = extended_edges.table_1; + const auto& table_2 = extended_edges.table_2; + const auto& table_3 = extended_edges.table_3; + const auto& table_4 = extended_edges.table_4; + + const auto& table_1_shift = extended_edges.table_1_shift; + const auto& table_2_shift = extended_edges.table_2_shift; + const auto& table_3_shift = extended_edges.table_3_shift; + const auto& table_4_shift = extended_edges.table_4_shift; + + const auto& s_accum = extended_edges.sorted_accum; + const auto& s_accum_shift = extended_edges.sorted_accum_shift; + const auto& z_lookup = extended_edges.z_lookup; + const auto& z_lookup_shift = extended_edges.z_lookup_shift; + + const auto& table_index = extended_edges.q_o; + const auto& column_1_step_size = extended_edges.q_r; + const auto& column_2_step_size = extended_edges.q_m; + const auto& column_3_step_size = extended_edges.q_c; + const auto& q_lookup = extended_edges.q_lookup; + + const auto& lagrange_first = extended_edges.lagrange_first; + const auto& lagrange_last = extended_edges.lagrange_last; + + auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + + (w_3 + column_3_step_size * w_3_shift) * eta_sqr + table_index * eta_cube; + + auto table_accum = table_1 + table_2 * eta + table_3 * eta_sqr + table_4 * eta_cube; + auto table_accum_shift = table_1_shift + table_2_shift * eta + table_3_shift * eta_sqr + table_4_shift * eta_cube; + + // Compute the expected result using a simple to read version of the relation expression + auto expected_evals = (z_lookup + lagrange_first) * (q_lookup * wire_accum + gamma) * + (table_accum + table_accum_shift * beta + gamma_by_one_plus_beta) * one_plus_beta; + expected_evals -= (z_lookup_shift + lagrange_last * grand_product_delta) * + (s_accum + s_accum_shift * beta + gamma_by_one_plus_beta); + + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +TEST_F(UltraRelationConsistency, LookupGrandProductInitializationRelation) +{ + using Flavor = honk::flavor::Ultra; + using FF = typename Flavor::FF; + using Flavor = honk::flavor::Ultra; + static constexpr size_t FULL_RELATION_LENGTH = 6; + using ExtendedEdges = typename Flavor::ExtendedEdges; + static const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; + auto relation_parameters = compute_mock_relation_parameters(); + ExtendedEdges extended_edges; + std::array, NUM_POLYNOMIALS> input_polynomials; + + // input_univariates are random polynomials of degree one + for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { + input_polynomials[i] = Univariate({ FF::random_element(), FF::random_element() }); + } + compute_mock_extended_edges(extended_edges, input_polynomials); + + auto relation = LookupGrandProductInitializationRelation(); + + // Extract the extended edges for manual computation of relation contribution + const auto& z_lookup_shift = extended_edges.z_lookup_shift; + const auto& lagrange_last = extended_edges.lagrange_last; + + // Compute the expected result using a simple to read version of the relation expression + auto expected_evals = z_lookup_shift * lagrange_last; + + validate_evaluations(expected_evals, relation, extended_edges, relation_parameters); +}; + +} // namespace proof_system::honk_relation_tests diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp index 7107dd9526a..8968ee12609 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp @@ -7,7 +7,6 @@ #include "barretenberg/common/throw_or_abort.hpp" #include "sumcheck_round.hpp" #include "polynomials/univariate.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" #include #include #include @@ -19,17 +18,20 @@ namespace proof_system::honk::sumcheck { -template class... Relations> class Sumcheck { +template class... Relations> class Sumcheck { public: + using FF = typename Flavor::FF; + using FoldedPolynomials = typename Flavor::FoldedPolynomials; + using PurportedEvaluations = typename Flavor::PurportedEvaluations; + static constexpr size_t MAX_RELATION_LENGTH = std::max({ Relations::RELATION_LENGTH... }); - static constexpr size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; + static constexpr size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; - std::array purported_evaluations; Transcript& transcript; const size_t multivariate_n; const size_t multivariate_d; - SumcheckRound round; + SumcheckRound round; /** * @@ -60,7 +62,7 @@ template class... Relations> cl * NOTE: With ~40 columns, prob only want to allocate 256 EdgeGroup's at once to keep stack under 1MB? * TODO(#224)(Cody): might want to just do C-style multidimensional array? for guaranteed adjacency? */ - std::array, NUM_POLYNOMIALS> folded_polynomials; + FoldedPolynomials folded_polynomials; // prover instantiates sumcheck with circuit size and a prover transcript Sumcheck(size_t multivariate_n, ProverTranscript& transcript) @@ -87,7 +89,7 @@ template class... Relations> cl * * @details */ - SumcheckOutput execute_prover( + SumcheckOutput execute_prover( auto full_polynomials, const RelationParameters& relation_parameters) // pass by value, not by reference { auto [alpha, zeta] = transcript.get_challenges("Sumcheck:alpha", "Sumcheck:zeta"); @@ -121,11 +123,13 @@ template class... Relations> cl } // Final round: Extract multivariate evaluations from folded_polynomials and add to transcript - std::array multivariate_evaluations; - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - multivariate_evaluations[i] = folded_polynomials[i][0]; + PurportedEvaluations multivariate_evaluations; + size_t evaluation_idx = 0; + for (auto& polynomial : folded_polynomials) { // TODO(#391) zip + multivariate_evaluations[evaluation_idx] = polynomial[0]; + ++evaluation_idx; } - transcript.send_to_verifier("Sumcheck:evaluations", multivariate_evaluations); + transcript.send_to_verifier("Sumcheck:evaluations", multivariate_evaluations._data); return { multivariate_challenge, multivariate_evaluations }; }; @@ -137,7 +141,7 @@ template class... Relations> cl * * @details If verification fails, returns std::nullopt, otherwise returns SumcheckOutput */ - std::optional> execute_verifier(const RelationParameters& relation_parameters) + std::optional> execute_verifier(const RelationParameters& relation_parameters) { bool verified(true); @@ -174,17 +178,17 @@ template class... Relations> cl } // Final round - auto purported_evaluations = + PurportedEvaluations purported_evaluations = transcript.template receive_from_prover>("Sumcheck:evaluations"); FF full_honk_relation_purported_value = round.compute_full_honk_relation_purported_value( - purported_evaluations, relation_parameters, pow_univariate, alpha); + purported_evaluations._data, relation_parameters, pow_univariate, alpha); verified = verified && (full_honk_relation_purported_value == round.target_total_sum); if (!verified) { return std::nullopt; } - return SumcheckOutput{ multivariate_challenge, purported_evaluations }; + return SumcheckOutput{ multivariate_challenge, purported_evaluations }; }; // TODO(#224)(Cody): Rename. fold is not descriptive, and it's already in use in the Gemini context. diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp index 95316ca5cbe..bae05061996 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp @@ -1,6 +1,6 @@ #include "sumcheck.hpp" #include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/honk/flavor/flavor.hpp" +#include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/transcript/transcript_wrappers.hpp" #include "relations/arithmetic_relation.hpp" #include "relations/grand_product_computation_relation.hpp" @@ -22,55 +22,52 @@ using namespace proof_system::honk; using namespace proof_system::honk::sumcheck; -using FF = barretenberg::fr; -const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; -using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; +using Flavor = honk::flavor::Standard; // TODO(Cody): Generalize this test. +using FF = typename Flavor::FF; +using ProverPolynomials = typename Flavor::ProverPolynomials; +const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; namespace test_sumcheck_round { -/** - * @brief Place polynomials into full_polynomials in the order determined by the StandardArithmetization enum. - * - */ template -std::array, NUM_POLYNOMIALS> construct_full_polynomials(std::array& w_l, - std::array& w_r, - std::array& w_o, - std::array& z_perm, - std::array& z_perm_shift, - std::array& q_m, - std::array& q_l, - std::array& q_r, - std::array& q_o, - std::array& q_c, - std::array& sigma_1, - std::array& sigma_2, - std::array& sigma_3, - std::array& id_1, - std::array& id_2, - std::array& id_3, - std::array& lagrange_first, - std::array& lagrange_last) +ProverPolynomials construct_full_polynomials(std::array& w_l, + std::array& w_r, + std::array& w_o, + std::array& z_perm, + std::array& z_perm_shift, + std::array& q_m, + std::array& q_l, + std::array& q_r, + std::array& q_o, + std::array& q_c, + std::array& sigma_1, + std::array& sigma_2, + std::array& sigma_3, + std::array& id_1, + std::array& id_2, + std::array& id_3, + std::array& lagrange_first, + std::array& lagrange_last) { - std::array, NUM_POLYNOMIALS> full_polynomials; - full_polynomials[POLYNOMIAL::W_L] = w_l; - full_polynomials[POLYNOMIAL::W_R] = w_r; - full_polynomials[POLYNOMIAL::W_O] = w_o; - full_polynomials[POLYNOMIAL::Z_PERM] = z_perm; - full_polynomials[POLYNOMIAL::Z_PERM_SHIFT] = z_perm_shift; - full_polynomials[POLYNOMIAL::Q_M] = q_m; - full_polynomials[POLYNOMIAL::Q_L] = q_l; - full_polynomials[POLYNOMIAL::Q_R] = q_r; - full_polynomials[POLYNOMIAL::Q_O] = q_o; - full_polynomials[POLYNOMIAL::Q_C] = q_c; - full_polynomials[POLYNOMIAL::SIGMA_1] = sigma_1; - full_polynomials[POLYNOMIAL::SIGMA_2] = sigma_2; - full_polynomials[POLYNOMIAL::SIGMA_3] = sigma_3; - full_polynomials[POLYNOMIAL::ID_1] = id_1; - full_polynomials[POLYNOMIAL::ID_2] = id_2; - full_polynomials[POLYNOMIAL::ID_3] = id_3; - full_polynomials[POLYNOMIAL::LAGRANGE_FIRST] = lagrange_first; - full_polynomials[POLYNOMIAL::LAGRANGE_LAST] = lagrange_last; + ProverPolynomials full_polynomials; + full_polynomials.w_l = w_l; + full_polynomials.w_r = w_r; + full_polynomials.w_o = w_o; + full_polynomials.z_perm = z_perm; + full_polynomials.z_perm_shift = z_perm_shift; + full_polynomials.q_m = q_m; + full_polynomials.q_l = q_l; + full_polynomials.q_r = q_r; + full_polynomials.q_o = q_o; + full_polynomials.q_c = q_c; + full_polynomials.sigma_1 = sigma_1; + full_polynomials.sigma_2 = sigma_2; + full_polynomials.sigma_3 = sigma_3; + full_polynomials.id_1 = id_1; + full_polynomials.id_2 = id_2; + full_polynomials.id_3 = id_3; + full_polynomials.lagrange_first = lagrange_first; + full_polynomials.lagrange_last = lagrange_last; return full_polynomials; } @@ -142,7 +139,7 @@ TEST(Sumcheck, PolynomialNormalization) auto transcript = ProverTranscript::init_empty(); - auto sumcheck = Sumcheck, ArithmeticRelation, GrandProductComputationRelation, @@ -242,7 +239,7 @@ TEST(Sumcheck, Prover) auto transcript = ProverTranscript::init_empty(); - auto sumcheck = Sumcheck, ArithmeticRelation, GrandProductComputationRelation, @@ -323,7 +320,7 @@ TEST(Sumcheck, ProverAndVerifier) auto prover_transcript = ProverTranscript::init_empty(); - auto sumcheck_prover = Sumcheck, ArithmeticRelation, GrandProductComputationRelation, @@ -333,7 +330,7 @@ TEST(Sumcheck, ProverAndVerifier) auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); - auto sumcheck_verifier = Sumcheck, ArithmeticRelation, GrandProductComputationRelation, @@ -405,7 +402,7 @@ TEST(Sumcheck, ProverAndVerifierLonger) auto prover_transcript = ProverTranscript::init_empty(); - auto sumcheck_prover = Sumcheck, ArithmeticRelation, GrandProductComputationRelation, @@ -415,7 +412,7 @@ TEST(Sumcheck, ProverAndVerifierLonger) auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); - auto sumcheck_verifier = Sumcheck, ArithmeticRelation, GrandProductComputationRelation, diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_output.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_output.hpp index 52383cc80b1..cfe3dfb09bd 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_output.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_output.hpp @@ -8,12 +8,38 @@ namespace proof_system::honk::sumcheck { * @brief Contains the multi-linear evaluations of the polynomials at the challenge point 'u'. * These are computed by the prover and need to be checked using a multi-linear PCS like Gemini. */ -template struct SumcheckOutput { +template struct SumcheckOutput { + using FF = typename Flavor::FF; + using PurportedEvaluations = typename Flavor::PurportedEvaluations; // u = (u_0, ..., u_{d-1}) std::vector challenge_point; // Evaluations in `u` of the polynomials used in Sumcheck - std::array evaluations; + PurportedEvaluations purported_evaluations; - bool operator==(const SumcheckOutput& other) const = default; + SumcheckOutput() + : purported_evaluations(std::array()){}; + + SumcheckOutput(const std::vector& _challenge_point, const PurportedEvaluations& _purported_evaluations) + : challenge_point(_challenge_point) + , purported_evaluations(_purported_evaluations){}; + + SumcheckOutput& operator=(SumcheckOutput&& other) + { + challenge_point = other.challenge_point; + purported_evaluations = other.purported_evaluations; + return *this; + }; + + SumcheckOutput(const SumcheckOutput& other) + : challenge_point(other.challenge_point) + , purported_evaluations(other.purported_evaluations){}; + + bool operator==(const SumcheckOutput& other) const + { + bool result{ false }; + result = challenge_point == other.challenge_point; + result = purported_evaluations._data == other.purported_evaluations._data; + return result; + }; }; } // namespace proof_system::honk::sumcheck diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp index 8a10169b8aa..0aea53047fa 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.hpp @@ -7,6 +7,7 @@ #include "polynomials/univariate.hpp" #include "polynomials/pow.hpp" #include "relations/relation.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" // WORKTOO namespace proof_system::honk::sumcheck { @@ -48,11 +49,18 @@ namespace proof_system::honk::sumcheck { Note: This class uses recursive function calls with template parameters. This is a common trick that is used to force the compiler to unroll loops. The idea is that a function that is only called once will always be inlined, and since template functions always create different functions, this is guaranteed. + + @todo TODO(#390): Template only on Flavor? Is it useful to have these decoupled? */ -template class... Relations> class SumcheckRound { +template class... Relations> class SumcheckRound { public: + using FF = typename Flavor::FF; + template + using ExtendedEdges = typename Flavor::template ExtendedEdges; + using PurportedEvaluations = typename Flavor::PurportedEvaluations; + bool round_failed = false; size_t round_size; // a power of 2 @@ -65,8 +73,8 @@ template class... Relation // TODO(#224)(Cody): this barycentric stuff should be more built-in? std::tuple::RELATION_LENGTH, MAX_RELATION_LENGTH>...> barycentric_utils; std::tuple::RELATION_LENGTH>...> univariate_accumulators; - std::array evaluations; - std::array, num_multivariates> extended_edges; + std::array relation_evaluations; + ExtendedEdges extended_edges; std::array, NUM_RELATIONS> extended_univariates; // TODO(#224)(Cody): this should go away and we should use constexpr method to extend @@ -86,7 +94,7 @@ template class... Relation { // FF's default constructor may not initialize to zero (e.g., barretenberg::fr), hence we can't rely on // aggregate initialization of the evaluations array. - std::fill(evaluations.begin(), evaluations.end(), FF(0)); + std::fill(relation_evaluations.begin(), relation_evaluations.end(), FF(0)); }; /** @@ -141,13 +149,16 @@ template class... Relation * entry of relation_evals. * * @details Should only be called externally with relation_idx equal to 0. + * In practice, multivariates is one of ProverPolynomials or FoldedPolynomials. * */ void extend_edges(auto& multivariates, size_t edge_idx) { - for (size_t idx = 0; idx < num_multivariates; idx++) { - auto edge = Univariate({ multivariates[idx][edge_idx], multivariates[idx][edge_idx + 1] }); - extended_edges[idx] = barycentric_2_to_max.extend(edge); + size_t univariate_idx = 0; // TODO(#391) zip + for (auto& poly : multivariates) { + auto edge = Univariate({ poly[edge_idx], poly[edge_idx + 1] }); + extended_edges[univariate_idx] = barycentric_2_to_max.extend(edge); + ++univariate_idx; } } @@ -207,8 +218,7 @@ template class... Relation * together, with appropriate scaling factors, produces the expected value of the full Honk relation. This value is * checked against the final value of the target total sum, defined as sigma_d. */ - // TODO(#224)(Cody): Input should be an array? - FF compute_full_honk_relation_purported_value(std::span purported_evaluations, + FF compute_full_honk_relation_purported_value(PurportedEvaluations purported_evaluations, const RelationParameters& relation_parameters, const PowUnivariate& pow_univariate, const FF alpha) @@ -218,7 +228,7 @@ template class... Relation // IMPROVEMENT(Cody): Reuse functions from univariate_accumulators batching? FF running_challenge = 1; FF output = 0; - for (auto& evals : evaluations) { + for (auto& evals : relation_evaluations) { output += evals * running_challenge; running_challenge *= alpha; } @@ -306,11 +316,11 @@ template class... Relation */ template // TODO(#224)(Cody): Input should be an array? - void accumulate_relation_evaluations(std::span purported_evaluations, + void accumulate_relation_evaluations(PurportedEvaluations purported_evaluations, const RelationParameters& relation_parameters) { std::get(relations).add_full_relation_value_contribution( - evaluations[relation_idx], purported_evaluations, relation_parameters); + relation_evaluations[relation_idx], purported_evaluations, relation_parameters); // Repeat for the next relation. if constexpr (relation_idx + 1 < NUM_RELATIONS) { diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp index 97b8ab4c470..97fefa6a48c 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp @@ -1,4 +1,3 @@ -#include "barretenberg/honk/flavor/flavor.hpp" #include "sumcheck_round.hpp" #include "relations/arithmetic_relation.hpp" #include "relations/grand_product_computation_relation.hpp" @@ -6,6 +5,7 @@ #include "polynomials/univariate.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/numeric/random/engine.hpp" +#include "barretenberg/honk/flavor/standard.hpp" #include @@ -21,58 +21,56 @@ using namespace proof_system::honk; using namespace proof_system::honk::sumcheck; + +using Flavor = flavor::Standard; +using FF = typename Flavor::FF; +using ProverPolynomials = typename Flavor::ProverPolynomials; +using PurportedEvaluations = typename Flavor::PurportedEvaluations; + +const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; const size_t max_relation_length = 5; const size_t input_polynomial_length = 2; -using FF = barretenberg::fr; -const size_t NUM_POLYNOMIALS = proof_system::honk::StandardArithmetization::NUM_POLYNOMIALS; -using POLYNOMIAL = proof_system::honk::StandardArithmetization::POLYNOMIAL; namespace test_sumcheck_round { -/** - * @brief Place polynomials into full_polynomials in the order determined by the StandardArithmetization enum. - * - */ template -std::array, NUM_POLYNOMIALS> construct_full_polynomials(std::array& w_l, - std::array& w_r, - std::array& w_o, - std::array& z_perm, - std::array& z_perm_shift, - std::array& q_m, - std::array& q_l, - std::array& q_r, - std::array& q_o, - std::array& q_c, - std::array& sigma_1, - std::array& sigma_2, - std::array& sigma_3, - std::array& id_1, - std::array& id_2, - std::array& id_3, - std::array& lagrange_first, - std::array& lagrange_last) +void construct_full_polynomials(ProverPolynomials& full_polynomials, + std::array& w_l, + std::array& w_r, + std::array& w_o, + std::array& z_perm, + std::array& z_perm_shift, + std::array& q_m, + std::array& q_l, + std::array& q_r, + std::array& q_o, + std::array& q_c, + std::array& sigma_1, + std::array& sigma_2, + std::array& sigma_3, + std::array& id_1, + std::array& id_2, + std::array& id_3, + std::array& lagrange_first, + std::array& lagrange_last) { - std::array, NUM_POLYNOMIALS> full_polynomials; - full_polynomials[POLYNOMIAL::W_L] = w_l; - full_polynomials[POLYNOMIAL::W_R] = w_r; - full_polynomials[POLYNOMIAL::W_O] = w_o; - full_polynomials[POLYNOMIAL::Z_PERM] = z_perm; - full_polynomials[POLYNOMIAL::Z_PERM_SHIFT] = z_perm_shift; - full_polynomials[POLYNOMIAL::Q_M] = q_m; - full_polynomials[POLYNOMIAL::Q_L] = q_l; - full_polynomials[POLYNOMIAL::Q_R] = q_r; - full_polynomials[POLYNOMIAL::Q_O] = q_o; - full_polynomials[POLYNOMIAL::Q_C] = q_c; - full_polynomials[POLYNOMIAL::SIGMA_1] = sigma_1; - full_polynomials[POLYNOMIAL::SIGMA_2] = sigma_2; - full_polynomials[POLYNOMIAL::SIGMA_3] = sigma_3; - full_polynomials[POLYNOMIAL::ID_1] = id_1; - full_polynomials[POLYNOMIAL::ID_2] = id_2; - full_polynomials[POLYNOMIAL::ID_3] = id_3; - full_polynomials[POLYNOMIAL::LAGRANGE_FIRST] = lagrange_first; - full_polynomials[POLYNOMIAL::LAGRANGE_LAST] = lagrange_last; - - return full_polynomials; + full_polynomials.w_l = w_l; + full_polynomials.w_r = w_r; + full_polynomials.w_o = w_o; + full_polynomials.z_perm = z_perm; + full_polynomials.z_perm_shift = z_perm_shift; + full_polynomials.q_m = q_m; + full_polynomials.q_l = q_l; + full_polynomials.q_r = q_r; + full_polynomials.q_o = q_o; + full_polynomials.q_c = q_c; + full_polynomials.sigma_1 = sigma_1; + full_polynomials.sigma_2 = sigma_2; + full_polynomials.sigma_3 = sigma_3; + full_polynomials.id_1 = id_1; + full_polynomials.id_2 = id_2; + full_polynomials.id_3 = id_3; + full_polynomials.lagrange_first = lagrange_first; + full_polynomials.lagrange_last = lagrange_last; } // The below two methods are used in the test ComputeUnivariateProver @@ -85,11 +83,9 @@ static Univariate compute_round_univariate( auto relations = std::tuple( ArithmeticRelation(), GrandProductComputationRelation(), GrandProductInitializationRelation()); // Improvement(Cody): This is ugly? Maye supply some/all of this data through "flavor" class? - auto round = SumcheckRound(round_size, relations); + auto round = + SumcheckRound( + round_size, relations); auto w_l = input_polynomials[0]; auto w_r = input_polynomials[1]; auto w_o = input_polynomials[2]; @@ -109,24 +105,26 @@ static Univariate compute_round_univariate( auto lagrange_first = input_polynomials[16]; auto lagrange_last = input_polynomials[17]; - auto full_polynomials = construct_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_first, - lagrange_last); + ProverPolynomials full_polynomials; + construct_full_polynomials(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_first, + lagrange_last); PowUnivariate pow_zeta(1); Univariate round_univariate = round.compute_univariate(full_polynomials, relation_parameters, pow_zeta, alpha); @@ -189,33 +187,30 @@ static FF compute_full_purported_value(std::array& input_va const RelationParameters& relation_parameters, const FF alpha) { - std::vector purported_evaluations; - purported_evaluations.resize(NUM_POLYNOMIALS); - purported_evaluations[POLYNOMIAL::W_L] = input_values[0]; - purported_evaluations[POLYNOMIAL::W_R] = input_values[1]; - purported_evaluations[POLYNOMIAL::W_O] = input_values[2]; - purported_evaluations[POLYNOMIAL::Z_PERM] = input_values[3]; - purported_evaluations[POLYNOMIAL::Z_PERM_SHIFT] = input_values[4]; - purported_evaluations[POLYNOMIAL::Q_M] = input_values[5]; - purported_evaluations[POLYNOMIAL::Q_L] = input_values[6]; - purported_evaluations[POLYNOMIAL::Q_R] = input_values[7]; - purported_evaluations[POLYNOMIAL::Q_O] = input_values[8]; - purported_evaluations[POLYNOMIAL::Q_C] = input_values[9]; - purported_evaluations[POLYNOMIAL::SIGMA_1] = input_values[10]; - purported_evaluations[POLYNOMIAL::SIGMA_2] = input_values[11]; - purported_evaluations[POLYNOMIAL::SIGMA_3] = input_values[12]; - purported_evaluations[POLYNOMIAL::ID_1] = input_values[13]; - purported_evaluations[POLYNOMIAL::ID_2] = input_values[14]; - purported_evaluations[POLYNOMIAL::ID_3] = input_values[15]; - purported_evaluations[POLYNOMIAL::LAGRANGE_FIRST] = input_values[16]; - purported_evaluations[POLYNOMIAL::LAGRANGE_LAST] = input_values[17]; + PurportedEvaluations purported_evaluations; + purported_evaluations.w_l = input_values[0]; + purported_evaluations.w_r = input_values[1]; + purported_evaluations.w_o = input_values[2]; + purported_evaluations.z_perm = input_values[3]; + purported_evaluations.z_perm_shift = input_values[4]; + purported_evaluations.q_m = input_values[5]; + purported_evaluations.q_l = input_values[6]; + purported_evaluations.q_r = input_values[7]; + purported_evaluations.q_o = input_values[8]; + purported_evaluations.q_c = input_values[9]; + purported_evaluations.sigma_1 = input_values[10]; + purported_evaluations.sigma_2 = input_values[11]; + purported_evaluations.sigma_3 = input_values[12]; + purported_evaluations.id_1 = input_values[13]; + purported_evaluations.id_2 = input_values[14]; + purported_evaluations.id_3 = input_values[15]; + purported_evaluations.lagrange_first = input_values[16]; + purported_evaluations.lagrange_last = input_values[17]; auto relations = std::tuple( ArithmeticRelation(), GrandProductComputationRelation(), GrandProductInitializationRelation()); - auto round = SumcheckRound(relations); + auto round = + SumcheckRound( + relations); PowUnivariate pow_univariate(1); FF full_purported_value = round.compute_full_honk_relation_purported_value( purported_evaluations, relation_parameters, pow_univariate, alpha); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp index ff859806b29..fec507a6422 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp @@ -119,8 +119,6 @@ template class BaseTranscript { */ void consume_prover_element_bytes(const std::string& label, std::span element_bytes) { - (void)label; - // Add an entry to the current round of the manifest manifest.add_entry(round_number, label, element_bytes.size()); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp index 1e2de3d9d9d..b0d46c74a38 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp @@ -3,6 +3,7 @@ #include "barretenberg/honk/composer/standard_honk_composer.hpp" #include "barretenberg/honk/sumcheck/polynomials/univariate.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" +#include "barretenberg/honk/flavor/standard.hpp" #include #include #include @@ -31,7 +32,7 @@ template class TranscriptTest : public testing::Test { size_t size_FF = sizeof(FF); size_t size_G = 2 * size_FF; size_t size_uni = max_relation_length * size_FF; - size_t size_evals = StandardArithmetization::NUM_POLYNOMIALS * size_FF; + size_t size_evals = flavor::Standard::NUM_ALL_ENTITIES * size_FF; size_t round = 0; manifest_expected.add_entry(round, "circuit_size", 4); @@ -90,7 +91,6 @@ TYPED_TEST_SUITE(TranscriptTest, FieldTypes); /** * @brief Ensure consistency between the manifest hard coded in this testing suite and the one generated by the * standard honk prover over the course of proof construction. - * */ TYPED_TEST(TranscriptTest, ProverManifestConsistency) { @@ -111,7 +111,6 @@ TYPED_TEST(TranscriptTest, ProverManifestConsistency) // Note: a manifest can be printed using manifest.print() for (size_t round = 0; round < manifest_expected.size(); ++round) { ASSERT_EQ(prover_manifest[round], manifest_expected[round]) << "Prover manifest discrepency in round " << round; - ; } } diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/composer_base.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/composer_base.hpp index 6c93da04b14..a3e57bc383e 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/composer_base.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/composer_base.hpp @@ -111,7 +111,7 @@ class ComposerBase { virtual void print_num_gates() const { std::cout << num_gates << std::endl; } virtual size_t get_num_variables() const { return variables.size(); } virtual std::shared_ptr compute_proving_key_base(const ComposerType type = STANDARD, - const size_t minimum_ciricut_size = 0, + const size_t minimum_circuit_size = 0, const size_t num_reserved_gates = NUM_RESERVED_GATES); // This needs to be static as it may be used only to compute the selector commitments. static std::shared_ptr compute_verification_key_base( diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.cpp index 4ab16d74341..54b11e71db5 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.cpp @@ -11,7 +11,7 @@ namespace proof_system::plonk { /** * @brief Retrieve lagrange forms of selector polynomials and compute monomial and coset-monomial forms and put into - * cache + * cache. * * @param key Pointer to the proving key * @param selector_properties Names of selectors diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.hpp index 927174cc0fc..c704608a3ac 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.hpp @@ -5,14 +5,15 @@ namespace proof_system::plonk { struct SelectorProperties { std::string name; - bool requires_lagrange_base_polynomial = false; // does the prover need the raw lagrange-base selector values? + // TODO: does the prover need the raw lagrange-base selector values? + bool requires_lagrange_base_polynomial = false; }; /** * @brief Retrieve lagrange forms of selector polynomials and compute monomial and coset-monomial forms and put into * cache * - * @param key Pointer to the proving key + * @param key Pointer to the proving key TODO(#293) * @param selector_properties Names of selectors */ void compute_monomial_and_coset_selector_forms(plonk::proving_key* key, diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/standard_plonk_composer_helper.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/standard_plonk_composer_helper.cpp index 601de58dacb..dabf5e4bc1b 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/standard_plonk_composer_helper.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/standard_plonk_composer_helper.cpp @@ -24,16 +24,15 @@ namespace proof_system::plonk { * * @tparam Program settings needed to establish if w_4 is being used. * */ -template -void StandardPlonkComposerHelper::compute_witness(const CircuitConstructor& circuit_constructor, - const size_t minimum_circuit_size) +void StandardPlonkComposerHelper::compute_witness(const CircuitConstructor& circuit_constructor, + const size_t minimum_circuit_size) { if (computed_witness) { return; } auto wire_polynomial_evaluations = - compute_witness_base(circuit_constructor, minimum_circuit_size, NUM_RANDOMIZED_GATES); + construct_wire_polynomials_base(circuit_constructor, minimum_circuit_size, NUM_RANDOMIZED_GATES); for (size_t j = 0; j < program_width; ++j) { std::string index = std::to_string(j + 1); @@ -54,8 +53,7 @@ void StandardPlonkComposerHelper::compute_witness(const Circ * * @return Pointer to the initialized proving key updated with selector polynomials. * */ -template -std::shared_ptr StandardPlonkComposerHelper::compute_proving_key( +std::shared_ptr StandardPlonkComposerHelper::compute_proving_key( const CircuitConstructor& circuit_constructor) { if (circuit_proving_key) { @@ -64,19 +62,18 @@ std::shared_ptr StandardPlonkComposerHelper( circuit_constructor, crs_factory_.get(), minimum_circuit_size, num_randomized_gates, ComposerType::STANDARD); // Compute lagrange selectors - construct_lagrange_selector_forms(circuit_constructor, circuit_proving_key.get()); + construct_selector_polynomials(circuit_constructor, circuit_proving_key.get()); // Make all selectors nonzero - enforce_nonzero_polynomial_selectors(circuit_constructor, circuit_proving_key.get()); + enforce_nonzero_selector_polynomials(circuit_constructor, circuit_proving_key.get()); // Compute selectors in monomial form compute_monomial_and_coset_selector_forms(circuit_proving_key.get(), standard_selector_properties()); // Compute sigma polynomials (we should update that late) - compute_standard_plonk_sigma_permutations(circuit_constructor, - circuit_proving_key.get()); + compute_standard_plonk_sigma_permutations(circuit_constructor, circuit_proving_key.get()); circuit_proving_key->recursive_proof_public_input_indices = std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); @@ -90,8 +87,7 @@ std::shared_ptr StandardPlonkComposerHelper -std::shared_ptr StandardPlonkComposerHelper::compute_verification_key( +std::shared_ptr StandardPlonkComposerHelper::compute_verification_key( const CircuitConstructor& circuit_constructor) { if (circuit_verification_key) { @@ -117,10 +113,7 @@ std::shared_ptr StandardPlonkComposerHelper -plonk::Verifier StandardPlonkComposerHelper::create_verifier( - const CircuitConstructor& circuit_constructor) +plonk::Verifier StandardPlonkComposerHelper::create_verifier(const CircuitConstructor& circuit_constructor) { auto verification_key = compute_verification_key(circuit_constructor); @@ -143,9 +136,7 @@ plonk::Verifier StandardPlonkComposerHelper::create_verifier * * @return Initialized prover. * */ -template -plonk::Prover StandardPlonkComposerHelper::create_prover( - const CircuitConstructor& circuit_constructor) +plonk::Prover StandardPlonkComposerHelper::create_prover(const CircuitConstructor& circuit_constructor) { // Compute q_l, etc. and sigma polynomials. compute_proving_key(circuit_constructor); @@ -172,5 +163,4 @@ plonk::Prover StandardPlonkComposerHelper::create_prover( return output_state; } -template class StandardPlonkComposerHelper; } // namespace proof_system::plonk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/standard_plonk_composer_helper.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/standard_plonk_composer_helper.hpp index 32085fcb57e..3c54be288cd 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/standard_plonk_composer_helper.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/standard_plonk_composer_helper.hpp @@ -1,5 +1,6 @@ #pragma once +#include "barretenberg/plonk/flavor/flavor.hpp" #include "barretenberg/srs/reference_string/file_reference_string.hpp" #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/plonk/proof_system/prover/prover.hpp" @@ -12,10 +13,10 @@ #include namespace proof_system::plonk { -// TODO(Kesha): change initializations to specify this parameter -// Cody: What does this mean? -template class StandardPlonkComposerHelper { +class StandardPlonkComposerHelper { public: + using Flavor = plonk::flavor::Standard; + using CircuitConstructor = StandardCircuitConstructor; static constexpr size_t NUM_RANDOMIZED_GATES = 2; // equal to the number of multilinear evaluations leaked static constexpr size_t program_width = CircuitConstructor::program_width; std::shared_ptr circuit_proving_key; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/turbo_plonk_composer_helper.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/turbo_plonk_composer_helper.cpp index c24524a9282..c367d9ccd1f 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/turbo_plonk_composer_helper.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/turbo_plonk_composer_helper.cpp @@ -29,8 +29,7 @@ namespace proof_system::plonk { * * @return Pointer to the initialized proving key updated with selector polynomials. * */ -template -std::shared_ptr TurboPlonkComposerHelper::compute_proving_key( +std::shared_ptr TurboPlonkComposerHelper::compute_proving_key( const CircuitConstructor& circuit_constructor) { if (circuit_proving_key) { @@ -39,19 +38,18 @@ std::shared_ptr TurboPlonkComposerHelper const size_t minimum_circuit_size = 0; const size_t num_randomized_gates = NUM_RANDOMIZED_GATES; // Initialize circuit_proving_key - // TODO(#229)(Kesha): replace composer types. - circuit_proving_key = initialize_proving_key( + // TODO(#392)(Kesha): replace composer types. + circuit_proving_key = initialize_proving_key( circuit_constructor, crs_factory_.get(), minimum_circuit_size, num_randomized_gates, ComposerType::TURBO); - construct_lagrange_selector_forms(circuit_constructor, circuit_proving_key.get()); + construct_selector_polynomials(circuit_constructor, circuit_proving_key.get()); - enforce_nonzero_polynomial_selectors(circuit_constructor, circuit_proving_key.get()); + enforce_nonzero_selector_polynomials(circuit_constructor, circuit_proving_key.get()); compute_monomial_and_coset_selector_forms(circuit_proving_key.get(), turbo_selector_properties()); // Compute sigma polynomials (TODO(kesha): we should update that late) - compute_standard_plonk_sigma_permutations(circuit_constructor, - circuit_proving_key.get()); + compute_standard_plonk_sigma_permutations(circuit_constructor, circuit_proving_key.get()); circuit_proving_key->recursive_proof_public_input_indices = std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); circuit_proving_key->contains_recursive_proof = contains_recursive_proof; @@ -63,8 +61,7 @@ std::shared_ptr TurboPlonkComposerHelper * * @return Pointer to created circuit verification key. * */ -template -std::shared_ptr TurboPlonkComposerHelper::compute_verification_key( +std::shared_ptr TurboPlonkComposerHelper::compute_verification_key( const CircuitConstructor& circuit_constructor) { if (circuit_verification_key) { @@ -92,16 +89,15 @@ std::shared_ptr TurboPlonkComposerHelper -void TurboPlonkComposerHelper::compute_witness(const CircuitConstructor& circuit_constructor, - const size_t minimum_circuit_size) +void TurboPlonkComposerHelper::compute_witness(const CircuitConstructor& circuit_constructor, + const size_t minimum_circuit_size) { if (computed_witness) { return; } auto wire_polynomial_evaluations = - compute_witness_base(circuit_constructor, minimum_circuit_size, NUM_RANDOMIZED_GATES); + construct_wire_polynomials_base(circuit_constructor, minimum_circuit_size, NUM_RANDOMIZED_GATES); for (size_t j = 0; j < program_width; ++j) { std::string index = std::to_string(j + 1); @@ -119,9 +115,7 @@ void TurboPlonkComposerHelper::compute_witness(const Circuit * * @return Initialized prover. * */ -template -plonk::TurboProver TurboPlonkComposerHelper::create_prover( - const CircuitConstructor& circuit_constructor) +plonk::TurboProver TurboPlonkComposerHelper::create_prover(const CircuitConstructor& circuit_constructor) { // Compute q_l, etc. and sigma polynomials. compute_proving_key(circuit_constructor); @@ -159,10 +153,7 @@ plonk::TurboProver TurboPlonkComposerHelper::create_prover( * * @return The verifier. * */ -// TODO(Cody): This should go away altogether. -template -plonk::TurboVerifier TurboPlonkComposerHelper::create_verifier( - const CircuitConstructor& circuit_constructor) +plonk::TurboVerifier TurboPlonkComposerHelper::create_verifier(const CircuitConstructor& circuit_constructor) { auto verification_key = compute_verification_key(circuit_constructor); @@ -177,5 +168,4 @@ plonk::TurboVerifier TurboPlonkComposerHelper::create_verifi return output_state; } -template class TurboPlonkComposerHelper; } // namespace proof_system::plonk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/turbo_plonk_composer_helper.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/turbo_plonk_composer_helper.hpp index c18fff8d829..de35b01e80a 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/turbo_plonk_composer_helper.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/turbo_plonk_composer_helper.hpp @@ -1,5 +1,6 @@ #pragma once +#include "barretenberg/plonk/flavor/flavor.hpp" #include "barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.hpp" #include "barretenberg/proof_system/composer/composer_helper_lib.hpp" #include "barretenberg/srs/reference_string/file_reference_string.hpp" @@ -8,8 +9,11 @@ #include "barretenberg/plonk/proof_system/verifier/verifier.hpp" namespace proof_system::plonk { -template class TurboPlonkComposerHelper { +class TurboPlonkComposerHelper { public: + using Flavor = plonk::flavor::Turbo; + using CircuitConstructor = TurboCircuitConstructor; + static constexpr size_t NUM_RANDOMIZED_GATES = 2; // equal to the number of multilinear evaluations leaked static constexpr size_t program_width = CircuitConstructor::program_width; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/ultra_plonk_composer_helper.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/ultra_plonk_composer_helper.cpp index 48f2bc64cb3..6dd56226e17 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/ultra_plonk_composer_helper.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/ultra_plonk_composer_helper.cpp @@ -19,8 +19,8 @@ namespace proof_system::plonk { * sorted `s` poly, lookup rows of the wire witnesses, the values of `z_lookup`, `z`. These are all calculated * elsewhere. */ -template -void UltraPlonkComposerHelper::compute_witness(CircuitConstructor& circuit_constructor) + +void UltraPlonkComposerHelper::compute_witness(CircuitConstructor& circuit_constructor) { if (computed_witness) { return; @@ -50,7 +50,8 @@ void UltraPlonkComposerHelper::compute_witness(CircuitConstr // TODO(luke): subgroup size was already computed above but compute_witness_base computes it again. If we pass in // NUM_RANDOMIZED_GATES (as in the other split composers) the resulting sizes can differ. Reconcile this. - auto wire_polynomial_evaluations = compute_witness_base(circuit_constructor, total_num_gates, NUM_RESERVED_GATES); + auto wire_polynomial_evaluations = + construct_wire_polynomials_base(circuit_constructor, total_num_gates, NUM_RESERVED_GATES); for (size_t j = 0; j < program_width; ++j) { std::string index = std::to_string(j + 1); @@ -141,8 +142,7 @@ void UltraPlonkComposerHelper::compute_witness(CircuitConstr computed_witness = true; } -template -UltraProver UltraPlonkComposerHelper::create_prover(CircuitConstructor& circuit_constructor) +UltraProver UltraPlonkComposerHelper::create_prover(CircuitConstructor& circuit_constructor) { finalize_circuit(circuit_constructor); @@ -191,10 +191,8 @@ UltraProver UltraPlonkComposerHelper::create_prover(CircuitC * * @return The verifier. * */ -// TODO(Cody): This should go away altogether. -template -plonk::UltraVerifier UltraPlonkComposerHelper::create_verifier( - const CircuitConstructor& circuit_constructor) + +plonk::UltraVerifier UltraPlonkComposerHelper::create_verifier(const CircuitConstructor& circuit_constructor) { auto verification_key = compute_verification_key(circuit_constructor); @@ -209,8 +207,7 @@ plonk::UltraVerifier UltraPlonkComposerHelper::create_verifi return output_state; } -template -std::shared_ptr UltraPlonkComposerHelper::compute_proving_key( +std::shared_ptr UltraPlonkComposerHelper::compute_proving_key( const CircuitConstructor& circuit_constructor) { if (circuit_proving_key) { @@ -227,18 +224,17 @@ std::shared_ptr UltraPlonkComposerHelper::compu const size_t minimum_circuit_size = tables_size + lookups_size; const size_t num_randomized_gates = NUM_RESERVED_GATES; // Initialize circuit_proving_key - // TODO(#229)(Kesha): replace composer types. - circuit_proving_key = initialize_proving_key( + // TODO(#392)(Kesha): replace composer types. + circuit_proving_key = initialize_proving_key( circuit_constructor, crs_factory_.get(), minimum_circuit_size, num_randomized_gates, ComposerType::PLOOKUP); - construct_lagrange_selector_forms(circuit_constructor, circuit_proving_key.get()); + construct_selector_polynomials(circuit_constructor, circuit_proving_key.get()); - enforce_nonzero_polynomial_selectors(circuit_constructor, circuit_proving_key.get()); + enforce_nonzero_selector_polynomials(circuit_constructor, circuit_proving_key.get()); compute_monomial_and_coset_selector_forms(circuit_proving_key.get(), ultra_selector_properties()); - compute_plonk_generalized_sigma_permutations(circuit_constructor, - circuit_proving_key.get()); + compute_plonk_generalized_sigma_permutations(circuit_constructor, circuit_proving_key.get()); const size_t subgroup_size = circuit_proving_key->circuit_size; @@ -346,8 +342,8 @@ std::shared_ptr UltraPlonkComposerHelper::compu * * @return Pointer to created circuit verification key. * */ -template -std::shared_ptr UltraPlonkComposerHelper::compute_verification_key( + +std::shared_ptr UltraPlonkComposerHelper::compute_verification_key( const CircuitConstructor& circuit_constructor) { if (circuit_verification_key) { @@ -370,9 +366,8 @@ std::shared_ptr UltraPlonkComposerHelper -void UltraPlonkComposerHelper::add_table_column_selector_poly_to_proving_key( - polynomial& selector_poly_lagrange_form, const std::string& tag) +void UltraPlonkComposerHelper::add_table_column_selector_poly_to_proving_key(polynomial& selector_poly_lagrange_form, + const std::string& tag) { polynomial selector_poly_lagrange_form_copy(selector_poly_lagrange_form, circuit_proving_key->small_domain.size); @@ -387,5 +382,4 @@ void UltraPlonkComposerHelper::add_table_column_selector_pol circuit_proving_key->polynomial_store.put(tag + "_fft", std::move(selector_poly_coset_form)); } -template class UltraPlonkComposerHelper; } // namespace proof_system::plonk diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/ultra_plonk_composer_helper.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/ultra_plonk_composer_helper.hpp index 0c0f155b15a..2cef06fc503 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/ultra_plonk_composer_helper.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/composer_helper/ultra_plonk_composer_helper.hpp @@ -1,27 +1,30 @@ #pragma once +#include "barretenberg/plonk/flavor/flavor.hpp" #include "barretenberg/proof_system/composer/composer_helper_lib.hpp" #include "barretenberg/plonk/composer/splitting_tmp/composer_helper/composer_helper_lib.hpp" #include "barretenberg/srs/reference_string/file_reference_string.hpp" #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" #include "barretenberg/plonk/proof_system/prover/prover.hpp" #include "barretenberg/plonk/proof_system/verifier/verifier.hpp" +#include "barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp" #include #include namespace proof_system::plonk { -// TODO(Kesha): change initializations to specify this parameter -// Cody: What does this mean? -template class UltraPlonkComposerHelper { +class UltraPlonkComposerHelper { public: + using Flavor = flavor::Ultra; + using CircuitConstructor = UltraCircuitConstructor; + // TODO(luke): In the split composers, NUM_RANDOMIZED_GATES has replaced NUM_RESERVED_GATES (in some places) to // determine the next-power-of-2 circuit size. (There are some places in this composer that still use // NUM_RESERVED_GATES). Therefore for consistency within this composer itself, and consistency with the original // Ultra Composer, this value must match that of NUM_RESERVED_GATES. This issue needs to be reconciled // simultaneously here and in the other split composers. static constexpr size_t NUM_RESERVED_GATES = 4; // equal to the number of multilinear evaluations leaked - static constexpr size_t program_width = CircuitConstructor::program_width; + static constexpr size_t program_width = CircuitConstructor::NUM_WIRES; std::shared_ptr circuit_proving_key; std::shared_ptr circuit_verification_key; // TODO(#218)(kesha): we need to put this into the commitment key, so that the composer doesn't have to handle srs diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/standard_plonk_composer.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/standard_plonk_composer.hpp index 93524589c68..9dc96d2e2f2 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/standard_plonk_composer.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/standard_plonk_composer.hpp @@ -4,7 +4,6 @@ #include "barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp" #include "barretenberg/srs/reference_string/file_reference_string.hpp" #include "barretenberg/transcript/manifest.hpp" -#include "barretenberg/proof_system/flavor/flavor.hpp" #include "barretenberg/proof_system/types/merkle_hash_type.hpp" #include "barretenberg/proof_system/types/pedersen_commitment_type.hpp" @@ -29,7 +28,7 @@ class StandardPlonkComposer { // 1) Proving and verification keys // 2) CRS // 3) Converting variables to witness vectors/polynomials - StandardPlonkComposerHelper composer_helper; + StandardPlonkComposerHelper composer_helper; // Leaving it in for now just in case bool contains_recursive_proof = false; @@ -195,7 +194,7 @@ class StandardPlonkComposer { static transcript::Manifest create_manifest(const size_t num_public_inputs) { - return StandardPlonkComposerHelper::create_manifest(num_public_inputs); + return StandardPlonkComposerHelper::create_manifest(num_public_inputs); } size_t& num_gates; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/turbo_plonk_composer.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/turbo_plonk_composer.hpp index 1a9abf596ff..950163dae11 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/turbo_plonk_composer.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/turbo_plonk_composer.hpp @@ -26,7 +26,7 @@ class TurboPlonkComposer { // 1) Proving and verification keys // 2) CRS // 3) Converting variables to witness vectors/polynomials - TurboPlonkComposerHelper composer_helper; + TurboPlonkComposerHelper composer_helper; size_t& num_gates; std::vector& variables; @@ -202,7 +202,7 @@ class TurboPlonkComposer { static transcript::Manifest create_manifest(const size_t num_public_inputs) { - return TurboPlonkComposerHelper::create_manifest(num_public_inputs); + return TurboPlonkComposerHelper::create_manifest(num_public_inputs); } bool failed() const { return circuit_constructor.failed(); }; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.hpp index 73a5f6ed94c..53c8ff8f903 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.hpp @@ -23,7 +23,7 @@ class UltraPlonkComposer { // 1) Proving and verification keys // 2) CRS // 3) Converting variables to witness vectors/polynomials - UltraPlonkComposerHelper composer_helper; + UltraPlonkComposerHelper composer_helper; size_t& num_gates; UltraPlonkComposer() diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.test.cpp index 1e697f07d44..5681e9032ea 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/composer/splitting_tmp/ultra_plonk_composer.test.cpp @@ -70,7 +70,6 @@ TEST(ultra_plonk_composer_splitting_tmp, debug_composer_discrepencies) for (const auto& [key, poly] : prover.key->polynomial_store) { if (prover_new.key->polynomial_store.contains(key)) { - // info(key); EXPECT_EQ(prover.key->polynomial_store.get(key), prover_new.key->polynomial_store.get(key)); } } @@ -79,7 +78,6 @@ TEST(ultra_plonk_composer_splitting_tmp, debug_composer_discrepencies) auto verifier_new = composer_new.create_verifier(); for (const auto& [key, poly] : verifier.key->commitments) { - // info(key); EXPECT_EQ(verifier.key->commitments[key], verifier_new.key->commitments[key]); } diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/flavor/flavor.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/flavor/flavor.hpp new file mode 100644 index 00000000000..b9bfa7b0a47 --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/flavor/flavor.hpp @@ -0,0 +1,29 @@ +#pragma once +#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" +#include "barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp" +#include "barretenberg/proof_system/circuit_constructors/turbo_circuit_constructor.hpp" +#include "barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp" + +namespace proof_system::plonk::flavor { +class Standard { + public: + using CircuitConstructor = proof_system::StandardCircuitConstructor; + using ProvingKey = plonk::proving_key; + static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; +}; + +class Turbo { + public: + using CircuitConstructor = proof_system::TurboCircuitConstructor; + using ProvingKey = plonk::proving_key; + static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; +}; + +class Ultra { + public: + using CircuitConstructor = proof_system::UltraCircuitConstructor; + using ProvingKey = plonk::proving_key; + static constexpr size_t NUM_WIRES = CircuitConstructor::NUM_WIRES; +}; +} // namespace proof_system::plonk::flavor \ No newline at end of file diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/proof.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/proof.hpp index aedf516e046..d0a65aa2b68 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/proof.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/proof.hpp @@ -28,7 +28,7 @@ template inline void write(B& buf, proof const& data) inline std::ostream& operator<<(std::ostream& os, proof const& data) { // REFACTOR: This is copied from barretenberg/common/streams.hpp, - // which means we could just cout proof_data directly, but that breaks the build in the CI with + // which means we could just cout proof_data directly, but that breaks the build in the CI with // a redefined operator<< error in barretenberg/stdlib/hash/keccak/keccak.test.cpp, // which is something we really don't want to deal with right now. std::ios_base::fmtflags f(os.flags()); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp index 3fa0e35d38a..67d77015d8d 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp @@ -12,7 +12,7 @@ class settings_base { class standard_settings : public settings_base { public: - using Arithmetization = arithmetization::Standard; + using Arithmetization = arithmetization::Standard; static constexpr size_t num_challenge_bytes = 16; static constexpr transcript::HashType hash_type = transcript::HashType::PedersenBlake3s; static constexpr size_t program_width = 3; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp index fed986d00ce..6c71e14b6c5 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/polynomials/polynomial.hpp @@ -12,6 +12,8 @@ namespace barretenberg { template class Polynomial { public: + using FF = Fr; + // Creates a read only polynomial using mmap. Polynomial(std::string const& filename); diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp index a2f22070849..fb4d72071e1 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp @@ -1,5 +1,7 @@ #pragma once +#include #include +#include namespace arithmetization { @@ -13,29 +15,82 @@ namespace arithmetization { * @remark It may make sense to say this is only partial arithmetization data, with the full data being * contained in the circuit constructor. We could change the name of this class if it conflicts with common usage. * - * @tparam _num_wires + * @tparam _NUM_WIRES * @tparam _num_selectors */ -template struct Arithmetization { - static constexpr size_t num_wires = _num_wires; +template struct Arithmetization { + static constexpr size_t NUM_WIRES = _NUM_WIRES; static constexpr size_t num_selectors = _num_selectors; + // Note: For even greater modularity, in each instantiation we could specify a list of components here, where a // component is a meaningful collection of functions for creating gates, as in: // // struct Component { // using Arithmetic = component::Arithmetic3Wires; // using RangeConstraints = component::Base4Accumulators or component::GenPerm or... - // using LooupTables = component::Plookup4Wire or component::CQ8Wire or... + // using LookupTables = component::Plookup4Wire or component::CQ8Wire or... // ... // }; // // We should only do this if it becomes necessary or convenient. }; -// These are not magic numbers and they should not be written with global constants. These paraters are not accessible +template struct SelectorsBase { + using DataType = std::array, num_selectors>; + DataType _data; + size_t size() { return _data.size(); }; + + typename DataType::const_iterator begin() const { return _data.begin(); }; + typename DataType::iterator begin() { return _data.begin(); }; + typename DataType::const_iterator end() const { return _data.end(); }; + typename DataType::iterator end() { return _data.end(); }; +}; + +// These are not magic numbers and they should not be written with global constants. These parameters are not accessible // through clearly named static class members. -using Standard = Arithmetization; -using Turbo = Arithmetization; -using Ultra = Arithmetization; +template class Standard : public Arithmetization { + public: + struct Selectors : SelectorsBase { + std::vector& q_m = std::get<0>(this->_data); + std::vector& q_1 = std::get<1>(this->_data); + std::vector& q_2 = std::get<2>(this->_data); + std::vector& q_3 = std::get<3>(this->_data); + std::vector& q_c = std::get<4>(this->_data); + }; +}; + +template class Turbo : public Arithmetization { + public: + struct Selectors : SelectorsBase { + std::vector& q_m = std::get<0>(this->_data); + std::vector& q_c = std::get<1>(this->_data); + std::vector& q_1 = std::get<2>(this->_data); + std::vector& q_2 = std::get<3>(this->_data); + std::vector& q_3 = std::get<4>(this->_data); + std::vector& q_4 = std::get<5>(this->_data); + std::vector& q_5 = std::get<6>(this->_data); + std::vector& q_arith = std::get<7>(this->_data); + std::vector& q_fixed_base = std::get<8>(this->_data); + std::vector& q_range = std::get<9>(this->_data); + std::vector& q_logic = std::get<10>(this->_data); + }; +}; + +template class Ultra : public Arithmetization { + public: + struct Selectors : SelectorsBase { + std::vector& q_m = std::get<0>(this->_data); + std::vector& q_c = std::get<1>(this->_data); + std::vector& q_1 = std::get<2>(this->_data); + std::vector& q_2 = std::get<3>(this->_data); + std::vector& q_3 = std::get<4>(this->_data); + std::vector& q_4 = std::get<5>(this->_data); + std::vector& q_arith = std::get<6>(this->_data); + std::vector& q_sort = std::get<7>(this->_data); + std::vector& q_elliptic = std::get<8>(this->_data); + std::vector& q_aux = std::get<9>(this->_data); + std::vector& q_lookup_type = std::get<10>(this->_data); + }; +}; } // namespace arithmetization \ No newline at end of file diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/circuit_constructor_base.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/circuit_constructor_base.cpp index 2f1f190805a..1cdb79e88c3 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/circuit_constructor_base.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/circuit_constructor_base.cpp @@ -41,6 +41,7 @@ void CircuitConstructorBase::assert_equal(const uint32_t a_vari real_variable_tags[a_real_idx] = real_variable_tags[b_real_idx]; } // Standard honk/ plonk instantiation -template class CircuitConstructorBase; -template class CircuitConstructorBase; +template class CircuitConstructorBase>; +template class CircuitConstructorBase>; +template class CircuitConstructorBase>; } // namespace proof_system diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/circuit_constructor_base.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/circuit_constructor_base.hpp index 325349708d0..3f6776eb09a 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/circuit_constructor_base.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/circuit_constructor_base.hpp @@ -9,18 +9,21 @@ static constexpr uint32_t DUMMY_TAG = 0; template class CircuitConstructorBase { public: - static constexpr size_t num_wires = Arithmetization::num_wires; - // Keeping num_wires, at least temporarily, for backward compatibility - static constexpr size_t program_width = Arithmetization::num_wires; + // TODO(Cody): This needs to be templated to allow constructing circuits over Grumpkin. For now, adding FF here + // since the flavor can extract it. + using FF = barretenberg::fr; + static constexpr size_t NUM_WIRES = Arithmetization::NUM_WIRES; + // Keeping NUM_WIRES, at least temporarily, for backward compatibility + static constexpr size_t program_width = Arithmetization::NUM_WIRES; static constexpr size_t num_selectors = Arithmetization::num_selectors; - // TODO(Cody): selector names are used by composer helper. They can therefore be specified through the proving - // system flavor. Getting rid of this also lets us get rid of the weird constructor that's uses the selector names - // functions + + // TODO(Cody): These are plonk-specific and could be specified in the plonk flavors. + // Also, there is loose coupling with the vectors of SelectorProperties std::vector selector_names_; size_t num_gates = 0; - std::array, num_wires> wires; - std::array, num_selectors> selectors; + std::array, NUM_WIRES> wires; + typename Arithmetization::Selectors selectors; std::vector public_inputs; std::vector variables; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp index b627b17a9b9..176aa39ed80 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/standard_circuit_constructor.hpp @@ -1,7 +1,6 @@ #pragma once #include #include "circuit_constructor_base.hpp" -#include "barretenberg/proof_system/flavor/flavor.hpp" #include "barretenberg/proof_system/types/composer_type.hpp" namespace proof_system { @@ -11,17 +10,17 @@ inline std::vector standard_selector_names() return result; } -class StandardCircuitConstructor : public CircuitConstructorBase { +class StandardCircuitConstructor : public CircuitConstructorBase> { public: std::vector& w_l = std::get<0>(wires); std::vector& w_r = std::get<1>(wires); std::vector& w_o = std::get<2>(wires); - std::vector& q_m = std::get<0>(selectors); - std::vector& q_1 = std::get<1>(selectors); - std::vector& q_2 = std::get<2>(selectors); - std::vector& q_3 = std::get<3>(selectors); - std::vector& q_c = std::get<4>(selectors); + std::vector& q_m = selectors.q_m; + std::vector& q_1 = selectors.q_1; + std::vector& q_2 = selectors.q_2; + std::vector& q_3 = selectors.q_3; + std::vector& q_c = selectors.q_c; static constexpr ComposerType type = ComposerType::STANDARD_HONK; // TODO(Cody): Get rid of this. static constexpr size_t UINT_LOG2_BASE = 2; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/turbo_circuit_constructor.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/turbo_circuit_constructor.hpp index 71dcca5c5ef..26310c44a88 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/turbo_circuit_constructor.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/turbo_circuit_constructor.hpp @@ -1,7 +1,6 @@ #pragma once #include #include "circuit_constructor_base.hpp" -#include "barretenberg/proof_system/flavor/flavor.hpp" #include "barretenberg/proof_system/types/composer_type.hpp" namespace proof_system { @@ -12,7 +11,7 @@ inline std::vector turbo_selector_names() "q_5", "q_arith", "q_fixed_base", "q_range", "q_logic" }; return result; } -class TurboCircuitConstructor : public CircuitConstructorBase { +class TurboCircuitConstructor : public CircuitConstructorBase> { public: std::vector& w_l = std::get<0>(wires); @@ -20,17 +19,17 @@ class TurboCircuitConstructor : public CircuitConstructorBase& w_o = std::get<2>(wires); std::vector& w_4 = std::get<3>(wires); - std::vector& q_m = std::get<0>(selectors); - std::vector& q_c = std::get<1>(selectors); - std::vector& q_1 = std::get<2>(selectors); - std::vector& q_2 = std::get<3>(selectors); - std::vector& q_3 = std::get<4>(selectors); - std::vector& q_4 = std::get<5>(selectors); - std::vector& q_5 = std::get<6>(selectors); - std::vector& q_arith = std::get<7>(selectors); - std::vector& q_fixed_base = std::get<8>(selectors); - std::vector& q_range = std::get<9>(selectors); - std::vector& q_logic = std::get<10>(selectors); + std::vector& q_m = selectors.q_m; + std::vector& q_c = selectors.q_c; + std::vector& q_1 = selectors.q_1; + std::vector& q_2 = selectors.q_2; + std::vector& q_3 = selectors.q_3; + std::vector& q_4 = selectors.q_4; + std::vector& q_5 = selectors.q_5; + std::vector& q_arith = selectors.q_arith; + std::vector& q_fixed_base = selectors.q_fixed_base; + std::vector& q_range = selectors.q_range; + std::vector& q_logic = selectors.q_logic; static constexpr ComposerType type = ComposerType::TURBO; static constexpr size_t UINT_LOG2_BASE = 2; diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp index c939163c31a..537288c0fcc 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/circuit_constructors/ultra_circuit_constructor.hpp @@ -3,7 +3,6 @@ #include "barretenberg/plonk/proof_system/types/polynomial_manifest.hpp" #include "circuit_constructor_base.hpp" #include "barretenberg/plonk/proof_system/constants.hpp" -#include "barretenberg/proof_system/flavor/flavor.hpp" #include "barretenberg/proof_system/types/merkle_hash_type.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/proof_system/plookup_tables/types.hpp" @@ -13,7 +12,7 @@ namespace proof_system { -class UltraCircuitConstructor : public CircuitConstructorBase { +class UltraCircuitConstructor : public CircuitConstructorBase> { public: static constexpr ComposerType type = ComposerType::PLOOKUP; static constexpr merkle::HashType merkle_hash_type = merkle::HashType::LOOKUP_PEDERSEN; @@ -531,17 +530,17 @@ class UltraCircuitConstructor : public CircuitConstructorBase& w_o = std::get<2>(wires); std::vector& w_4 = std::get<3>(wires); - std::vector& q_m = std::get<0>(selectors); - std::vector& q_c = std::get<1>(selectors); - std::vector& q_1 = std::get<2>(selectors); - std::vector& q_2 = std::get<3>(selectors); - std::vector& q_3 = std::get<4>(selectors); - std::vector& q_4 = std::get<5>(selectors); - std::vector& q_arith = std::get<6>(selectors); - std::vector& q_sort = std::get<7>(selectors); - std::vector& q_elliptic = std::get<8>(selectors); - std::vector& q_aux = std::get<9>(selectors); - std::vector& q_lookup_type = std::get<10>(selectors); + std::vector& q_m = selectors.q_m; + std::vector& q_c = selectors.q_c; + std::vector& q_1 = selectors.q_1; + std::vector& q_2 = selectors.q_2; + std::vector& q_3 = selectors.q_3; + std::vector& q_4 = selectors.q_4; + std::vector& q_arith = selectors.q_arith; + std::vector& q_sort = selectors.q_sort; + std::vector& q_elliptic = selectors.q_elliptic; + std::vector& q_aux = selectors.q_aux; + std::vector& q_lookup_type = selectors.q_lookup_type; // These are variables that we have used a gate on, to enforce that they are // equal to a defined value. diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_helper_lib.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_helper_lib.hpp index c31dfe13b98..9eb71bf2544 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_helper_lib.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_helper_lib.hpp @@ -1,25 +1,28 @@ #pragma once #include #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" namespace proof_system { /** - * @brief Initialize proving key and load the crs + * @brief Initilalize proving key and load the crs * - * @tparam CircuitConstructor Class containing the circuit + * @tparam Flavor * @param circuit_constructor Object containing the circuit + * @param crs_factory Produces the prover's reference string * @param minimum_circuit_size The minimum size of polynomials without randomized elements * @param num_randomized_gates Number of gates with randomized witnesses * @param composer_type The type of composer we are using - * @return std::shared_ptr + * @return std::shared_ptr */ -template -std::shared_ptr initialize_proving_key(const CircuitConstructor& circuit_constructor, - ReferenceStringFactory* crs_factory, - const size_t minimum_circuit_size, - const size_t num_randomized_gates, - ComposerType composer_type) +template +std::shared_ptr initialize_proving_key( + const typename Flavor::CircuitConstructor& circuit_constructor, + ReferenceStringFactory* crs_factory, + const size_t minimum_circuit_size, + const size_t num_randomized_gates, + ComposerType composer_type) { const size_t num_gates = circuit_constructor.num_gates; std::span public_inputs = circuit_constructor.public_inputs; @@ -32,77 +35,95 @@ std::shared_ptr initialize_proving_key(const CircuitConstruc auto crs = crs_factory->get_prover_crs(subgroup_size + 1); - return std::make_shared(subgroup_size, num_public_inputs, crs, composer_type); + return std::make_shared(subgroup_size, num_public_inputs, crs, composer_type); } /** - * @brief Construct lagrange selector polynomials from ciruit selector information and put into polynomial cache + * @brief Construct selector polynomials from ciruit selector information and put into polynomial cache * - * @tparam CircuitConstructor The class holding the circuit + * @tparam Flavor * @param circuit_constructor The object holding the circuit * @param key Pointer to the proving key */ -template -void construct_lagrange_selector_forms(const CircuitConstructor& circuit_constructor, - plonk::proving_key* circuit_proving_key) +template +void construct_selector_polynomials(const typename Flavor::CircuitConstructor& circuit_constructor, + typename Flavor::ProvingKey* proving_key) { const size_t num_public_inputs = circuit_constructor.public_inputs.size(); - for (size_t j = 0; j < circuit_constructor.num_selectors; ++j) { - std::span selector_values = circuit_constructor.selectors[j]; - ASSERT(circuit_proving_key->circuit_size >= selector_values.size()); + // TODO(#398): Loose coupling here! Would rather build up pk from arithmetization + size_t selector_idx = 0; // TODO(#391) zip + for (auto& selector_values : circuit_constructor.selectors) { + ASSERT(proving_key->circuit_size >= selector_values.size()); - // Compute selector vector, initialized to 0. // Copy the selector values for all gates, keeping the rows at which we store public inputs as 0. // Initializing the polynomials in this way automatically applies 0-padding to the selectors. - barretenberg::polynomial selector_poly_lagrange(circuit_proving_key->circuit_size); + barretenberg::polynomial selector_poly_lagrange(proving_key->circuit_size); for (size_t i = 0; i < selector_values.size(); ++i) { selector_poly_lagrange[num_public_inputs + i] = selector_values[i]; } - // TODO(#217)(Adrian): We may want to add a unique value (e.g. j+1) in the last position of each selector - // polynomial to guard against some edge cases that may occur during the MSM. If we do so, we should ensure that - // this does not clash with any other values we want to place at the end of of the witness vectors. In later - // iterations of the Sumcheck, we will be able to efficiently cancel out any checks in the last 2^k rows, so any - // randomness or unique values should be placed there. - circuit_proving_key->polynomial_store.put(circuit_constructor.selector_names_[j] + "_lagrange", - std::move(selector_poly_lagrange)); + if constexpr (IsHonkFlavor) { + // TODO(#398): Loose coupling here of arithmetization and flavor. + proving_key->_precomputed_polynomials[selector_idx] = selector_poly_lagrange; + } else if constexpr (IsPlonkFlavor) { + // TODO(Cody): Loose coupling here of selector_names and selector_properties. + proving_key->polynomial_store.put(circuit_constructor.selector_names_[selector_idx] + "_lagrange", + std::move(selector_poly_lagrange)); + } + ++selector_idx; } } /** * @brief Fill the last index of each selector polynomial in lagrange form with a non-zero value * - * @tparam CircuitConstructor The class holding the circuit + * @tparam Flavor * @param circuit_constructor The object holding the circuit * @param key Pointer to the proving key + * + * @warning We should ensure that this does not clash with any other values we want to place at the end of of the + * witness vectors. In later iterations of the Sumcheck, we will be able to efficiently cancel out any checks in the + * last 2^k rows, so any randomness or unique values should be placed there. -@adr1anh */ -template -void enforce_nonzero_polynomial_selectors(const CircuitConstructor& circuit_constructor, - plonk::proving_key* circuit_proving_key) +template +void enforce_nonzero_selector_polynomials(const typename Flavor::CircuitConstructor& circuit_constructor, + typename Flavor::ProvingKey* proving_key) { - for (size_t j = 0; j < circuit_constructor.num_selectors; ++j) { - auto current_selector = - circuit_proving_key->polynomial_store.get(circuit_constructor.selector_names_[j] + "_lagrange"); - current_selector[current_selector.size() - 1] = j + 1; - circuit_proving_key->polynomial_store.put(circuit_constructor.selector_names_[j] + "_lagrange", - std::move(current_selector)); + if constexpr (IsHonkFlavor) { + size_t idx = 1; + for (auto selector : proving_key->get_selectors()) { + selector[selector.size() - 1] = idx; + ++idx; + } + } else if constexpr (IsPlonkFlavor) { + for (size_t idx = 0; idx < circuit_constructor.num_selectors; ++idx) { + auto current_selector = + proving_key->polynomial_store.get(circuit_constructor.selector_names_[idx] + "_lagrange"); + current_selector[current_selector.size() - 1] = idx + 1; + proving_key->polynomial_store.put(circuit_constructor.selector_names_[idx] + "_lagrange", + std::move(current_selector)); + } } } /** - * Compute witness polynomials (w_1, w_2, w_3, w_4) and put them into polynomial cache + * @brief Construct the witness polynomials from the witness vectors in the circuit constructor. * - * @details Fills 3 or 4 witness polynomials w_1, w_2, w_3, w_4 with the values of in-circuit variables. The beginning - * of w_1, w_2 polynomials is filled with public_input values. - * @return Witness with computed witness polynomials. + * @details The first two witness polynomials begin with the public input values. * - * @tparam Program settings needed to establish if w_4 is being used. + * + * @tparam Flavor provides the circuit constructor type and the number of wires. + * @param circuit_constructor + * @param minimum_circuit_size + * @param number_of_randomized_gates + * + * @return std::vector * */ -template -std::vector compute_witness_base(const CircuitConstructor& circuit_constructor, - const size_t minimum_circuit_size, - const size_t number_of_randomized_gates) +template +std::vector construct_wire_polynomials_base( + const typename Flavor::CircuitConstructor& circuit_constructor, + const size_t minimum_circuit_size, + const size_t number_of_randomized_gates) { - const size_t program_width = CircuitConstructor::program_width; const size_t num_gates = circuit_constructor.num_gates; std::span public_inputs = circuit_constructor.public_inputs; const size_t num_public_inputs = public_inputs.size(); @@ -117,36 +138,32 @@ std::vector compute_witness_base(const CircuitConstruc // construct a view over all the wire's variable indices // w[j][i] is the index of the variable in the j-th wire, at gate i // Each array should be of size `num_gates` - std::array, program_width> w; - w[0] = circuit_constructor.w_l; - w[1] = circuit_constructor.w_r; - w[2] = circuit_constructor.w_o; - if constexpr (program_width > 3) { - w[3] = circuit_constructor.w_4; - } - std::vector wires; + + std::vector wire_polynomials; // Note: randomness is added to 3 of the last 4 positions in plonk/proof_system/prover/prover.cpp // StandardProverBase::execute_preamble_round(). - for (size_t j = 0; j < program_width; ++j) { + size_t wire_idx = 0; // TODO(#391) zip + for (auto& wire : circuit_constructor.wires) { // Initialize the polynomial with all the actual copies variable values // Expect all values to be set to 0 initially barretenberg::polynomial w_lagrange(subgroup_size); - // Place all public inputs at the start of w_l and w_r. - // All selectors at these indices are set to 0 so these values are not constrained at all. - if ((j == 0) || (j == 1)) { + // Place all public inputs at the start of the first two wires. + // All selectors at these indices are set to 0, so these values are not constrained at all. + if (wire_idx < 2) { for (size_t i = 0; i < num_public_inputs; ++i) { w_lagrange[i] = circuit_constructor.get_variable(public_inputs[i]); } + ++wire_idx; } - // Assign the variable values (which are pointed-to by the `w_` wires) to the wire witness polynomials - // `poly_w_`, shifted to make room for the public inputs at the beginning. + // Assign the variable values (which are pointed-to by the `w_` wire_polynomials) to the wire witness + // polynomials `poly_w_`, shifted to make room for the public inputs at the beginning. for (size_t i = 0; i < num_gates; ++i) { - w_lagrange[num_public_inputs + i] = circuit_constructor.get_variable(w[j][i]); + w_lagrange[num_public_inputs + i] = circuit_constructor.get_variable(wire[i]); } - wires.push_back(std::move(w_lagrange)); + wire_polynomials.push_back(std::move(w_lagrange)); } - return wires; + return wire_polynomials; } } // namespace proof_system diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_helper_lib.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_helper_lib.test.cpp new file mode 100644 index 00000000000..720705b7f03 --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_helper_lib.test.cpp @@ -0,0 +1,169 @@ +#include +#include +#include "barretenberg/honk/flavor/standard.hpp" // TODO: needed? +#include "barretenberg/proof_system/composer/composer_helper_lib.hpp" +#include "barretenberg/proof_system/types/composer_type.hpp" +#include "barretenberg/srs/reference_string/reference_string.hpp" + +namespace proof_system::test_composer_lib { + +class ComposerLibTests : public ::testing::Test { + protected: + using Flavor = honk::flavor::Standard; + using FF = typename Flavor::FF; + Flavor::CircuitConstructor circuit_constructor; + Flavor::ProvingKey proving_key = []() { + auto crs_factory = ReferenceStringFactory(); + auto crs = crs_factory.get_prover_crs(4); + return Flavor::ProvingKey(/*circuit_size=*/4, /*num_public_inputs=*/0, crs, ComposerType::STANDARD); + }(); +}; + +TEST_F(ComposerLibTests, InitializeProvingKey) +{ + static_assert(IsHonkFlavor); + + EXPECT_EQ(circuit_constructor.get_circuit_subgroup_size(7), 8); + + ReferenceStringFactory crs_factory; + + auto pk = initialize_proving_key(circuit_constructor, + &crs_factory, + /*minimum_circuit_size=*/0, + /*num_randomized_gates=*/2, + ComposerType::STANDARD); + EXPECT_EQ(pk->circuit_size, 8); + EXPECT_EQ(pk->num_public_inputs, 0); +} + +TEST_F(ComposerLibTests, ConstructSelectors) +{ + circuit_constructor.q_m = std::vector{ 1, 2, 3, 4 }; + circuit_constructor.q_1 = std::vector{ 5, 6, 7, 8 }; + circuit_constructor.q_2 = std::vector{ 9, 10, 11, 12 }; + circuit_constructor.q_3 = std::vector{ 13, 14, 15, 16 }; + circuit_constructor.q_c = std::vector{ 17, 18, 19, 20 }; + + construct_selector_polynomials(circuit_constructor, &proving_key); + + EXPECT_EQ(proving_key.q_m[0], 1); + EXPECT_EQ(proving_key.q_m[1], 2); + EXPECT_EQ(proving_key.q_m[2], 3); + EXPECT_EQ(proving_key.q_m[3], 4); + + EXPECT_EQ(proving_key.q_l[0], 5); + EXPECT_EQ(proving_key.q_l[1], 6); + EXPECT_EQ(proving_key.q_l[2], 7); + EXPECT_EQ(proving_key.q_l[3], 8); + + EXPECT_EQ(proving_key.q_r[0], 9); + EXPECT_EQ(proving_key.q_r[1], 10); + EXPECT_EQ(proving_key.q_r[2], 11); + EXPECT_EQ(proving_key.q_r[3], 12); + + EXPECT_EQ(proving_key.q_o[0], 13); + EXPECT_EQ(proving_key.q_o[1], 14); + EXPECT_EQ(proving_key.q_o[2], 15); + EXPECT_EQ(proving_key.q_o[3], 16); + + EXPECT_EQ(proving_key.q_c[0], 17); + EXPECT_EQ(proving_key.q_c[1], 18); + EXPECT_EQ(proving_key.q_c[2], 19); + EXPECT_EQ(proving_key.q_c[3], 20); +} + +TEST_F(ComposerLibTests, EnforceNonzeroSelectors) +{ + circuit_constructor.q_m = std::vector{ 0, 0, 0, 0 }; + circuit_constructor.q_1 = std::vector{ 0, 0, 0, 0 }; + circuit_constructor.q_2 = std::vector{ 0, 0, 0, 0 }; + circuit_constructor.q_3 = std::vector{ 0, 0, 0, 0 }; + circuit_constructor.q_c = std::vector{ 0, 0, 0, 0 }; + + construct_selector_polynomials(circuit_constructor, &proving_key); + enforce_nonzero_selector_polynomials(circuit_constructor, &proving_key); + + EXPECT_EQ(proving_key.q_m[3], 1); + EXPECT_EQ(proving_key.q_l[3], 2); + EXPECT_EQ(proving_key.q_r[3], 3); + EXPECT_EQ(proving_key.q_o[3], 4); + EXPECT_EQ(proving_key.q_c[3], 5); +} + +TEST_F(ComposerLibTests, ConstructWitnessPolynomialsBase) +{ + circuit_constructor.add_public_variable(1024); + circuit_constructor.add_public_variable(1025); + + uint32_t v_1 = circuit_constructor.add_variable(16 + 1); + uint32_t v_2 = circuit_constructor.add_variable(16 + 2); + uint32_t v_3 = circuit_constructor.add_variable(16 + 3); + uint32_t v_4 = circuit_constructor.add_variable(16 + 4); + uint32_t v_5 = circuit_constructor.add_variable(16 + 5); + uint32_t v_6 = circuit_constructor.add_variable(16 + 6); + uint32_t v_7 = circuit_constructor.add_variable(16 + 7); + uint32_t v_8 = circuit_constructor.add_variable(16 + 8); + uint32_t v_9 = circuit_constructor.add_variable(16 + 9); + uint32_t v_10 = circuit_constructor.add_variable(16 + 10); + uint32_t v_11 = circuit_constructor.add_variable(16 + 11); + uint32_t v_12 = circuit_constructor.add_variable(16 + 12); + + circuit_constructor.create_add_gate({ v_1, v_5, v_9, 0, 0, 0, 0 }); + circuit_constructor.create_add_gate({ v_2, v_6, v_10, 0, 0, 0, 0 }); + circuit_constructor.create_add_gate({ v_3, v_7, v_11, 0, 0, 0, 0 }); + circuit_constructor.create_add_gate({ v_4, v_8, v_12, 0, 0, 0, 0 }); + + /* Execution trace: + w_l w_r w_o + ------------------------------ + pub1_idx | pub1_idx | 0 <-- public inputs + pub2_idx | pub2_idx | 0 <-/ + zero_idx | zero_idx | zero_idx <-- fix witness for 0 + one_idx | zero_idx | zero_idx <-- fix witness for 1 + one_idx | one_idx | one_idx <-- ensure nonzero selectors... TODO(Cody): redundant now + v_1 | v_5 | v_9 + v_2 | v_6 | v_10 + v_3 | v_7 | v_11 + v_4 | v_8 | v_12 + + */ + + auto wires = construct_wire_polynomials_base(circuit_constructor, 1, 2); + auto& w_l = wires[0]; + auto& w_r = wires[1]; + auto& w_o = wires[2]; + auto& zero_idx = circuit_constructor.zero_idx; + auto& one_idx = circuit_constructor.one_idx; + + EXPECT_EQ(w_l[0], 1024); + EXPECT_EQ(w_l[1], 1025); + EXPECT_EQ(w_l[2], zero_idx); + EXPECT_EQ(w_l[3], one_idx); + EXPECT_EQ(w_l[4], one_idx); + EXPECT_EQ(w_l[5], 17); + EXPECT_EQ(w_l[6], 18); + EXPECT_EQ(w_l[7], 19); + EXPECT_EQ(w_l[8], 20); + + EXPECT_EQ(w_r[0], 1024); + EXPECT_EQ(w_r[1], 1025); + EXPECT_EQ(w_r[2], zero_idx); + EXPECT_EQ(w_r[3], zero_idx); + EXPECT_EQ(w_r[4], one_idx); + EXPECT_EQ(w_r[5], 21); + EXPECT_EQ(w_r[6], 22); + EXPECT_EQ(w_r[7], 23); + EXPECT_EQ(w_r[8], 24); + + EXPECT_EQ(w_o[0], 0); + EXPECT_EQ(w_o[1], 0); + EXPECT_EQ(w_o[2], zero_idx); + EXPECT_EQ(w_o[3], zero_idx); + EXPECT_EQ(w_o[4], one_idx); + EXPECT_EQ(w_o[5], 25); + EXPECT_EQ(w_o[6], 26); + EXPECT_EQ(w_o[7], 27); + EXPECT_EQ(w_o[8], 28); +} + +} // namespace proof_system::test_composer_lib diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_helper.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_helper.hpp index 8da1252278e..2c12ef18e90 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_helper.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_helper.hpp @@ -5,12 +5,12 @@ * @details It is structured to reuse similar components in Honk and Plonk * */ - #pragma once #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" +#include "barretenberg/polynomials/iterate_over_domain.hpp" #include #include @@ -21,6 +21,8 @@ #include #include +// TODO(Cody): very little code is shared; should split this up into plonk/honk files. + namespace proof_system { /** @@ -48,8 +50,8 @@ struct permutation_subgroup_element { bool is_tag = false; }; -template struct PermutationMapping { - using Mapping = std::array, program_width>; +template struct PermutationMapping { + using Mapping = std::array, NUM_WIRES>; Mapping sigmas; Mapping ids; }; @@ -64,24 +66,14 @@ namespace { * * @tparam program_width Program width * */ -template -std::vector compute_wire_copy_cycles(const CircuitConstructor& circuit_constructor) +template +std::vector compute_wire_copy_cycles(const typename Flavor::CircuitConstructor& circuit_constructor) { // Reference circuit constructor members const size_t num_gates = circuit_constructor.num_gates; std::span public_inputs = circuit_constructor.public_inputs; const size_t num_public_inputs = public_inputs.size(); - // Get references to the wires containing the index of the value inside constructor.variables - // These wires only contain the "real" gate constraints, and are not padded. - std::array, program_width> wire_indices; - wire_indices[0] = circuit_constructor.w_l; - wire_indices[1] = circuit_constructor.w_r; - wire_indices[2] = circuit_constructor.w_o; - if constexpr (program_width > 3) { - wire_indices[3] = circuit_constructor.w_4; - } - // Each variable represents one cycle const size_t number_of_cycles = circuit_constructor.variables.size(); std::vector copy_cycles(number_of_cycles); @@ -110,17 +102,19 @@ std::vector compute_wire_copy_cycles(const CircuitConstructor } // Iterate over all variables of the "real" gates, and add a corresponding node to the cycle for that variable - for (size_t i = 0; i < num_gates; ++i) { - for (size_t j = 0; j < program_width; ++j) { + for (size_t gate_idx = 0; gate_idx < num_gates; ++gate_idx) { + size_t wire_idx = 0; + for (auto& wire : circuit_constructor.wires) { // We are looking at the j-th wire in the i-th row. // The value in this position should be equal to the value of the element at index `var_index` // of the `constructor.variables` vector. // Therefore, we add (i,j) to the cycle at index `var_index` to indicate that w^j_i should have the values // constructor.variables[var_index]. - const uint32_t var_index = circuit_constructor.real_variable_index[wire_indices[j][i]]; - const auto wire_index = static_cast(j); - const auto gate_index = static_cast(i + num_public_inputs); - copy_cycles[var_index].emplace_back(cycle_node{ wire_index, gate_index }); + const uint32_t var_index = circuit_constructor.real_variable_index[wire[gate_idx]]; + const auto wire_index = static_cast(wire_idx); + const auto shifted_gate_idx = static_cast(gate_idx + num_public_inputs); + copy_cycles[var_index].emplace_back(cycle_node{ wire_index, shifted_gate_idx }); + ++wire_idx; } } return copy_cycles; @@ -139,28 +133,32 @@ std::vector compute_wire_copy_cycles(const CircuitConstructor * @param key Pointer to the proving key * @return PermutationMapping sigma mapping (and id mapping if generalized == true) */ -template -PermutationMapping compute_permutation_mapping(const CircuitConstructor& circuit_constructor, - plonk::proving_key* key) +template +PermutationMapping compute_permutation_mapping( + const typename Flavor::CircuitConstructor& circuit_constructor, typename Flavor::ProvingKey* proving_key) { // Compute wire copy cycles (cycles of permutations) - auto wire_copy_cycles = compute_wire_copy_cycles(circuit_constructor); + auto wire_copy_cycles = compute_wire_copy_cycles(circuit_constructor); - PermutationMapping mapping; + PermutationMapping mapping; // Initialize the table of permutations so that every element points to itself - for (size_t i = 0; i < program_width; ++i) { - mapping.sigmas[i].reserve(key->circuit_size); - if (generalized) { - mapping.ids[i].reserve(key->circuit_size); + for (size_t i = 0; i < Flavor::NUM_WIRES; ++i) { // TODO(#391) zip and split + mapping.sigmas[i].reserve(proving_key->circuit_size); + if constexpr (generalized) { + mapping.ids[i].reserve(proving_key->circuit_size); } - for (size_t j = 0; j < key->circuit_size; ++j) { - mapping.sigmas[i].emplace_back(permutation_subgroup_element{ - .row_index = (uint32_t)j, .column_index = (uint8_t)i, .is_public_input = false, .is_tag = false }); - if (generalized) { - mapping.ids[i].emplace_back(permutation_subgroup_element{ - .row_index = (uint32_t)j, .column_index = (uint8_t)i, .is_public_input = false, .is_tag = false }); + for (size_t j = 0; j < proving_key->circuit_size; ++j) { + mapping.sigmas[i].emplace_back(permutation_subgroup_element{ .row_index = static_cast(j), + .column_index = static_cast(i), + .is_public_input = false, + .is_tag = false }); + if constexpr (generalized) { + mapping.ids[i].emplace_back(permutation_subgroup_element{ .row_index = static_cast(j), + .column_index = static_cast(i), + .is_public_input = false, + .is_tag = false }); } } } @@ -187,7 +185,7 @@ PermutationMapping compute_permutation_mapping(const CircuitConst .row_index = next_row, .column_index = next_column, .is_public_input = false, .is_tag = false }; - if (generalized) { + if constexpr (generalized) { bool first_node = (node_idx == 0); bool last_node = (next_cycle_node_index == 0); @@ -231,20 +229,17 @@ PermutationMapping compute_permutation_mapping(const CircuitConst * @param permutation_mappings A table with information about permuting each element * @param key Pointer to the proving key */ -template +template void compute_honk_style_permutation_lagrange_polynomials_from_mapping( - std::string label, - std::array, program_width>& permutation_mappings, - plonk::proving_key* key) + std::vector permutation_polynomials, // sigma or ID poly + std::array, Flavor::NUM_WIRES>& permutation_mappings, + typename Flavor::ProvingKey* proving_key) { - const size_t num_gates = key->circuit_size; - - std::array permutation_poly; // sigma or ID poly + const size_t num_gates = proving_key->circuit_size; - for (size_t wire_index = 0; wire_index < program_width; wire_index++) { - permutation_poly[wire_index] = barretenberg::polynomial(num_gates); - auto& current_permutation_poly = permutation_poly[wire_index]; - ITERATE_OVER_DOMAIN_START(key->small_domain) + size_t wire_index = 0; + for (auto& current_permutation_poly : permutation_polynomials) { + ITERATE_OVER_DOMAIN_START(proving_key->evaluation_domain); const auto& current_mapping = permutation_mappings[wire_index][i]; if (current_mapping.is_public_input) { // We intentionally want to break the cycles of the public input variables. @@ -259,7 +254,7 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( -barretenberg::fr(current_mapping.row_index + 1 + num_gates * current_mapping.column_index); } else if (current_mapping.is_tag) { // Set evaluations to (arbitrary) values disjoint from non-tag values - current_permutation_poly[i] = num_gates * program_width + current_mapping.row_index; + current_permutation_poly[i] = num_gates * Flavor::NUM_WIRES + current_mapping.row_index; } else { // For the regular permutation we simply point to the next location by setting the evaluation to its // index @@ -267,13 +262,10 @@ void compute_honk_style_permutation_lagrange_polynomials_from_mapping( barretenberg::fr(current_mapping.row_index + num_gates * current_mapping.column_index); } ITERATE_OVER_DOMAIN_END; - } - // Save to polynomial cache - for (size_t j = 0; j < program_width; j++) { - std::string index = std::to_string(j + 1); - key->polynomial_store.put(label + "_" + index + "_lagrange", std::move(permutation_poly[j])); + wire_index++; } } +} // namespace /** * Compute sigma permutation polynomial in lagrange base @@ -404,8 +396,6 @@ void compute_monomial_and_coset_fft_polynomials_from_lagrange(std::string label, } } -} // namespace - /** * @brief Compute standard honk id polynomials and put them into cache * @@ -415,19 +405,17 @@ void compute_monomial_and_coset_fft_polynomials_from_lagrange(std::string label, * @tparam program_width The number of witness polynomials * @param key Proving key where we will save the polynomials */ -template -void compute_standard_honk_id_polynomials(auto key) // proving_key* and shared_ptr +template +void compute_standard_honk_id_polynomials(auto proving_key) // TODO(Cody): proving_key* and shared_ptr { - const size_t n = key->circuit_size; // Fill id polynomials with default values - for (size_t j = 0; j < program_width; ++j) { - // Construct permutation polynomials in lagrange base - barretenberg::polynomial id_j(n); - for (size_t i = 0; i < key->circuit_size; ++i) { - id_j[i] = (j * n + i); + // TODO(Cody): Allocate polynomial space in proving key constructor. + size_t coset_idx = 0; // TODO(#391) zip + for (auto& id_poly : proving_key->get_id_polynomials()) { + for (size_t i = 0; i < proving_key->circuit_size; ++i) { + id_poly[i] = coset_idx * proving_key->circuit_size + i; } - std::string index = std::to_string(j + 1); - key->polynomial_store.put("id_" + index + "_lagrange", std::move(id_j)); + ++coset_idx; } } @@ -435,7 +423,8 @@ void compute_standard_honk_id_polynomials(auto key) // proving_key* and shared_p * @brief Compute sigma permutations for standard honk and put them into polynomial cache * * @details These permutations don't involve sets. We only care about equating one witness value to another. The - * sequences don't use cosets unlike FFT-based Plonk, because there is no need for them. We simply use indices based on + * sequences don't use cosets unlike FFT-based Plonk, because there is no need for them. We simply use indices based + on * the witness vector and index within the vector. These values are permuted to account for wire copy cycles * * @tparam program_width @@ -444,13 +433,15 @@ void compute_standard_honk_id_polynomials(auto key) // proving_key* and shared_p * @param key */ // TODO(#293): Update this (and all similar functions) to take a smart pointer. -template -void compute_standard_honk_sigma_permutations(CircuitConstructor& circuit_constructor, plonk::proving_key* key) +template +void compute_standard_honk_sigma_permutations(const typename Flavor::CircuitConstructor& circuit_constructor, + typename Flavor::ProvingKey* proving_key) { // Compute the permutation table specifying which element becomes which - auto mapping = compute_permutation_mapping(circuit_constructor, key); - // Compute Honk-style sigma polynomial fromt the permutation table - compute_honk_style_permutation_lagrange_polynomials_from_mapping("sigma", mapping.sigmas, key); + auto mapping = compute_permutation_mapping(circuit_constructor, proving_key); + // Compute Honk-style sigma polynomial from the permutation table + compute_honk_style_permutation_lagrange_polynomials_from_mapping( + proving_key->get_sigma_polynomials(), mapping.sigmas, proving_key); } /** @@ -461,15 +452,16 @@ void compute_standard_honk_sigma_permutations(CircuitConstructor& circuit_constr * @param circuit_constructor An object holdingt he circuit * @param key Pointer to a proving key */ -template -void compute_standard_plonk_sigma_permutations(CircuitConstructor& circuit_constructor, plonk::proving_key* key) +template +void compute_standard_plonk_sigma_permutations(const typename Flavor::CircuitConstructor& circuit_constructor, + typename Flavor::ProvingKey* key) { // Compute the permutation table specifying which element becomes which - auto mapping = compute_permutation_mapping(circuit_constructor, key); + auto mapping = compute_permutation_mapping(circuit_constructor, key); // Compute Plonk-style sigma polynomials from the mapping compute_plonk_permutation_lagrange_polynomials_from_mapping("sigma", mapping.sigmas, key); // Compute their monomial and coset versions - compute_monomial_and_coset_fft_polynomials_from_lagrange("sigma", key); + compute_monomial_and_coset_fft_polynomials_from_lagrange("sigma", key); } /** @@ -477,15 +469,16 @@ void compute_standard_plonk_sigma_permutations(CircuitConstructor& circuit_const * * @param key Proving key where we will save the polynomials */ -inline void compute_first_and_last_lagrange_polynomials(auto key) // proving_key* and share_ptr +template inline void compute_first_and_last_lagrange_polynomials(auto proving_key) { - const size_t n = key->circuit_size; - barretenberg::polynomial lagrange_polynomial_0(n); - barretenberg::polynomial lagrange_polynomial_n_min_1(n); + const size_t n = proving_key->circuit_size; + typename Flavor::Polynomial lagrange_polynomial_0(n); + typename Flavor::Polynomial lagrange_polynomial_n_min_1(n); lagrange_polynomial_0[0] = 1; + proving_key->lagrange_first = lagrange_polynomial_0; + lagrange_polynomial_n_min_1[n - 1] = 1; - key->polynomial_store.put("L_first_lagrange", std::move(lagrange_polynomial_0)); - key->polynomial_store.put("L_last_lagrange", std::move(lagrange_polynomial_n_min_1)); + proving_key->lagrange_last = lagrange_polynomial_n_min_1; } /** @@ -497,18 +490,18 @@ inline void compute_first_and_last_lagrange_polynomials(auto key) // proving_key * @param key * @return std::array, program_width> */ -template -void compute_plonk_generalized_sigma_permutations(const CircuitConstructor& circuit_constructor, - plonk::proving_key* key) +template +void compute_plonk_generalized_sigma_permutations(const typename Flavor::CircuitConstructor& circuit_constructor, + typename Flavor::ProvingKey* key) { - auto mapping = compute_permutation_mapping(circuit_constructor, key); + auto mapping = compute_permutation_mapping(circuit_constructor, key); // Compute Plonk-style sigma and ID polynomials from the corresponding mappings compute_plonk_permutation_lagrange_polynomials_from_mapping("sigma", mapping.sigmas, key); compute_plonk_permutation_lagrange_polynomials_from_mapping("id", mapping.ids, key); // Compute the monomial and coset-ffts for sigmas and IDs - compute_monomial_and_coset_fft_polynomials_from_lagrange("sigma", key); - compute_monomial_and_coset_fft_polynomials_from_lagrange("id", key); + compute_monomial_and_coset_fft_polynomials_from_lagrange("sigma", key); + compute_monomial_and_coset_fft_polynomials_from_lagrange("id", key); } /** @@ -517,17 +510,20 @@ void compute_plonk_generalized_sigma_permutations(const CircuitConstructor& circ * @tparam program_width * @tparam CircuitConstructor * @param circuit_constructor - * @param key + * @param proving_key * @return std::array, program_width> */ -template -void compute_honk_generalized_sigma_permutations(const CircuitConstructor& circuit_constructor, plonk::proving_key* key) +template +void compute_honk_generalized_sigma_permutations(const typename Flavor::CircuitConstructor& circuit_constructor, + typename Flavor::ProvingKey* proving_key) { - auto mapping = compute_permutation_mapping(circuit_constructor, key); + auto mapping = compute_permutation_mapping(circuit_constructor, proving_key); // Compute Honk-style sigma and ID polynomials from the corresponding mappings - compute_honk_style_permutation_lagrange_polynomials_from_mapping("sigma", mapping.sigmas, key); - compute_honk_style_permutation_lagrange_polynomials_from_mapping("id", mapping.ids, key); + compute_honk_style_permutation_lagrange_polynomials_from_mapping( + proving_key->get_sigma_polynomials(), mapping.sigmas, proving_key); + compute_honk_style_permutation_lagrange_polynomials_from_mapping( + proving_key->get_id_polynomials(), mapping.ids, proving_key); } } // namespace proof_system diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_helper.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_helper.test.cpp new file mode 100644 index 00000000000..57103c69ae0 --- /dev/null +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_helper.test.cpp @@ -0,0 +1,91 @@ +#include +#include +#include "barretenberg/honk/flavor/standard.hpp" // TODO: needed? +#include "barretenberg/proof_system/composer/composer_helper_lib.hpp" +#include "barretenberg/proof_system/composer/permutation_helper.hpp" +#include "barretenberg/proof_system/types/composer_type.hpp" +#include "barretenberg/srs/reference_string/reference_string.hpp" + +namespace proof_system::test_composer_lib { + +class PermutationHelperTests : public ::testing::Test { + protected: + using Flavor = honk::flavor::Standard; + using FF = typename Flavor::FF; + Flavor::CircuitConstructor circuit_constructor; + ReferenceStringFactory crs_factory = ReferenceStringFactory(); + std::shared_ptr proving_key; + + virtual void SetUp() + { + circuit_constructor.add_public_variable(1024); + circuit_constructor.add_public_variable(1025); + + uint32_t v_1 = circuit_constructor.add_variable(16 + 1); + uint32_t v_2 = circuit_constructor.add_variable(16 + 2); + uint32_t v_3 = circuit_constructor.add_variable(16 + 3); + uint32_t v_4 = circuit_constructor.add_variable(16 + 4); + uint32_t v_5 = circuit_constructor.add_variable(16 + 5); + uint32_t v_6 = circuit_constructor.add_variable(16 + 6); + uint32_t v_7 = circuit_constructor.add_variable(16 + 7); + uint32_t v_8 = circuit_constructor.add_variable(16 + 8); + uint32_t v_9 = circuit_constructor.add_variable(16 + 9); + uint32_t v_10 = circuit_constructor.add_variable(16 + 10); + uint32_t v_11 = circuit_constructor.add_variable(16 + 11); + uint32_t v_12 = circuit_constructor.add_variable(16 + 12); + + circuit_constructor.create_add_gate({ v_1, v_5, v_9, 0, 0, 0, 0 }); + circuit_constructor.create_add_gate({ v_2, v_6, v_10, 0, 0, 0, 0 }); + circuit_constructor.create_add_gate({ v_3, v_7, v_11, 0, 0, 0, 0 }); + circuit_constructor.create_add_gate({ v_4, v_8, v_12, 0, 0, 0, 0 }); + + /* Execution trace: + w_l w_r w_o + ------------------------------ + pub1_idx | pub1_idx | 0 <-- public inputs + pub2_idx | pub2_idx | 0 <-/ + zero_idx | zero_idx | zero_idx <-- fix witness for 0 + one_idx | zero_idx | zero_idx <-- fix witness for 1 + one_idx | one_idx | one_idx <-- ensure nonzero selectors... TODO(Cody): redundant now + v_1 | v_5 | v_9 + v_2 | v_6 | v_10 + v_3 | v_7 | v_11 + v_4 | v_8 | v_12 + + */ + + proving_key = initialize_proving_key(circuit_constructor, &crs_factory, 0, 2, ComposerType::STANDARD); + + // construct_selector_polynomials(circuit_constructor, proving_key.get()); + } +}; + +TEST_F(PermutationHelperTests, ComputeWireCopyCycles) +{ + // TODO(#425) Flesh out these tests + compute_wire_copy_cycles(circuit_constructor); +} + +TEST_F(PermutationHelperTests, ComputePermutationMapping) +{ + // TODO(#425) Flesh out these tests + compute_permutation_mapping(circuit_constructor, proving_key.get()); +} + +TEST_F(PermutationHelperTests, ComputeHonkStyleSigmaLagrangePolynomialsFromMapping) +{ + // TODO(#425) Flesh out these tests + auto mapping = compute_permutation_mapping(circuit_constructor, proving_key.get()); + compute_honk_style_permutation_lagrange_polynomials_from_mapping( + proving_key->get_sigma_polynomials(), mapping.sigmas, proving_key.get()); +} + +TEST_F(PermutationHelperTests, ComputeStandardAuxPolynomials) +{ + // TODO(#425) Flesh out these tests + compute_standard_honk_id_polynomials(proving_key); + compute_standard_honk_sigma_permutations(circuit_constructor, proving_key.get()); + compute_first_and_last_lagrange_polynomials(proving_key); +} + +} // namespace proof_system::test_composer_lib diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp index e69de29bb2d..047102b599b 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp @@ -0,0 +1,250 @@ +/** + * @file flavor.hpp + * @brief Base class templates for structures that contain data parameterized by the fundamental polynomials of a Honk + * variant (a "flavor"). + * + * @details #Motivation + * We choose the framework set out in these classes for several reasons. + * + * For one, it allows for a large amount of the information of a Honk flavor to be read at a glance in a single file. + * + * The primary motivation, however, is to reduce the sort loose of coupling that is a significant source of complexity + * in the original plonk code. There, we find many similarly-named entities defined in many different places (to name + * some: selector_properties; FooSelectors; PolynomialIndex; the labels given to the polynomial store; the commitment + * label; inconsistent terminology and notation around these), and it can be difficult to discover or remember the + * relationships between these. We aim for a more uniform treatment, to enfore identical and informative naming, and to + * prevent the developer having to think very much about the ordering of protocol entities in disparate places. + * + * Another motivation is iterate on the polynomial manifest of plonk, which is nice in its compatness, but which feels + * needlessly manual and low-level. In the past, this contained even more boolean parameters, making it quite hard to + * parse. A typical construction is to loop over the polynomial manifest by extracting a globally-defined + * "FOO_MANIFEST_SIZE" (the use of "manifest" here is distinct from the manifests in the transcript) to loop + * over a C-style array, and then manually parsing the various tags of different types in the manifest entries. We + * greatly enrich this structure by using basic C++ OOP functionality. Rather than recording the polynomial source in an + * enum, we group polynomial handles using getter functions in our new class. We get code that is more compact, + * more legible, and which is safer because it admits ranged `for` loops. + * + * Another motivation is proper and clear specification of Honk variants. The flavors are meant to be explicit and + * easily comparable. In plonk, the various settings template parameters and objects like the ComposerType enum became + * overloaded in time, and continue to be a point of accumulation for tech debt. We aim to remedy some of this by + * putting proving system information in the flavor, and circuit construction information in the arithmetization (or + * larger circuit constructor class). + * + * @details #Data model + * All of the flavor classes derive from a single Entities_ template, which simply wraps a std::array (we would + * inherit, but this is unsafe as std::array has a non-virtual destructor). The developer should think of every flavor + * class as being: + * - A std::array instance called _data. + * - An informative name for each entry of _data that is fixed at compile time. + * - Some classic metadata like we'd see in plonk (e.g., a circuit size, a reference string, an evaluation domain). + * - A collection of getters that record subsets of the array that are of interest in the Honk variant. + * + * Each getter returns a container of HandleType's, where a HandleType is a value type that is inexpensive to create and + * that lets one view and mutate a DataType instance. The primary example here is that std::span is the handle type + * chosen for barrtenberg::Polynomial. + * + * @details #Some Notes + * + * @note It would be ideal to codify more structure in these base class template and to have it imposed on the actual + * flavors, but our inheritance model is complicated as it is, and we saw no reasonable way to fix this. + * + * @note One asymmetry to note is in the use of the term "key". It is worthwhile to distinguish betwen prover/verifier + * circuit data, and "keys" that consist of such data augmented with witness data (whether, raw, blinded, or polynomial + * commitments). Currently the proving key contains witness data, while the verification key does not. + * TODO(Cody): It would be nice to resolve this but it's not essential. + * + * @note The VerifierCommitments classes are not 'tight' in the sense that that the underlying array contains(a few) + * empty slots. This is a conscious choice to limit complexity. Note that there is very little memory cost here since + * the DataType size in that case is small. + * + * @todo TODO(#394): Folded polynomials should use polynomial class. + * @todo TODO(#395): Getters should return arrays? + * @todo TODO(#396): Access specifiers? + * @todo TODO(#397): Use more handle types? + * @todo TODO(#398): Selectors should come from arithmetization. + */ + +#pragma once +#include +#include +#include +#include "barretenberg/srs/reference_string/reference_string.hpp" +#include "barretenberg/polynomials/evaluation_domain.hpp" +#include "barretenberg/proof_system/types/composer_type.hpp" + +namespace proof_system::honk::flavor { + +/** + * @brief Base data class template, a wrapper for std::array, from which every flavor class ultimately derives. + * + * @tparam T The underlying data type stored in the array + * @tparam HandleType The type that will be used to + * @tparam NUM_ENTITIES The size of the underlying array. + */ +template class Entities_ { + public: + using ArrayType = std::array; + ArrayType _data; + + virtual ~Entities_() = default; + + DataType& operator[](size_t idx) { return _data[idx]; }; + typename ArrayType::iterator begin() { return _data.begin(); }; + typename ArrayType::iterator end() { return _data.end(); }; + + constexpr size_t size() { return NUM_ENTITIES; }; +}; + +/** + * @brief Base class template containing circuit-specifying data. + * + */ +template +class PrecomputedEntities_ : public Entities_ { + public: + using DataType = DataType_; + + size_t circuit_size; + size_t log_circuit_size; + size_t num_public_inputs; + ComposerType composer_type; // TODO(#392) + + virtual std::vector get_selectors() = 0; + virtual std::vector get_sigma_polynomials() = 0; + virtual std::vector get_id_polynomials() = 0; +}; + +/** + * @brief Base class template containing witness (wires and derived witnesses). + * @details Shifts are not included here since they do not occupy their own memory. + */ +template +class WitnessEntities_ : public Entities_ { + public: + virtual std::vector get_wires() = 0; +}; + +/** + * @brief Base proving key class. + * + * @tparam PrecomputedEntities An instance of PrecomputedEntities_ with polynomial data type and span handle type. + * @tparam FF The scalar field on which we will encode our polynomial data. When instantiating, this may be extractable + * from the other template paramter. + */ +template +class ProvingKey_ : public PrecomputedPolynomials, public WitnessPolynomials { + public: + using Polynomial = typename PrecomputedPolynomials::DataType; + using FF = typename Polynomial::FF; + + typename PrecomputedPolynomials::ArrayType& _precomputed_polynomials = PrecomputedPolynomials::_data; + typename WitnessPolynomials::ArrayType& _witness_polynomials = WitnessPolynomials::_data; + + bool contains_recursive_proof; + std::vector recursive_proof_public_input_indices; + std::shared_ptr crs; + barretenberg::EvaluationDomain evaluation_domain; + + ProvingKey_() = default; + ProvingKey_(const size_t circuit_size, + const size_t num_public_inputs, + std::shared_ptr const& crs, + ComposerType composer_type) + { + this->crs = crs; + this->evaluation_domain = barretenberg::EvaluationDomain(circuit_size, circuit_size); + PrecomputedPolynomials::circuit_size = circuit_size; + this->log_circuit_size = numeric::get_msb(circuit_size); + this->num_public_inputs = num_public_inputs; + this->composer_type = composer_type; + // Allocate memory for precomputed polynomials + for (auto& poly : _precomputed_polynomials) { + poly = Polynomial(circuit_size); + } + // Allocate memory for witness polynomials + for (auto& poly : _witness_polynomials) { + poly = Polynomial(circuit_size); + } + }; +}; + +/** + * @brief Base verification key class. + * + * @tparam PrecomputedEntities An instance of PrecomputedEntities_ with affine_element data type and handle type. + */ +template class VerificationKey_ : public PrecomputedCommitments { + public: + std::shared_ptr vrs; + + VerificationKey_() = default; + VerificationKey_(const size_t circuit_size, + const size_t num_public_inputs, + std::shared_ptr const& vrs, + ComposerType composer_type) + { + this->circuit_size = circuit_size; + this->log_circuit_size = numeric::get_msb(circuit_size); + this->num_public_inputs = num_public_inputs; + this->vrs = vrs; + this->composer_type = composer_type; + }; +}; + +/** + * @brief Base class containing all entities (or handles on these) in one place. + * + * @tparam PrecomputedEntities An instance of PrecomputedEntities_ with affine_element data type and handle type. + */ +template +class AllEntities_ : public Entities_ { + public: + virtual std::vector get_wires() = 0; + virtual std::vector get_unshifted() = 0; + virtual std::vector get_to_be_shifted() = 0; + virtual std::vector get_shifted() = 0; + + // Because of how Gemini is written, is importat to put the polynomials out in this order. + std::vector get_unshifted_then_shifted() + { + std::vector result{ get_unshifted() }; + std::vector shifted{ get_shifted() }; + result.insert(result.end(), shifted.begin(), shifted.end()); + return result; + }; +}; + +} // namespace proof_system::honk::flavor + +// Forward declare honk flavors +namespace proof_system::honk::flavor { +class Standard; +class Ultra; +} // namespace proof_system::honk::flavor + +// Forward declare plonk flavors +namespace proof_system::plonk::flavor { +class Standard; +class Turbo; +class Ultra; +} // namespace proof_system::plonk::flavor + +// Establish concepts for testing flavor attributes +namespace proof_system { +/** + * @brief Test whether a type T lies in a list of types ...U. + * + * @tparam T The type being tested + * @tparam U A parameter pack of types being checked against T. + */ +// clang-format off +template +concept IsAnyOf = (std::same_as || ...); + +template +concept IsPlonkFlavor = IsAnyOf; + +template +concept IsHonkFlavor = IsAnyOf; +// clang-format on +} // namespace proof_system diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.test.cpp deleted file mode 100644 index 06accb92651..00000000000 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.test.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include "flavor.hpp" - -#include - -namespace test_flavor { - -// // TODO(Cody) This seems like a good idea, but I'm not sure why. -// TEST(Flavor, StandardArithmetization){ -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::W_L, 0); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::W_R, 1); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::W_O, 2); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Z_PERM, 3); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Z_PERM_SHIFT, 4); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_M, 5); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_L, 6); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_R, 7); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_O, 8); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::Q_C, 9); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::SIGMA_1, 10); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::SIGMA_2, 11); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::SIGMA_3, 12); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::ID_1, 13); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::ID_2, 14); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::ID_3, 15); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::LAGRANGE_FIRST, 16); -// EXPECT_EQ(StandardArithmetization::MULTIVARIATE::COUNT, 17); - -// } - -} // namespace test_flavor diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/types/composer_type.hpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/types/composer_type.hpp index 295967e1360..bc744f976fa 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/types/composer_type.hpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/proof_system/types/composer_type.hpp @@ -1,6 +1,6 @@ #pragma once namespace proof_system { -// TODO(Cody) Get rid of this. +// TODO(#392) This enum has been overloaded. Perhaps its different responsibilities have been split up. enum ComposerType { STANDARD, TURBO, PLOOKUP, STANDARD_HONK }; } // namespace proof_system \ No newline at end of file diff --git a/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp b/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp index 7d3fa5e5761..b8280e3298c 100644 --- a/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp +++ b/circuits/cpp/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp @@ -195,8 +195,9 @@ template class stdlib_field : public testing::Test { uint64_t expected = fidget(composer); auto prover = composer.create_prover(); + // TODO(Cody): This is a hack and the test should be rewritten. if constexpr (Composer::type == ComposerType::STANDARD_HONK) { - EXPECT_EQ(prover.wire_polynomials[2][20], fr(expected)); + EXPECT_EQ(prover.key->w_o[20], fr(expected)); } else { EXPECT_EQ(prover.key->polynomial_store.get("w_3_lagrange")[18], fr(expected)); } @@ -291,7 +292,7 @@ template class stdlib_field : public testing::Test { auto prover = composer.create_prover(); if constexpr (Composer::type == ComposerType::STANDARD_HONK) { - EXPECT_EQ(prover.wire_polynomials[2][19], fr(4181)); + EXPECT_EQ(prover.key->w_o[19], fr(4181)); } else { EXPECT_EQ(prover.key->polynomial_store.get("w_3_lagrange")[17], fr(4181)); }