diff --git a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/CMakeLists.txt index d9a995e7cfb8..3234668be52c 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/CMakeLists.txt @@ -1,6 +1,5 @@ # Each source represents a separate benchmark suite set(BENCHMARK_SOURCES -standard_honk.bench.cpp standard_plonk.bench.cpp ultra_honk.bench.cpp ultra_plonk.bench.cpp @@ -14,7 +13,7 @@ set(LINKED_LIBRARIES benchmark::benchmark ) -# Add executable and custom target for each suite, e.g. standard_honk_bench +# Add executable and custom target for each suite, e.g. ultra_honk_bench foreach(BENCHMARK_SOURCE ${BENCHMARK_SOURCES}) get_filename_component(BENCHMARK_NAME ${BENCHMARK_SOURCE} NAME_WE) # extract name without extension add_executable(${BENCHMARK_NAME}_bench main.bench.cpp ${BENCHMARK_SOURCE} benchmark_utilities.hpp) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp index e2727fb5f17f..21e3513fd84c 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp @@ -1,6 +1,5 @@ #include -#include "barretenberg/honk/composer/standard_composer.hpp" #include "barretenberg/honk/composer/ultra_composer.hpp" #include "barretenberg/proof_system/types/circuit_type.hpp" #include "barretenberg/stdlib/encryption/ecdsa/ecdsa.hpp" @@ -195,20 +194,11 @@ void construct_proof_with_specified_num_gates(State& state, test_circuit_function(builder, num_gates); auto composer = Composer(); - if constexpr (proof_system::IsAnyOf) { - auto instance = composer.create_instance(builder); - auto ext_prover = composer.create_prover(instance); - state.ResumeTiming(); - - // Construct proof - auto proof = ext_prover.construct_proof(); - } else { - auto ext_prover = composer.create_prover(builder); - state.ResumeTiming(); + auto ext_prover = composer.create_prover(builder); + state.ResumeTiming(); - // Construct proof - auto proof = ext_prover.construct_proof(); - } + // Construct proof + auto proof = ext_prover.construct_proof(); } } diff --git a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/compare_honk_to_plonk_standard.sh b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/compare_honk_to_plonk_standard.sh deleted file mode 100755 index ad7ecc1f22d0..000000000000 --- a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/compare_honk_to_plonk_standard.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -# This script is used to compare the results of honk_bench between baseline (master) and -# the branch from which the script is run. Simply check out the branch of interest, ensure -# it is up to date with local master, and run the script. - -echo -e '\nComparing Standard Plonk/Honk benchmarks.' -# Set some directories -BASE_DIR="$HOME/barretenberg/cpp" -BUILD_DIR="$BASE_DIR/build-bench" -BENCH_RESULTS_DIR="$BASE_DIR/tmp_bench_results" -BENCH_TOOLS_DIR="$BUILD_DIR/_deps/benchmark-src/tools" - -# Install requirements (numpy + scipy) for comparison script if necessary. -# Note: By default, installation will occur in $HOME/.local/bin. -pip3 install --user -r $BUILD_DIR/_deps/benchmark-src/requirements.txt - -# Create temporary directory for honk_bench results (json) -cd $BASE_DIR -mkdir $BENCH_RESULTS_DIR - -# -echo -e '\nBuilding and running Standard benchmarks..' -# rm -rf $BUILD_DIR -cmake --preset bench > /dev/null && cmake --build --preset bench --target standard_plonk_bench -cd build-bench -PLONK_BENCH_RESULTS="$BENCH_RESULTS_DIR/plonk_bench.json" -./bin/standard_plonk_bench --benchmark_format=json > $PLONK_BENCH_RESULTS - -cd .. -cmake --preset bench > /dev/null && cmake --build --preset bench --target standard_honk_bench -cd build-bench -HONK_BENCH_RESULTS="$BENCH_RESULTS_DIR/honk_bench.json" -./bin/standard_honk_bench --benchmark_format=json > $HONK_BENCH_RESULTS - -# Call compare.py on the results (json) to get high level statistics. -# See docs at https://github.com/google/benchmark/blob/main/docs/tools.md for more details. -$BENCH_TOOLS_DIR/compare.py benchmarks $PLONK_BENCH_RESULTS $HONK_BENCH_RESULTS - -# # Delete the temporary results directory and its contents -rm -r $BENCH_RESULTS_DIR \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/honk.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/honk.bench.cpp deleted file mode 100644 index 87b8c5a2845a..000000000000 --- a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/honk.bench.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "barretenberg/honk/composer/standard_composer.hpp" -#include "barretenberg/stdlib/primitives/field/field.hpp" -#include "barretenberg/stdlib/primitives/witness/witness.hpp" -#include -#include - -using namespace benchmark; -using namespace proof_system::plonk::stdlib; - -namespace standard_honk_bench { - -using Builder = proof_system::StandardCircuitBuilder; -using Composer = proof_system::honk::StandardComposer; - -constexpr size_t MIN_LOG_NUM_GATES = 16; -constexpr size_t MAX_LOG_NUM_GATES = 16; -// To get good statistics, number of Repetitions must be sufficient. ~30 Repetitions gives good results. -constexpr size_t NUM_REPETITIONS = 5; - -void generate_test_circuit(auto& builder, size_t num_gates) -{ - barretenberg::srs::init_crs_factory("../srs_db/ignition"); - field_t a(witness_t(&builder, barretenberg::fr::random_element())); - field_t b(witness_t(&builder, barretenberg::fr::random_element())); - field_t c(&builder); - for (size_t i = 0; i < (num_gates / 4) - 4; ++i) { - c = a + b; - c = a * c; - a = b * b; - b = c * c; - } -} - -/** - * @brief Benchmark: Creation of a Standard Honk prover - */ -void create_prover_standard(State& state) noexcept -{ - for (auto _ : state) { - state.PauseTiming(); - auto num_gates = 1 << (size_t)state.range(0); - auto builder = Builder(static_cast(num_gates)); - generate_test_circuit(builder, static_cast(num_gates)); - state.ResumeTiming(); - - auto composer = Composer(); - composer.create_prover(builder); - } -} -BENCHMARK(create_prover_standard)->DenseRange(MIN_LOG_NUM_GATES, MAX_LOG_NUM_GATES, 1)->Repetitions(NUM_REPETITIONS); - -/** - * @brief Benchmark: Construction of a Standard Honk proof - */ -void construct_proof_standard(State& state) noexcept -{ - auto num_gates = 1 << (size_t)state.range(0); - for (auto _ : state) { - state.PauseTiming(); - auto builder = Builder(static_cast(num_gates)); - generate_test_circuit(builder, static_cast(num_gates)); - - auto composer = Composer(); - auto ext_prover = composer.create_prover(builder); - state.ResumeTiming(); - - auto proof = ext_prover.construct_proof(); - } - state.SetComplexityN(num_gates); // Set up for computation of constant C where prover ~ C*N -} -BENCHMARK(construct_proof_standard) - ->DenseRange(MIN_LOG_NUM_GATES, MAX_LOG_NUM_GATES, 1) - ->Repetitions(NUM_REPETITIONS) - ->Complexity(oN); - -/** - * @brief Benchmark: Creation of a Standard Honk verifier - */ -void create_verifier_standard(State& state) noexcept -{ - for (auto _ : state) { - state.PauseTiming(); - auto num_gates = 1 << (size_t)state.range(0); - auto builder = Builder(static_cast(num_gates)); - generate_test_circuit(builder, static_cast(num_gates)); - state.ResumeTiming(); - - auto composer = Composer(); - composer.create_verifier(builder); - } -} -// BENCHMARK(create_verifier_standard)->DenseRange(MIN_LOG_NUM_GATES, MAX_LOG_NUM_GATES, -// 1)->Repetitions(NUM_REPETITIONS); - -/** - * @brief Benchmark: Verification of a Standard Honk proof - */ -void verify_proof_standard(State& state) noexcept -{ - for (auto _ : state) { - state.PauseTiming(); - auto num_gates = (size_t)state.range(0); - auto builder = Builder(static_cast(num_gates)); - generate_test_circuit(builder, static_cast(num_gates)); - - auto composer = Composer(); - auto prover = composer.create_prover(builder); - auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(builder); - state.ResumeTiming(); - - verifier.verify_proof(proof); - } -} -// BENCHMARK(verify_proof_standard)->DenseRange(MIN_LOG_NUM_GATES, MAX_LOG_NUM_GATES, 1)->Iterations(1); -} // namespace standard_honk_bench \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/standard_honk.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/standard_honk.bench.cpp deleted file mode 100644 index 42fed512ffc7..000000000000 --- a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/standard_honk.bench.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "barretenberg/benchmark/honk_bench/benchmark_utilities.hpp" -#include "barretenberg/honk/composer/standard_composer.hpp" -#include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" - -using namespace benchmark; - -namespace standard_honk_bench { - -using StandardBuilder = proof_system::StandardCircuitBuilder; -using StandardHonk = proof_system::honk::StandardComposer; - -// Log number of gates for test circuit -constexpr size_t MIN_LOG_NUM_GATES = bench_utils::BenchParams::MIN_LOG_NUM_GATES; -constexpr size_t MAX_LOG_NUM_GATES = bench_utils::BenchParams::MAX_LOG_NUM_GATES; -// Number of times to repeat each benchmark -constexpr size_t NUM_REPETITIONS = bench_utils::BenchParams::NUM_REPETITIONS; - -/** - * @brief Benchmark: Construction of a Standard proof for a circuit determined by the provided circuit function - */ -void construct_proof_standard(State& state, void (*test_circuit_function)(StandardBuilder&, size_t)) noexcept -{ - bench_utils::construct_proof_with_specified_num_gates(state, test_circuit_function); -} - -BENCHMARK_CAPTURE(construct_proof_standard, - arithmetic, - &bench_utils::generate_basic_arithmetic_circuit) - ->DenseRange(MIN_LOG_NUM_GATES, MAX_LOG_NUM_GATES) - ->Repetitions(NUM_REPETITIONS) - ->Unit(::benchmark::kSecond); - -} // namespace standard_honk_bench \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/CMakeLists.txt b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/CMakeLists.txt index 7fd8082895c0..57f0eea70ee1 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/CMakeLists.txt +++ b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/CMakeLists.txt @@ -10,7 +10,7 @@ set(LINKED_LIBRARIES benchmark::benchmark ) -# Add executable and custom target for each suite, e.g. standard_honk_bench +# Add executable and custom target for each suite, e.g. ultra_honk_bench foreach(BENCHMARK_SOURCE ${BENCHMARK_SOURCES}) get_filename_component(BENCHMARK_NAME ${BENCHMARK_SOURCE} NAME_WE) # extract name without extension add_executable(${BENCHMARK_NAME}_bench main.bench.cpp ${BENCHMARK_SOURCE}) diff --git a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp index 362d5b15b6ca..df0be6fe25a2 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/relations_bench/relations.bench.cpp @@ -1,7 +1,5 @@ #include "barretenberg/honk/flavor/goblin_ultra.hpp" -#include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/honk/flavor/ultra.hpp" -#include "barretenberg/proof_system/relations/arithmetic_relation.hpp" #include "barretenberg/proof_system/relations/auxiliary_relation.hpp" #include "barretenberg/proof_system/relations/ecc_op_queue_relation.hpp" #include "barretenberg/proof_system/relations/elliptic_relation.hpp" @@ -47,12 +45,6 @@ template void execute_relation(::benchmark: } } -void arithmetic_relation(::benchmark::State& state) noexcept -{ - execute_relation>(state); -} -BENCHMARK(arithmetic_relation); - void auxiliary_relation(::benchmark::State& state) noexcept { execute_relation>(state); @@ -83,11 +75,11 @@ void lookup_relation(::benchmark::State& state) noexcept } BENCHMARK(lookup_relation); -void permutation_relation(::benchmark::State& state) noexcept +void ultra_permutation_relation(::benchmark::State& state) noexcept { - execute_relation>(state); + execute_relation>(state); } -BENCHMARK(permutation_relation); +BENCHMARK(ultra_permutation_relation); void ultra_arithmetic_relation(::benchmark::State& state) noexcept { diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/eccvm_composer.hpp b/barretenberg/cpp/src/barretenberg/honk/composer/eccvm_composer.hpp index bd72d44bb6ce..93b3b9914618 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/eccvm_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/eccvm_composer.hpp @@ -23,7 +23,7 @@ template class ECCVMComposer_ { std::shared_ptr verification_key; // The crs_factory holds the path to the srs and exposes methods to extract the srs elements - std::shared_ptr> crs_factory_; + std::shared_ptr> crs_factory_; // The commitment key is passed to the prover but also used herein to compute the verfication key commitments std::shared_ptr commitment_key; @@ -42,7 +42,8 @@ template class ECCVMComposer_ { crs_factory_ = barretenberg::srs::get_crs_factory(); }; - explicit ECCVMComposer_(std::shared_ptr> crs_factory) + explicit ECCVMComposer_( + std::shared_ptr> crs_factory) : crs_factory_(std::move(crs_factory)) {} @@ -65,7 +66,7 @@ template class ECCVMComposer_ { ECCVMProver_ create_prover(CircuitConstructor& circuit_constructor); ECCVMVerifier_ create_verifier(CircuitConstructor& circuit_constructor); - void add_table_column_selector_poly_to_proving_key(polynomial& small, const std::string& tag); + void add_table_column_selector_poly_to_proving_key(barretenberg::polynomial& small, const std::string& tag); void compute_commitment_key(size_t circuit_size) { diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/eccvm_composer.test.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/eccvm_composer.test.cpp index 9b4d520b7d3a..5fb5daafb66a 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/eccvm_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/eccvm_composer.test.cpp @@ -4,7 +4,6 @@ #include #include "barretenberg/honk/composer/eccvm_composer.hpp" -#include "barretenberg/honk/proof_system/prover.hpp" #include "barretenberg/honk/sumcheck/sumcheck_round.hpp" #include "barretenberg/honk/utils/grand_product_delta.hpp" #include "barretenberg/numeric/uint256/uint256.hpp" @@ -15,7 +14,7 @@ using namespace proof_system::honk; -namespace test_standard_honk_composer { +namespace test_eccvm_composer { template class ECCVMComposerTests : public ::testing::Test { protected: @@ -103,4 +102,4 @@ TYPED_TEST(ECCVMComposerTests, EqFails) bool verified = verifier.verify_proof(proof); ASSERT_FALSE(verified); } -} // namespace test_standard_honk_composer +} // namespace test_eccvm_composer diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.cpp deleted file mode 100644 index d7d8b55b1e8b..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.cpp +++ /dev/null @@ -1,42 +0,0 @@ -#include "standard_composer.hpp" -#include "barretenberg/numeric/bitop/get_msb.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/srs/factories/crs_factory.hpp" - -#include -#include -#include - -namespace proof_system::honk { - -template -std::shared_ptr> StandardComposer_::create_instance(CircuitBuilder& circuit) -{ - auto instance = std::make_shared(circuit); - instance->commitment_key = compute_commitment_key(instance->proving_key->circuit_size); - return instance; -} - -template -StandardVerifier_ StandardComposer_::create_verifier(std::shared_ptr instance) -{ - auto verification_key = instance->compute_verification_key(); - StandardVerifier_ output_state(verification_key); - auto pcs_verification_key = - std::make_unique(verification_key->circuit_size, crs_factory_); - output_state.pcs_verification_key = std::move(pcs_verification_key); - - return output_state; -} - -template -StandardProver_ StandardComposer_::create_prover(std::shared_ptr instance) -{ - StandardProver_ output_state(instance); - - return output_state; -} - -template class StandardComposer_; -template class StandardComposer_; -} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.hpp b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.hpp deleted file mode 100644 index 6763a4a29d1f..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.hpp +++ /dev/null @@ -1,83 +0,0 @@ -#pragma once - -#include "barretenberg/honk/instance/prover_instance.hpp" -#include "barretenberg/honk/proof_system/prover.hpp" -#include "barretenberg/honk/proof_system/verifier.hpp" -#include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" -#include "barretenberg/proof_system/composer/composer_lib.hpp" -#include "barretenberg/proof_system/composer/permutation_lib.hpp" -#include "barretenberg/srs/factories/file_crs_factory.hpp" -#include - -#include "barretenberg/honk/flavor/standard.hpp" -#include "barretenberg/honk/flavor/standard_grumpkin.hpp" - -namespace proof_system::honk { -template class StandardComposer_ { - public: - using CircuitBuilder = typename Flavor::CircuitBuilder; - using ProvingKey = typename Flavor::ProvingKey; - using VerificationKey = typename Flavor::VerificationKey; - using CommitmentKey = typename Flavor::CommitmentKey; - using Instance = ProverInstance_; - - static constexpr std::string_view NAME_STRING = "StandardHonk"; - static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; - std::shared_ptr proving_key; - std::shared_ptr verification_key; - - // The crs_factory holds the path to the srs and exposes methods to extract the srs elements - std::shared_ptr> crs_factory_; - - // The commitment key is passed to the prover but also used herein to compute the verfication key commitments - std::shared_ptr commitment_key; - ; - - bool computed_witness = false; - // TODO(Luke): use make_shared - // TODO(https://github.com/AztecProtocol/barretenberg/issues/637): design the crs factory better - StandardComposer_() - { - if constexpr (IsGrumpkinFlavor) { - crs_factory_ = barretenberg::srs::get_grumpkin_crs_factory(); - - } else { - crs_factory_ = barretenberg::srs::get_crs_factory(); - } - } - - StandardComposer_(std::shared_ptr> crs_factory) - : crs_factory_(std::move(crs_factory)) - {} - - StandardComposer_(std::unique_ptr>&& crs_factory) - : crs_factory_(std::move(crs_factory)) - {} - StandardComposer_(std::shared_ptr p_key, std::shared_ptr v_key) - : proving_key(std::move(p_key)) - , verification_key(std::move(v_key)) - {} - StandardComposer_(StandardComposer_&& other) noexcept = default; - StandardComposer_(const StandardComposer_& other) = delete; - StandardComposer_& operator=(StandardComposer_&& other) noexcept = default; - StandardComposer_& operator=(const StandardComposer_& other) = delete; - ~StandardComposer_() = default; - - std::shared_ptr create_instance(CircuitBuilder& circuit); - - StandardProver_ create_prover(std::shared_ptr); - StandardVerifier_ create_verifier(std::shared_ptr); - - std::shared_ptr compute_commitment_key(size_t circuit_size) - { - commitment_key = std::make_shared(circuit_size, crs_factory_); - return commitment_key; - }; -}; - -extern template class StandardComposer_; -extern template class StandardComposer_; -// TODO(#532): this pattern is weird; is this not instantiating the templates? -using StandardComposer = StandardComposer_; -using StandardGrumpkinComposer = StandardComposer_; -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.test.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.test.cpp deleted file mode 100644 index 7a5efaede993..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.test.cpp +++ /dev/null @@ -1,448 +0,0 @@ -#include -#include -#include -#include - -#include "barretenberg/honk/composer/standard_composer.hpp" -#include "barretenberg/honk/proof_system/prover.hpp" -#include "barretenberg/honk/sumcheck/sumcheck_round.hpp" -#include "barretenberg/honk/utils/grand_product_delta.hpp" -#include "barretenberg/numeric/uint256/uint256.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" -#include "barretenberg/proof_system/relations/permutation_relation.hpp" -#include "barretenberg/proof_system/relations/relation_parameters.hpp" - -using namespace proof_system::honk; - -#define TYPE_ALIASES \ - using Flavor = TypeParam; \ - using FF = typename Flavor::FF; \ - using CircuitBuilder = proof_system::StandardCircuitBuilder_; \ - using Composer = StandardComposer_; - -namespace test_standard_honk_composer { - -template class StandardHonkComposerTests : public ::testing::Test { - protected: - // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. - virtual void SetUp() - { - if constexpr (proof_system::IsGrumpkinFlavor) { - barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } else { - barretenberg::srs::init_crs_factory("../srs_db/ignition"); - } - }; -}; - -using FlavorTypes = ::testing::Types; -TYPED_TEST_SUITE(StandardHonkComposerTests, FlavorTypes); - -/** - * @brief The goal of this test is to check that the sigma permutation vectors for honk are generated correctly. - * - * @details Specifically: - * 1) That they are indeed a permutation of all initial indices - * 2) That if the permutation argument is computed with witness values, the values from the identity permutation and - * sigma permutation are equal - */ -TYPED_TEST(StandardHonkComposerTests, SigmaIDCorrectness) -{ - TYPE_ALIASES - auto test_permutation = [](CircuitBuilder& builder, Composer& composer) { - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto proving_key = instance->proving_key; - - const auto n = proving_key->circuit_size; - - auto public_inputs = builder.get_public_inputs(); - auto num_public_inputs = public_inputs.size(); - auto num_gates = builder.get_num_gates(); - - // Using the same random beta and gamma as in the permutation argument - FF beta = FF::random_element(); - FF gamma = FF::random_element(); - - FF left = FF::one(); - FF right = FF::one(); - - // Let's check that indices are the same and nothing is lost, first - size_t wire_idx = 0; - for (auto& sigma_polynomial : proving_key->get_sigma_polynomials()) { - for (size_t i = 0; i < n; ++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 (wire_idx == 0) { - for (size_t i = 0; i < num_public_inputs; ++i) { - EXPECT_EQ(sigma_polynomial[i], -FF(i + 1)); - left *= (gamma - (i + 1)); - right *= (gamma + (n + i)); - } - } - ++wire_idx; - } - - EXPECT_EQ(left, right); - - left = FF::one(); - right = FF::one(); - - 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 < Composer::NUM_WIRES; ++j) { - std::string index = std::to_string(j + 1); - 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) { - const auto current_witness = witness_polynomial[i]; - left *= current_witness + beta * id_polynomial[i] + gamma; - right *= current_witness + beta * permutation_polynomial[i] + gamma; - } - // check that the first rows are correctly set to handle public inputs. - for (size_t i = 0; i < num_public_inputs; ++i) { - if ((j == 0) || (j == 1)) { - EXPECT_EQ(witness_polynomial[i], public_inputs[i]); - } else { - EXPECT_EQ(witness_polynomial[i], 0); - } - } - // Check that the last rows are all 0 - for (size_t i = num_public_inputs + num_gates; i < n; ++i) { - EXPECT_EQ(witness_polynomial[i], 0); - } - } - - // test correctness of the public input delta - auto delta = proof_system::honk::compute_public_input_delta(public_inputs, beta, gamma, n); - EXPECT_EQ(left / right, delta); - - for (size_t i = 0; i < num_public_inputs; ++i) { - left *= public_inputs[i] - beta * (i + 1) + gamma; - right *= public_inputs[i] + beta * (n + i) + gamma; - } - EXPECT_EQ(left, right); - }; - - auto builder = CircuitBuilder(); - FF a = FF::one(); - uint32_t a_idx = builder.add_variable(a); - FF b = FF::one(); - FF c = a + b; - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - FF d = a + c; - uint32_t d_idx = builder.add_public_variable(d); - - uint32_t e_idx = builder.put_constant_variable(d); - builder.assert_equal(e_idx, d_idx, ""); - - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ b_idx, a_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - for (size_t i = 0; i < 30; ++i) { - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - } - - auto composer = Composer(); - test_permutation(builder, composer); -} - -/** - * @brief Check the correctness of lagrange polynomials generated during proving key computation - * - */ -TYPED_TEST(StandardHonkComposerTests, LagrangeCorrectness) -{ - TYPE_ALIASES - using Polynomial = typename Flavor::Polynomial; - // Create a dummy circuit with a few gates - auto builder = CircuitBuilder(); - FF a = FF::one(); - uint32_t a_idx = builder.add_variable(a); - FF b = FF::one(); - FF c = a + b; - FF d = a + c; - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - for (size_t i = 0; i < 16; i++) { - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); - } - - // Generate proving key - auto composer = Composer(); - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto proving_key = instance->proving_key; - - // Generate a random polynomial - Polynomial random_polynomial = Polynomial(proving_key->circuit_size); - for (size_t i = 0; i < proving_key->circuit_size; i++) { - random_polynomial[i] = FF::random_element(); - } - // Compute inner product of random polynomial and the first lagrange polynomial - - Polynomial first_lagrange_polynomial = proving_key->lagrange_first; - FF first_product(0); - for (size_t i = 0; i < proving_key->circuit_size; i++) { - first_product += random_polynomial[i] * first_lagrange_polynomial[i]; - } - EXPECT_EQ(first_product, random_polynomial[0]); - - // Compute inner product of random polynomial and the last lagrange polynomial - auto last_lagrange_polynomial = proving_key->lagrange_last; - FF last_product(0); - for (size_t i = 0; i < proving_key->circuit_size; i++) { - last_product += random_polynomial[i] * last_lagrange_polynomial[i]; - } - EXPECT_EQ(last_product, random_polynomial[proving_key->circuit_size - 1]); -} - -/** - * @brief Test that the assert_equal method in composer is working as intended - * - * @details We show equality of witness values through permutation arguments, so the assert_equal method changes the - * underlying variable structure. If we bind two real variables through it, we expect their wire copy cycles to be - * merged. - * In this test we create two almost identical circuits. They differ because one - */ -TYPED_TEST(StandardHonkComposerTests, AssertEquals) -{ - TYPE_ALIASES - - /** - * @brief A function that creates a simple circuit with repeated gates, leading to large permutation cycles - * - */ - auto create_simple_circuit = [](auto& builder) { - FF a = FF::one(); - uint32_t a_idx = builder.add_variable(a); - FF b = FF::one(); - FF c = a + b; - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - - for (size_t i = 0; i < 10; i++) { - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ b_idx, a_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - } - return std::make_tuple(a_idx, b_idx); - }; - /** - * @brief A function that computes the largest cycle from the sigma permutation generated by the composer - * - */ - auto get_maximum_cycle = [](auto& builder, auto& composer) { - // Compute the proving key for sigma polynomials - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto proving_key = instance->proving_key; - - 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; - - std::vector visited_indices; - - visited_indices.resize(permutation_length, false); - - for (size_t i = 0; i < permutation_length;) { - // Jump to first unvisited member in the cycle - // We check that i is limited by permutation_length - while (visited_indices[i] && (i < permutation_length)) { - i++; - } - if (i >= permutation_length) { - break; - } - auto starting_element = i; - auto next_element_big = - static_cast(sigma_polynomials[i / proving_key->circuit_size][i % proving_key->circuit_size]); - EXPECT_LE(next_element_big, uint256_t(UINT32_MAX)); - auto next_element = static_cast(next_element_big.data[0]); - size_t cycle_length = 1; - visited_indices[i] = true; - - // Jump through the cycle untill we reach the start or the permutation length exceeds the possible - // maximum - while ((next_element != starting_element) && cycle_length < (permutation_length + 1)) { - // Update cycle length and visited index infromation - cycle_length++; - visited_indices[next_element] = true; - // Get next index - next_element_big = static_cast(sigma_polynomials[next_element / proving_key->circuit_size] - [next_element % proving_key->circuit_size]); - EXPECT_LE(next_element_big, uint256_t(UINT32_MAX)); - next_element = static_cast(next_element_big.data[0]); - } - // If cycle_length is larger than permutation length, then instead of just a cycle we have a runway,too, - // which is incorrect - EXPECT_LE(cycle_length, permutation_length); - - // Update the maximum cycle - if (cycle_length > maximum_cycle) { - maximum_cycle = cycle_length; - } - } - return maximum_cycle; - }; - - // Get 2 circuits - auto builder_no_assert_equal = CircuitBuilder(); - auto builder_with_assert_equal = CircuitBuilder(); - - // Construct circuits - create_simple_circuit(builder_no_assert_equal); - auto assert_eq_params = create_simple_circuit(builder_with_assert_equal); - - // Use assert_equal on one of them - builder_with_assert_equal.assert_equal(std::get<0>(assert_eq_params), - std::get<1>(assert_eq_params), - "Equality asssertion in standard honk composer test"); - - // Check that the maximum cycle in the one, where we used assert_equal, is twice as long - auto composer_no_assert_equal = Composer(); - auto composer_with_assert_equal = Composer(); - EXPECT_EQ(get_maximum_cycle(builder_with_assert_equal, composer_with_assert_equal), - get_maximum_cycle(builder_no_assert_equal, composer_no_assert_equal) * 2); -} - -TYPED_TEST(StandardHonkComposerTests, VerificationKeyCreation) -{ - TYPE_ALIASES - - // Create a composer and a dummy circuit with a few gates - auto builder = CircuitBuilder(); - FF a = FF::one(); - uint32_t a_idx = builder.add_variable(a); - FF b = FF::one(); - FF c = a + b; - FF d = a + c; - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - for (size_t i = 0; i < 16; i++) { - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); - } - - auto composer = Composer(); - auto instance = composer.create_instance(builder); - auto verification_key = instance->compute_verification_key(); - // 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->size(), builder.selectors.size() + composer.NUM_WIRES * 2 + 2); -} - -TYPED_TEST(StandardHonkComposerTests, BaseCase) -{ - TYPE_ALIASES - auto builder = CircuitBuilder(); - FF a = 1; - builder.add_variable(a); - - auto composer = Composer(); - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(instance); - bool verified = verifier.verify_proof(proof); - ASSERT_TRUE(verified); -} - -TYPED_TEST(StandardHonkComposerTests, TwoGates) -{ - TYPE_ALIASES - auto run_test = [](bool expect_verified) { - if constexpr (proof_system::IsGrumpkinFlavor) { - barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } - auto builder = CircuitBuilder(); - // 1 + 1 - 2 = 0 - uint32_t w_l_1_idx; - if (expect_verified) { - w_l_1_idx = builder.add_variable(1); - } else { - w_l_1_idx = builder.add_variable(0); - } - uint32_t w_r_1_idx = builder.add_variable(1); - uint32_t w_o_1_idx = builder.add_variable(2); - builder.create_add_gate({ w_l_1_idx, w_r_1_idx, w_o_1_idx, 1, 1, -1, 0 }); - - // 2 * 2 - 4 = 0 - uint32_t w_l_2_idx = builder.add_variable(2); - uint32_t w_r_2_idx = builder.add_variable(2); - uint32_t w_o_2_idx = builder.add_variable(4); - builder.create_mul_gate({ w_l_2_idx, w_r_2_idx, w_o_2_idx, 1, -1, 0 }); - - auto composer = Composer(); - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto proof = prover.construct_proof(); - - auto verifier = composer.create_verifier(instance); - bool verified = verifier.verify_proof(proof); - - EXPECT_EQ(verified, expect_verified); - }; - - run_test(/* expect_verified=*/true); - run_test(/* expect_verified=*/false); -} - -TYPED_TEST(StandardHonkComposerTests, SumcheckEvaluations) -{ - TYPE_ALIASES - auto run_test = [](bool expected_result) { - if constexpr (proof_system::IsGrumpkinFlavor) { - barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } else { - barretenberg::srs::init_crs_factory("../srs_db/ignition"); - } - auto builder = CircuitBuilder(); - FF a = FF::one(); - // Construct a small but non-trivial circuit - uint32_t a_idx = builder.add_public_variable(a); - FF b = FF::one(); - FF c = a + b; - FF d = a + c; - - if (expected_result == false) { - d += 1; - }; - - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - for (size_t i = 0; i < 4; i++) { - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); - } - - auto composer = Composer(); - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(instance); - 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/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp b/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp index 6a227e33f459..01508f4fb70a 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/flavor.test.cpp @@ -1,4 +1,4 @@ -#include "barretenberg/honk/flavor/standard.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" #include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" #include @@ -8,9 +8,9 @@ #pragma GCC diagnostic ignored "-Wunused-variable" namespace proof_system::test_flavor { -TEST(Flavor, StandardGetters) +TEST(Flavor, Getters) { - using Flavor = proof_system::honk::flavor::Standard; + using Flavor = proof_system::honk::flavor::Ultra; using FF = Flavor::FF; using ProvingKey = typename Flavor::ProvingKey; @@ -42,7 +42,7 @@ TEST(Flavor, StandardGetters) // 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"); + EXPECT_EQ(commitment_labels.w_r, "W_R"); auto get_test_polynomial = [](size_t& idx) { Flavor::Polynomial poly(4); @@ -56,6 +56,7 @@ TEST(Flavor, StandardGetters) auto w_l = get_test_polynomial(idx); auto w_r = get_test_polynomial(idx); auto w_o = get_test_polynomial(idx); + auto w_4 = 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); @@ -75,6 +76,7 @@ TEST(Flavor, StandardGetters) prover_polynomials.w_l = w_l; prover_polynomials.w_r = w_r; prover_polynomials.w_o = w_o; + prover_polynomials.w_4 = w_4; prover_polynomials.z_perm = z_perm; prover_polynomials.z_perm_shift = z_perm_shift; prover_polynomials.q_m = q_m; @@ -101,20 +103,11 @@ TEST(Flavor, StandardGetters) 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 Flavor = proof_system::honk::flavor::Ultra; using FF = Flavor::FF; using PartiallyEvaluatedMultivariates = Flavor::PartiallyEvaluatedMultivariates; using Polynomial = barretenberg::Polynomial; diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp deleted file mode 100644 index 0f503179a6a7..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp +++ /dev/null @@ -1,309 +0,0 @@ -#pragma once -#include "barretenberg/ecc/curves/bn254/g1.hpp" -#include "barretenberg/honk/pcs/kzg/kzg.hpp" -#include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/polynomials/barycentric.hpp" -#include "barretenberg/polynomials/evaluation_domain.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/polynomials/univariate.hpp" -#include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" -#include "barretenberg/proof_system/flavor/flavor.hpp" -#include "barretenberg/proof_system/relations/arithmetic_relation.hpp" -#include "barretenberg/proof_system/relations/permutation_relation.hpp" -#include "barretenberg/srs/factories/crs_factory.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 CircuitBuilder = StandardCircuitBuilder; - using Curve = curve::BN254; - using PCS = pcs::kzg::KZG; - using GroupElement = Curve::Element; - using Commitment = Curve::AffineElement; - using CommitmentHandle = Curve::AffineElement; - using FF = Curve::ScalarField; - using Polynomial = barretenberg::Polynomial; - using PolynomialHandle = std::span; - using CommitmentKey = pcs::CommitmentKey; - using VerifierCommitmentKey = pcs::VerifierCommitmentKey; - - static constexpr size_t NUM_WIRES = CircuitBuilder::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; - - using GrandProductRelations = std::tuple>; - // define the tuple of Relations that comprise the Sumcheck relation - using Relations = std::tuple, proof_system::PermutationRelation>; - - static constexpr size_t MAX_RELATION_LENGTH = get_max_relation_length(); - - // MAX_RANDOM_RELATION_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` random - // polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation length = 3 - static constexpr size_t MAX_RANDOM_RELATION_LENGTH = MAX_RELATION_LENGTH + 1; - static constexpr size_t NUM_RELATIONS = std::tuple_size::value; - - // define the containers for storing the contributions from each relation in Sumcheck - using RelationUnivariates = decltype(create_relation_univariates_container()); - using RelationValues = decltype(create_relation_values_container()); - - // Whether or not the first row of the execution trace is reserved for 0s to enable shifts - static constexpr bool has_zero_row = false; - - 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 - - static constexpr CircuitType CIRCUIT_TYPE = CircuitBuilder::CIRCUIT_TYPE; - - 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 storing the partially evaluated multivariates produced by sumcheck. - */ - class PartiallyEvaluatedMultivariates : public AllEntities { - - public: - PartiallyEvaluatedMultivariates() = default; - PartiallyEvaluatedMultivariates(const size_t circuit_size) - { - // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) - for (auto& poly : this->_data) { - poly = Polynomial(circuit_size / 2); - } - } - }; - - /** - * @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, - barretenberg::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 ClaimedEvaluations : public AllEntities { - public: - using Base = AllEntities; - using Base::Base; - ClaimedEvaluations(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; - } - }; - - class FoldingParameters { - public: - FF gate_separation_challenge; - FF target_sum; - }; -}; - -} // namespace proof_system::honk::flavor diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/standard_grumpkin.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/standard_grumpkin.hpp deleted file mode 100644 index bee22076a591..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/standard_grumpkin.hpp +++ /dev/null @@ -1,306 +0,0 @@ -#pragma once -#include "barretenberg/ecc/curves/bn254/g1.hpp" -#include "barretenberg/honk/pcs/ipa/ipa.hpp" -#include "barretenberg/polynomials/barycentric.hpp" -#include "barretenberg/polynomials/univariate.hpp" - -#include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/polynomials/evaluation_domain.hpp" -#include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp" -#include "barretenberg/proof_system/flavor/flavor.hpp" -#include "barretenberg/proof_system/relations/arithmetic_relation.hpp" -#include "barretenberg/proof_system/relations/permutation_relation.hpp" -#include -#include -#include -#include -#include -#include - -namespace proof_system::honk::flavor { -class StandardGrumpkin { - // TODO(Mara): At the moment this class is a duplicate of the Standard flavor with a different PCS for testing - // purposes. This will be changed to Grumpkin once generating Honk proofs over Grumpkin has been enabled. - public: - using CircuitBuilder = StandardGrumpkinCircuitBuilder; - using Curve = curve::Grumpkin; - using PCS = pcs::ipa::IPA; - using GroupElement = Curve::Element; - using Commitment = Curve::AffineElement; - using CommitmentHandle = Curve::AffineElement; - using FF = Curve::ScalarField; - using Polynomial = barretenberg::Polynomial; - using PolynomialHandle = std::span; - using CommitmentKey = pcs::CommitmentKey; - using VerifierCommitmentKey = pcs::VerifierCommitmentKey; - - static constexpr size_t NUM_WIRES = CircuitBuilder::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; - - // define the tuple of Relations that require grand products - using GrandProductRelations = std::tuple>; - // define the tuple of Relations that comprise the Sumcheck relation - using Relations = std::tuple, proof_system::PermutationRelation>; - - static constexpr size_t MAX_RELATION_LENGTH = get_max_relation_length(); - - // MAX_RANDOM_RELATION_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` random - // polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation length = 3 - static constexpr size_t MAX_RANDOM_RELATION_LENGTH = MAX_RELATION_LENGTH + 1; - static constexpr size_t NUM_RELATIONS = std::tuple_size::value; - - // define the containers for storing the contributions from each relation in Sumcheck - using RelationUnivariates = decltype(create_relation_univariates_container()); - using RelationValues = decltype(create_relation_values_container()); - - // Whether or not the first row of the execution trace is reserved for 0s to enable shifts - static constexpr bool has_zero_row = false; - - 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 storing the partially evaluated multivariates produced by sumcheck. - */ - class PartiallyEvaluatedMultivariates : public AllEntities { - - public: - PartiallyEvaluatedMultivariates() = default; - PartiallyEvaluatedMultivariates(const size_t circuit_size) - { - // Storage is only needed after the first partial evaluation, hence polynomials of size (n / 2) - for (auto& poly : this->_data) { - poly = Polynomial(circuit_size / 2); - } - } - }; - - /** - * @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, - barretenberg::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 ClaimedEvaluations : public AllEntities { - public: - using Base = AllEntities; - using Base::Base; - ClaimedEvaluations(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; - } - }; - - class FoldingParameters { - public: - FF gate_separation_challenge; - FF target_sum; - }; -}; -} // namespace proof_system::honk::flavor \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp index 284f1616b681..961548373993 100644 --- a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp @@ -10,9 +10,7 @@ namespace proof_system::honk { * @tparam Flavor * @param circuit */ -template -void ProverInstance_::compute_circuit_size_parameters(Circuit& circuit) - requires IsUltraFlavor +template void ProverInstance_::compute_circuit_size_parameters(Circuit& circuit) { // Compute total length of the tables and the number of lookup gates; their sum is the minimum circuit size for (const auto& table : circuit.lookup_tables) { @@ -58,101 +56,98 @@ template void ProverInstance_::compute_witness(Circuit& c 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]; - if constexpr (IsUltraFlavor) { - proving_key->w_4 = wire_polynomials[3]; - - // If Goblin, construct the ECC op queue wire polynomials - if constexpr (IsGoblinFlavor) { - construct_ecc_op_wire_polynomials(wire_polynomials); - } + // If Goblin, construct the ECC op queue wire polynomials + if constexpr (IsGoblinFlavor) { + construct_ecc_op_wire_polynomials(wire_polynomials); + } - // Construct the sorted concatenated list polynomials for the lookup argument - polynomial s_1(dyadic_circuit_size); - polynomial s_2(dyadic_circuit_size); - polynomial s_3(dyadic_circuit_size); - polynomial s_4(dyadic_circuit_size); - - // The sorted list polynomials have (tables_size + lookups_size) populated entries. We define the index below so - // that these entries are written into the last indices of the polynomials. The values on the first - // dyadic_circuit_size - (tables_size + lookups_size) indices are automatically initialized to zero via the - // polynomial constructor. - size_t s_index = dyadic_circuit_size - tables_size - lookups_size; - ASSERT(s_index > 0); // We need at least 1 row of zeroes for the permutation argument - - for (auto& table : circuit.lookup_tables) { - const fr table_index(table.table_index); - auto& lookup_gates = table.lookup_gates; - for (size_t i = 0; i < table.size; ++i) { - if (table.use_twin_keys) { - lookup_gates.push_back({ - { - table.column_1[i].from_montgomery_form().data[0], - table.column_2[i].from_montgomery_form().data[0], - }, - { - table.column_3[i], - 0, - }, - }); - } else { - lookup_gates.push_back({ - { - table.column_1[i].from_montgomery_form().data[0], - 0, - }, - { - table.column_2[i], - table.column_3[i], - }, - }); - } + // Construct the sorted concatenated list polynomials for the lookup argument + polynomial s_1(dyadic_circuit_size); + polynomial s_2(dyadic_circuit_size); + polynomial s_3(dyadic_circuit_size); + polynomial s_4(dyadic_circuit_size); + + // The sorted list polynomials have (tables_size + lookups_size) populated entries. We define the index below so + // that these entries are written into the last indices of the polynomials. The values on the first + // dyadic_circuit_size - (tables_size + lookups_size) indices are automatically initialized to zero via the + // polynomial constructor. + size_t s_index = dyadic_circuit_size - tables_size - lookups_size; + ASSERT(s_index > 0); // We need at least 1 row of zeroes for the permutation argument + + for (auto& table : circuit.lookup_tables) { + const fr table_index(table.table_index); + auto& lookup_gates = table.lookup_gates; + for (size_t i = 0; i < table.size; ++i) { + if (table.use_twin_keys) { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + table.column_2[i].from_montgomery_form().data[0], + }, + { + table.column_3[i], + 0, + }, + }); + } else { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + 0, + }, + { + table.column_2[i], + table.column_3[i], + }, + }); } + } #ifdef NO_TBB - std::sort(lookup_gates.begin(), lookup_gates.end()); + std::sort(lookup_gates.begin(), lookup_gates.end()); #else - std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); + std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); #endif - for (const auto& entry : lookup_gates) { - const auto components = entry.to_sorted_list_components(table.use_twin_keys); - s_1[s_index] = components[0]; - s_2[s_index] = components[1]; - s_3[s_index] = components[2]; - s_4[s_index] = table_index; - ++s_index; - } + for (const auto& entry : lookup_gates) { + const auto components = entry.to_sorted_list_components(table.use_twin_keys); + s_1[s_index] = components[0]; + s_2[s_index] = components[1]; + s_3[s_index] = components[2]; + s_4[s_index] = table_index; + ++s_index; } - - // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing - // space - proving_key->sorted_1 = s_1; - proving_key->sorted_2 = s_2; - proving_key->sorted_3 = s_3; - proving_key->sorted_4 = s_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 have been committed to. The 4th wire on these gates will be a random linear combination of the - // first 3 wires, using the plookup challenge `eta`. We need to update the records with an offset Because we - // shift the gates to account for everything that comes before them in the execution trace, e.g. public inputs, - // a zero row, etc. - size_t offset = num_ecc_op_gates + num_public_inputs + num_zero_rows; - auto add_public_inputs_offset = [offset](uint32_t gate_index) { return gate_index + offset; }; - proving_key->memory_read_records = std::vector(); - proving_key->memory_write_records = std::vector(); - - std::transform(circuit.memory_read_records.begin(), - circuit.memory_read_records.end(), - std::back_inserter(proving_key->memory_read_records), - add_public_inputs_offset); - std::transform(circuit.memory_write_records.begin(), - circuit.memory_write_records.end(), - std::back_inserter(proving_key->memory_write_records), - add_public_inputs_offset); } + // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing + // space + proving_key->sorted_1 = s_1; + proving_key->sorted_2 = s_2; + proving_key->sorted_3 = s_3; + proving_key->sorted_4 = s_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 have been committed to. The 4th wire on these gates will be a random linear combination of the + // first 3 wires, using the plookup challenge `eta`. We need to update the records with an offset Because we + // shift the gates to account for everything that comes before them in the execution trace, e.g. public inputs, + // a zero row, etc. + size_t offset = num_ecc_op_gates + num_public_inputs + num_zero_rows; + auto add_public_inputs_offset = [offset](uint32_t gate_index) { return gate_index + offset; }; + proving_key->memory_read_records = std::vector(); + proving_key->memory_write_records = std::vector(); + + std::transform(circuit.memory_read_records.begin(), + circuit.memory_read_records.end(), + std::back_inserter(proving_key->memory_read_records), + add_public_inputs_offset); + std::transform(circuit.memory_write_records.begin(), + circuit.memory_write_records.end(), + std::back_inserter(proving_key->memory_write_records), + add_public_inputs_offset); + computed_witness = true; } @@ -164,9 +159,7 @@ template void ProverInstance_::compute_witness(Circuit& c * @tparam Flavor * @param wire_polynomials */ -template -void ProverInstance_::construct_ecc_op_wire_polynomials(auto& wire_polynomials) - requires IsUltraFlavor +template void ProverInstance_::construct_ecc_op_wire_polynomials(auto& wire_polynomials) { std::array op_wire_polynomials; for (auto& poly : op_wire_polynomials) { @@ -200,71 +193,63 @@ std::shared_ptr ProverInstance_::compute_pr // Compute lagrange selectors proving_key = std::make_shared(dyadic_circuit_size, num_public_inputs); - construct_selector_polynomials(circuit, proving_key.get()); - if constexpr (StandardFlavor) { - // Compute sigma polynomials (we should update that late) - compute_standard_honk_sigma_permutations(circuit, proving_key.get()); - compute_standard_honk_id_polynomials(proving_key.get()); - compute_first_and_last_lagrange_polynomials(proving_key.get()); - } + construct_selector_polynomials(circuit, proving_key.get()); - if constexpr (IsUltraFlavor) { + compute_honk_generalized_sigma_permutations(circuit, proving_key.get()); - compute_honk_generalized_sigma_permutations(circuit, proving_key.get()); - compute_first_and_last_lagrange_polynomials(proving_key.get()); + compute_first_and_last_lagrange_polynomials(proving_key.get()); - polynomial poly_q_table_column_1(dyadic_circuit_size); - polynomial poly_q_table_column_2(dyadic_circuit_size); - polynomial poly_q_table_column_3(dyadic_circuit_size); - polynomial poly_q_table_column_4(dyadic_circuit_size); + polynomial poly_q_table_column_1(dyadic_circuit_size); + polynomial poly_q_table_column_2(dyadic_circuit_size); + polynomial poly_q_table_column_3(dyadic_circuit_size); + polynomial poly_q_table_column_4(dyadic_circuit_size); - size_t offset = dyadic_circuit_size - tables_size; + size_t offset = dyadic_circuit_size - tables_size; - // Create lookup selector polynomials which interpolate each table column. - // Our selector polys always need to interpolate the full subgroup size, so here we offset so as to - // put the table column's values at the end. (The first gates are for non-lookup constraints). - // [0, ..., 0, ...table, 0, 0, 0, x] - // ^^^^^^^^^ ^^^^^^^^ ^^^^^^^ ^nonzero to ensure uniqueness and to avoid infinity commitments - // | table randomness - // ignored, as used for regular constraints and padding to the next power of 2. + // Create lookup selector polynomials which interpolate each table column. + // Our selector polys always need to interpolate the full subgroup size, so here we offset so as to + // put the table column's values at the end. (The first gates are for non-lookup constraints). + // [0, ..., 0, ...table, 0, 0, 0, x] + // ^^^^^^^^^ ^^^^^^^^ ^^^^^^^ ^nonzero to ensure uniqueness and to avoid infinity commitments + // | table randomness + // ignored, as used for regular constraints and padding to the next power of 2. - for (size_t i = 0; i < offset; ++i) { - poly_q_table_column_1[i] = 0; - poly_q_table_column_2[i] = 0; - poly_q_table_column_3[i] = 0; - poly_q_table_column_4[i] = 0; - } - - for (const auto& table : circuit.lookup_tables) { - const fr table_index(table.table_index); + for (size_t i = 0; i < offset; ++i) { + poly_q_table_column_1[i] = 0; + poly_q_table_column_2[i] = 0; + poly_q_table_column_3[i] = 0; + poly_q_table_column_4[i] = 0; + } - for (size_t i = 0; i < table.size; ++i) { - poly_q_table_column_1[offset] = table.column_1[i]; - poly_q_table_column_2[offset] = table.column_2[i]; - poly_q_table_column_3[offset] = table.column_3[i]; - poly_q_table_column_4[offset] = table_index; - ++offset; - } + for (const auto& table : circuit.lookup_tables) { + const fr table_index(table.table_index); + + for (size_t i = 0; i < table.size; ++i) { + poly_q_table_column_1[offset] = table.column_1[i]; + poly_q_table_column_2[offset] = table.column_2[i]; + poly_q_table_column_3[offset] = table.column_3[i]; + poly_q_table_column_4[offset] = table_index; + ++offset; } + } - // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing - // space + // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing + // space - 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; + 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; - proving_key->recursive_proof_public_input_indices = std::vector( - recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); + proving_key->recursive_proof_public_input_indices = + std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); - proving_key->contains_recursive_proof = contains_recursive_proof; + proving_key->contains_recursive_proof = contains_recursive_proof; - if constexpr (IsGoblinFlavor) { - proving_key->num_ecc_op_gates = num_ecc_op_gates; - proving_key->op_queue = circuit.op_queue; - } + if constexpr (IsGoblinFlavor) { + proving_key->num_ecc_op_gates = num_ecc_op_gates; + proving_key->op_queue = circuit.op_queue; } return proving_key; @@ -289,27 +274,25 @@ template void ProverInstance_::initialise_prover_polynomi prover_polynomials.w_r = proving_key->w_r; prover_polynomials.w_o = proving_key->w_o; - if constexpr (IsUltraFlavor) { - prover_polynomials.q_4 = proving_key->q_4; - prover_polynomials.q_arith = proving_key->q_arith; - prover_polynomials.q_sort = proving_key->q_sort; - prover_polynomials.q_elliptic = proving_key->q_elliptic; - prover_polynomials.q_aux = proving_key->q_aux; - prover_polynomials.q_lookup = proving_key->q_lookup; - prover_polynomials.sigma_4 = proving_key->sigma_4; - prover_polynomials.id_4 = proving_key->id_4; - prover_polynomials.table_1 = proving_key->table_1; - prover_polynomials.table_2 = proving_key->table_2; - prover_polynomials.table_3 = proving_key->table_3; - prover_polynomials.table_4 = proving_key->table_4; - prover_polynomials.table_1_shift = proving_key->table_1.shifted(); - prover_polynomials.table_2_shift = proving_key->table_2.shifted(); - prover_polynomials.table_3_shift = proving_key->table_3.shifted(); - prover_polynomials.table_4_shift = proving_key->table_4.shifted(); - prover_polynomials.w_l_shift = proving_key->w_l.shifted(); - prover_polynomials.w_r_shift = proving_key->w_r.shifted(); - prover_polynomials.w_o_shift = proving_key->w_o.shifted(); - } + prover_polynomials.q_4 = proving_key->q_4; + prover_polynomials.q_arith = proving_key->q_arith; + prover_polynomials.q_sort = proving_key->q_sort; + prover_polynomials.q_elliptic = proving_key->q_elliptic; + prover_polynomials.q_aux = proving_key->q_aux; + prover_polynomials.q_lookup = proving_key->q_lookup; + prover_polynomials.sigma_4 = proving_key->sigma_4; + prover_polynomials.id_4 = proving_key->id_4; + prover_polynomials.table_1 = proving_key->table_1; + prover_polynomials.table_2 = proving_key->table_2; + prover_polynomials.table_3 = proving_key->table_3; + prover_polynomials.table_4 = proving_key->table_4; + prover_polynomials.table_1_shift = proving_key->table_1.shifted(); + prover_polynomials.table_2_shift = proving_key->table_2.shifted(); + prover_polynomials.table_3_shift = proving_key->table_3.shifted(); + prover_polynomials.table_4_shift = proving_key->table_4.shifted(); + prover_polynomials.w_l_shift = proving_key->w_l.shifted(); + prover_polynomials.w_r_shift = proving_key->w_r.shifted(); + prover_polynomials.w_o_shift = proving_key->w_o.shifted(); if constexpr (IsGoblinFlavor) { prover_polynomials.ecc_op_wire_1 = proving_key->ecc_op_wire_1; @@ -322,26 +305,18 @@ template void ProverInstance_::initialise_prover_polynomi std::span public_wires_source = prover_polynomials.w_r; // Determine public input offsets in the circuit relative to the 0th index for Ultra flavors - if constexpr (IsUltraFlavor) { - pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; - if constexpr (IsGoblinFlavor) { - pub_inputs_offset += proving_key->num_ecc_op_gates; - } - // Construct the public inputs array - for (size_t i = 0; i < proving_key->num_public_inputs; ++i) { - size_t idx = i + pub_inputs_offset; - public_inputs.emplace_back(public_wires_source[idx]); - } - } else { - for (size_t i = 0; i < proving_key->num_public_inputs; ++i) { - public_inputs.emplace_back(public_wires_source[i]); - } + pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; + if constexpr (IsGoblinFlavor) { + pub_inputs_offset += proving_key->num_ecc_op_gates; + } + // Construct the public inputs array + for (size_t i = 0; i < proving_key->num_public_inputs; ++i) { + size_t idx = i + pub_inputs_offset; + public_inputs.emplace_back(public_wires_source[idx]); } } -template -void ProverInstance_::compute_sorted_accumulator_polynomials(FF eta) - requires IsUltraFlavor +template void ProverInstance_::compute_sorted_accumulator_polynomials(FF eta) { relation_parameters.eta = eta; // Compute sorted witness-table accumulator @@ -366,9 +341,7 @@ void ProverInstance_::compute_sorted_accumulator_polynomials(FF eta) * @param eta random challenge * @return Polynomial */ -template -void ProverInstance_::compute_sorted_list_accumulator(FF eta) - requires IsUltraFlavor +template void ProverInstance_::compute_sorted_list_accumulator(FF eta) { const size_t circuit_size = proving_key->circuit_size; @@ -399,9 +372,7 @@ void ProverInstance_::compute_sorted_list_accumulator(FF eta) * @tparam Flavor * @param eta challenge produced after commitment to first three wire polynomials */ -template -void ProverInstance_::add_plookup_memory_records_to_wire_4(FF eta) - requires IsUltraFlavor +template void ProverInstance_::add_plookup_memory_records_to_wire_4(FF eta) { // The plookup memory record values are computed at the indicated indices as // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; @@ -439,10 +410,8 @@ template void ProverInstance_::compute_grand_product_poly relation_parameters.gamma = gamma; relation_parameters.public_input_delta = public_input_delta; - if constexpr (IsUltraFlavor) { - auto lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, proving_key->circuit_size); - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; - } + auto lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, proving_key->circuit_size); + relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Compute permutation and lookup grand product polynomials grand_product_library::compute_grand_products(proving_key, prover_polynomials, relation_parameters); @@ -478,40 +447,37 @@ std::shared_ptr ProverInstance_::compu verification_key->lagrange_first = commitment_key->commit(proving_key->lagrange_first); verification_key->lagrange_last = commitment_key->commit(proving_key->lagrange_last); - if constexpr (IsUltraFlavor) { - verification_key->q_4 = commitment_key->commit(proving_key->q_4); - verification_key->q_arith = commitment_key->commit(proving_key->q_arith); - verification_key->q_sort = commitment_key->commit(proving_key->q_sort); - verification_key->q_elliptic = commitment_key->commit(proving_key->q_elliptic); - verification_key->q_aux = commitment_key->commit(proving_key->q_aux); - verification_key->q_lookup = commitment_key->commit(proving_key->q_lookup); - verification_key->sigma_4 = commitment_key->commit(proving_key->sigma_4); - verification_key->id_4 = commitment_key->commit(proving_key->id_4); - verification_key->table_1 = commitment_key->commit(proving_key->table_1); - verification_key->table_2 = commitment_key->commit(proving_key->table_2); - verification_key->table_3 = commitment_key->commit(proving_key->table_3); - verification_key->table_4 = commitment_key->commit(proving_key->table_4); - - // TODO(luke): Similar to the lagrange_first/last polynomials, we dont really need to commit to this polynomial - // due to its simple structure. Handling it in the same way as the lagrange polys for now for simplicity. - if constexpr (IsGoblinFlavor) { - verification_key->lagrange_ecc_op = commitment_key->commit(proving_key->lagrange_ecc_op); - } + verification_key->q_4 = commitment_key->commit(proving_key->q_4); + verification_key->q_arith = commitment_key->commit(proving_key->q_arith); + verification_key->q_sort = commitment_key->commit(proving_key->q_sort); + verification_key->q_elliptic = commitment_key->commit(proving_key->q_elliptic); + verification_key->q_aux = commitment_key->commit(proving_key->q_aux); + verification_key->q_lookup = commitment_key->commit(proving_key->q_lookup); + verification_key->sigma_4 = commitment_key->commit(proving_key->sigma_4); + verification_key->id_4 = commitment_key->commit(proving_key->id_4); + verification_key->table_1 = commitment_key->commit(proving_key->table_1); + verification_key->table_2 = commitment_key->commit(proving_key->table_2); + verification_key->table_3 = commitment_key->commit(proving_key->table_3); + verification_key->table_4 = commitment_key->commit(proving_key->table_4); + + // TODO(luke): Similar to the lagrange_first/last polynomials, we dont really need to commit to this polynomial + // due to its simple structure. Handling it in the same way as the lagrange polys for now for simplicity. + if constexpr (IsGoblinFlavor) { + verification_key->lagrange_ecc_op = commitment_key->commit(proving_key->lagrange_ecc_op); + } - // // See `add_recusrive_proof()` for how this recursive data is assigned. - // verification_key->recursive_proof_public_input_indices = - // std::vector(recursive_proof_public_input_indices.begin(), - // recursive_proof_public_input_indices.end()); + // // See `add_recusrive_proof()` for how this recursive data is assigned. + // verification_key->recursive_proof_public_input_indices = + // std::vector(recursive_proof_public_input_indices.begin(), + // recursive_proof_public_input_indices.end()); + + // verification_key->contains_recursive_proof = contains_recursive_proof; - // verification_key->contains_recursive_proof = contains_recursive_proof; - } return verification_key; } template class ProverInstance_; template class ProverInstance_; -template class ProverInstance_; -template class ProverInstance_; template class ProverInstance_; } // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp index f65a06e79e99..82a15ae736fd 100644 --- a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp @@ -1,7 +1,5 @@ #pragma once #include "barretenberg/honk/flavor/goblin_ultra.hpp" -#include "barretenberg/honk/flavor/standard.hpp" -#include "barretenberg/honk/flavor/standard_grumpkin.hpp" #include "barretenberg/honk/flavor/ultra.hpp" #include "barretenberg/honk/flavor/ultra_grumpkin.hpp" #include "barretenberg/honk/proof_system/folding_result.hpp" @@ -51,13 +49,7 @@ template class ProverInstance_ { ProverInstance_(Circuit& circuit) { - if constexpr (IsUltraFlavor) { - compute_circuit_size_parameters(circuit); - } else { - num_public_inputs = circuit.public_inputs.size(); - total_num_gates = circuit.num_gates + num_public_inputs; - dyadic_circuit_size = circuit.get_circuit_subgroup_size(total_num_gates); - } + compute_circuit_size_parameters(circuit); compute_proving_key(circuit); compute_witness(circuit); } @@ -74,11 +66,9 @@ template class ProverInstance_ { void initialise_prover_polynomials(); - void compute_sorted_accumulator_polynomials(FF) - requires IsUltraFlavor; + void compute_sorted_accumulator_polynomials(FF); - void compute_sorted_list_accumulator(FF) - requires IsUltraFlavor; + void compute_sorted_list_accumulator(FF); void compute_grand_product_polynomials(FF, FF); @@ -96,25 +86,20 @@ template class ProverInstance_ { std::shared_ptr compute_proving_key(Circuit&); - void compute_circuit_size_parameters(Circuit&) - requires IsUltraFlavor; + void compute_circuit_size_parameters(Circuit&); void compute_witness(Circuit&); - void construct_ecc_op_wire_polynomials(auto&) - requires IsUltraFlavor; + void construct_ecc_op_wire_polynomials(auto&); void add_table_column_selector_poly_to_proving_key(barretenberg::polynomial& small, const std::string& tag); - void add_plookup_memory_records_to_wire_4(FF) - requires IsUltraFlavor; + void add_plookup_memory_records_to_wire_4(FF); }; extern template class ProverInstance_; extern template class ProverInstance_; extern template class ProverInstance_; -extern template class ProverInstance_; -extern template class ProverInstance_; using ProverInstance = ProverInstance_; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.cpp index f1dc05345c23..74f35e6e4b15 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_verifier.cpp @@ -1,5 +1,6 @@ #include "./eccvm_verifier.hpp" -#include "barretenberg/honk/flavor/standard.hpp" +#include "barretenberg/honk/pcs/gemini/gemini.hpp" +#include "barretenberg/honk/pcs/shplonk/shplonk.hpp" #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/grand_product_library.test.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/grand_product_library.test.cpp index 807c27f7d0f8..c66c876b98aa 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/grand_product_library.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/grand_product_library.test.cpp @@ -1,7 +1,6 @@ #include "grand_product_library.hpp" #include "barretenberg/ecc/curves/bn254/bn254.hpp" -#include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/honk/flavor/ultra.hpp" #include "barretenberg/polynomials/polynomial.hpp" @@ -118,17 +117,11 @@ template class GrandProductTests : public testing::Test { constexpr size_t PERMUTATION_RELATION_INDEX = 0; using LHS = typename std::tuple_element::type; - if constexpr (Flavor::NUM_WIRES == 4) { - using RHS = typename proof_system::UltraPermutationRelation; - static_assert(std::same_as); - grand_product_library::compute_grand_product( - proving_key->circuit_size, prover_polynomials, params); - } else { - using RHS = proof_system::PermutationRelation; - static_assert(std::same_as); - grand_product_library::compute_grand_product( - proving_key->circuit_size, prover_polynomials, params); - } + ASSERT(Flavor::NUM_WIRES == 4); + using RHS = typename proof_system::UltraPermutationRelation; + static_assert(std::same_as); + grand_product_library::compute_grand_product( + proving_key->circuit_size, prover_polynomials, params); // 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 @@ -376,7 +369,6 @@ TYPED_TEST_SUITE(GrandProductTests, FieldTypes); TYPED_TEST(GrandProductTests, GrandProductPermutation) { - TestFixture::template test_permutation_grand_product_construction(); TestFixture::template test_permutation_grand_product_construction(); } diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp deleted file mode 100644 index 8df098e009f9..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp +++ /dev/null @@ -1,248 +0,0 @@ -#include "prover.hpp" -#include "barretenberg/honk/proof_system/grand_product_library.hpp" -#include "barretenberg/honk/sumcheck/sumcheck.hpp" -#include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/honk/utils/power_polynomial.hpp" - -namespace proof_system::honk { - -/** - * Create Prover from proving key, witness and manifest. - * - * @param input_key Proving key. - * @param input_manifest Input manifest - * - * @tparam settings Settings class. - * */ -template -StandardProver_::StandardProver_(std::shared_ptr inst) - : queue(inst->commitment_key, transcript) - , instance(std::move(inst)) - , pcs_commitment_key(instance->commitment_key) -{ - instance->initialise_prover_polynomials(); -} - -/** - * - Add circuit size, public input size, and public inputs to transcript - * - * */ -template void StandardProver_::execute_preamble_round() -{ - const auto circuit_size = static_cast(instance->proving_key->circuit_size); - const auto num_public_inputs = static_cast(instance->proving_key->num_public_inputs); - - transcript.send_to_verifier("circuit_size", circuit_size); - transcript.send_to_verifier("public_input_size", num_public_inputs); - - for (size_t i = 0; i < instance->proving_key->num_public_inputs; ++i) { - auto public_input_i = instance->public_inputs[i]; - transcript.send_to_verifier("public_input_" + std::to_string(i), public_input_i); - } -} - -/** - * - Add commitment to wires 1,2,3 to work queue - * - Add PI to transcript (I guess PI will stay in w_2 for now?) - * - * */ -template void StandardProver_::execute_wire_commitments_round() -{ - size_t wire_idx = 0; // TODO(#391) zip - auto wire_polys = instance->proving_key->get_wires(); - for (auto& label : commitment_labels.get_wires()) { - queue.add_commitment(wire_polys[wire_idx], label); - ++wire_idx; - } -} - -/** - * For Standard Honk, this is a non-op (just like for Standard/Turbo Plonk). - * */ -template void StandardProver_::execute_tables_round() -{ - // No operations are needed here for Standard Honk -} - -/** - * - Do Fiat-Shamir to get "beta" challenge (Note: gamma = beta^2) - * - Compute grand product polynomial (permutation only) and commitment - * */ -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"); - - instance->compute_grand_product_polynomials(beta, gamma); - - queue.add_commitment(instance->proving_key->z_perm, commitment_labels.z_perm); -} - -/** - * - Do Fiat-Shamir to get "alpha" challenge - * - Run Sumcheck resulting in u = (u_1,...,u_d) challenges and all - * evaluations at u being calculated. - * */ -template void StandardProver_::execute_relation_check_rounds() -{ - using Sumcheck = sumcheck::SumcheckProver; - - auto sumcheck = Sumcheck(instance->proving_key->circuit_size, transcript); - - sumcheck_output = sumcheck.prove(instance->prover_polynomials, instance->relation_parameters); -} - -/** - * - Get rho challenge - * - Compute d+1 Fold polynomials and their evaluations. - * - * */ -template void StandardProver_::execute_univariatization_round() -{ - const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; - - // Generate batching challenge ρ and powers 1,ρ,…,ρᵐ⁻¹ - FF rho = transcript.get_challenge("rho"); - std::vector rhos = pcs::gemini::powers_of_rho(rho, NUM_POLYNOMIALS); - auto key = instance->proving_key; - auto prover_polynomials = instance->prover_polynomials; - - // Batch the unshifted polynomials and the to-be-shifted polynomials using ρ - Polynomial batched_poly_unshifted(key->circuit_size); // batched unshifted polynomials - 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 - 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. - gemini_polynomials = Gemini::compute_gemini_polynomials( - sumcheck_output.challenge_point, std::move(batched_poly_unshifted), std::move(batched_poly_to_be_shifted)); - - // Compute and add to trasnscript the commitments [Fold^(i)], i = 1, ..., d-1 - for (size_t l = 0; l < key->log_circuit_size - 1; ++l) { - queue.add_commitment(gemini_polynomials[l + 2], "Gemini:FOLD_" + std::to_string(l + 1)); - } -} - -/** - * - Do Fiat-Shamir to get "r" challenge - * - Compute remaining two partially evaluated Fold polynomials Fold_{r}^(0) and Fold_{-r}^(0). - * - 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 StandardProver_::execute_pcs_evaluation_round() -{ - const FF r_challenge = transcript.get_challenge("Gemini:r"); - gemini_output = Gemini::compute_fold_polynomial_evaluations( - sumcheck_output.challenge_point, std::move(gemini_polynomials), r_challenge); - - for (size_t l = 0; l < instance->proving_key->log_circuit_size; ++l) { - std::string label = "Gemini:a_" + std::to_string(l); - const auto& evaluation = gemini_output.opening_pairs[l + 1].evaluation; - transcript.send_to_verifier(label, evaluation); - } -} - -/** - * - Do Fiat-Shamir to get "nu" challenge. - * - Compute commitment [Q]_1 - * */ -template void StandardProver_::execute_shplonk_batched_quotient_round() -{ - nu_challenge = transcript.get_challenge("Shplonk:nu"); - - batched_quotient_Q = - Shplonk::compute_batched_quotient(gemini_output.opening_pairs, gemini_output.witnesses, nu_challenge); - - // commit to Q(X) and add [Q] to the transcript - queue.add_commitment(batched_quotient_Q, "Shplonk:Q"); -} - -/** - * - Do Fiat-Shamir to get "z" challenge. - * - Compute polynomial Q(X) - Q_z(X) - * */ -template void StandardProver_::execute_shplonk_partial_evaluation_round() -{ - 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); -} - -/** - * - Compute final PCS opening proof: - * - For KZG, this is the quotient commitment [W]_1 - * - For IPA, the vectors L and R - * */ -template void StandardProver_::execute_final_pcs_round() -{ - PCS::compute_opening_proof(pcs_commitment_key, shplonk_output.opening_pair, shplonk_output.witness, transcript); -} - -template plonk::proof& StandardProver_::export_proof() -{ - proof.proof_data = transcript.proof_data; - return proof; -} - -template plonk::proof& StandardProver_::construct_proof() -{ - // Add circuit size and public input size to transcript. - execute_preamble_round(); - - // Compute wire commitments; Add PI to transcript - execute_wire_commitments_round(); - queue.process_queue(); - - // Currently a no-op; may execute some "random widgets", commit to W_4, do RAM/ROM stuff - // if this prover structure is kept when we bring tables to Honk. - // Suggestion: Maybe we shouldn't mix and match proof creation for different systems and - // instead instatiate construct_proof differently for each? - execute_tables_round(); - - // Fiat-Shamir: beta & gamma - // Compute grand product(s) and commitments. - execute_grand_product_computation_round(); - queue.process_queue(); - - // Fiat-Shamir: alpha - // Run sumcheck subprotocol. - execute_relation_check_rounds(); - - // Fiat-Shamir: rho - // Compute Fold polynomials and their commitments. - execute_univariatization_round(); - queue.process_queue(); - - // Fiat-Shamir: r - // Compute Fold evaluations - execute_pcs_evaluation_round(); - - // Fiat-Shamir: nu - // Compute Shplonk batched quotient commitment Q - execute_shplonk_batched_quotient_round(); - queue.process_queue(); - - // Fiat-Shamir: z - // Compute partial evaluation Q_z - execute_shplonk_partial_evaluation_round(); - - // Fiat-Shamir: z - // Compute final PCS opening proof (this is KZG quotient commitment or IPA opening proof) - execute_final_pcs_round(); - // TODO(#479): queue.process_queue after the work_queue has been (re)added to KZG/IPA - - return export_proof(); -} - -template class StandardProver_; -template class StandardProver_; - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp deleted file mode 100644 index a88e8db8b7b0..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp +++ /dev/null @@ -1,86 +0,0 @@ -#pragma once -#include "barretenberg/honk/flavor/standard.hpp" -#include "barretenberg/honk/flavor/standard_grumpkin.hpp" -#include "barretenberg/honk/instance/prover_instance.hpp" -#include "barretenberg/honk/pcs/gemini/gemini.hpp" -#include "barretenberg/honk/pcs/shplonk/shplonk.hpp" -#include "barretenberg/honk/proof_system/work_queue.hpp" -#include "barretenberg/honk/sumcheck/sumcheck.hpp" -#include "barretenberg/honk/sumcheck/sumcheck_output.hpp" -#include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/plonk/proof_system/types/proof.hpp" - -namespace proof_system::honk { - -// 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 class StandardProver_ { - - using FF = typename Flavor::FF; - using ProvingKey = typename Flavor::ProvingKey; - using Polynomial = typename Flavor::Polynomial; - using ProverPolynomials = typename Flavor::ProverPolynomials; - using CommitmentLabels = typename Flavor::CommitmentLabels; - using CommitmentKey = typename Flavor::CommitmentKey; - using PCS = typename Flavor::PCS; - using Curve = typename Flavor::Curve; - using Instance = ProverInstance_; - - public: - explicit StandardProver_(std::shared_ptr); - void execute_preamble_round(); - void execute_wire_commitments_round(); - void execute_tables_round(); - void execute_grand_product_computation_round(); - void execute_relation_check_rounds(); - void execute_univariatization_round(); - void execute_pcs_evaluation_round(); - void execute_shplonk_batched_quotient_round(); - void execute_shplonk_partial_evaluation_round(); - - void execute_final_pcs_round(); - - void compute_wire_commitments(); - - void construct_prover_polynomials(); - - plonk::proof& export_proof(); - plonk::proof& construct_proof(); - - ProverTranscript transcript; - - std::vector public_inputs; - - CommitmentLabels commitment_labels; - - // Container for d + 1 Fold polynomials produced by Gemini - std::vector gemini_polynomials; - - Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk - FF nu_challenge; // needed in both Shplonk rounds - - Polynomial quotient_W; - - work_queue queue; - - std::shared_ptr instance; - - sumcheck::SumcheckOutput sumcheck_output; - pcs::gemini::ProverOutput gemini_output; - pcs::shplonk::ProverOutput shplonk_output; - std::shared_ptr pcs_commitment_key; - - using Gemini = pcs::gemini::GeminiProver_; - using Shplonk = pcs::shplonk::ShplonkProver_; - - private: - plonk::proof proof; -}; - -extern template class StandardProver_; -extern template class StandardProver_; - -using StandardProver = StandardProver_; -// using GrumpkinStandardProver = StandardProver_; // e.g. - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp index 19bfcab0a41c..38dc6c2b8b14 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp @@ -1,6 +1,7 @@ #include "./ultra_verifier.hpp" -#include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/honk/pcs/claim.hpp" +#include "barretenberg/honk/pcs/gemini/gemini.hpp" +#include "barretenberg/honk/pcs/shplonk/shplonk.hpp" #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp deleted file mode 100644 index d708c17bd1e8..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include "./verifier.hpp" -#include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/honk/utils/power_polynomial.hpp" -#include "barretenberg/numeric/bitop/get_msb.hpp" - -using namespace barretenberg; -using namespace proof_system::honk::sumcheck; - -namespace proof_system::honk { -template -StandardVerifier_::StandardVerifier_(std::shared_ptr verifier_key) - : key(verifier_key) -{} - -template -StandardVerifier_::StandardVerifier_(StandardVerifier_&& other) - : key(other.key) - , pcs_verification_key(std::move(other.pcs_verification_key)) -{} - -template StandardVerifier_& StandardVerifier_::operator=(StandardVerifier_&& other) -{ - key = other.key; - pcs_verification_key = (std::move(other.pcs_verification_key)); - commitments.clear(); - return *this; -} - -/** -* @brief This function verifies a Honk proof for given program settings. -* -* @details A Standard Honk proof contains the following: - Multilinear evaluations: - w_i(X), i = 1,2,3 - sigma_i(X), i = 1,2,3 - q_i(X), i = 1,2,3,4,5 - z_perm(X), - L_0(X), - id(X) - - Univariate evaluations: - a_0 = Fold_{-r}^(0)(-r), - a_l = Fold^(l)(-r^{2^l}), i = 1,...,d-1 - - Univariate polynomials (evaluations over MAX_RELATION_LENGTH-many points): - S_l, l = 0,...,d-1 - - Commitments: - [w_i]_1, i = 1,2,3 - [z_perm]_1, - [Fold^(l)]_1, l = 1,...,d-1 - [Q]_1, - [W]_1 -*/ -template bool StandardVerifier_::verify_proof(const plonk::proof& proof) -{ - using FF = typename Flavor::FF; - using GroupElement = typename Flavor::GroupElement; - using Commitment = typename Flavor::Commitment; - using Curve = typename Flavor::Curve; - using Gemini = pcs::gemini::GeminiVerifier_; - using Shplonk = pcs::shplonk::ShplonkVerifier_; - using PCS = typename Flavor::PCS; - 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"); - - if (circuit_size != key->circuit_size) { - return false; - } - if (public_input_size != key->num_public_inputs) { - return false; - } - - std::vector public_inputs; - for (size_t i = 0; i < public_input_size; ++i) { - auto public_input_i = transcript.template receive_from_prover("public_input_" + std::to_string(i)); - public_inputs.emplace_back(public_input_i); - } - - // Get commitments to the wires - 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"); - - const FF public_input_delta = compute_public_input_delta(public_inputs, beta, gamma, circuit_size); - - proof_system::RelationParameters relation_parameters{ - .beta = beta, - .gamma = gamma, - .public_input_delta = public_input_delta, - }; - - // Get commitment to Z_PERM - commitments.z_perm = transcript.template receive_from_prover(commitment_labels.z_perm); - - // Execute Sumcheck Verifier - auto sumcheck = SumcheckVerifier(circuit_size); - std::optional sumcheck_output = sumcheck.verify(relation_parameters, transcript); - - // If Sumcheck does not return an output, sumcheck verification has failed - if (!sumcheck_output.has_value()) { - return false; - } - - 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 = GroupElement::zero(); - auto batched_commitment_to_be_shifted = GroupElement::zero(); - - // Compute powers of batching challenge rho - FF rho = transcript.get_challenge("rho"); - std::vector rhos = pcs::gemini::powers_of_rho(rho, Flavor::NUM_ALL_ENTITIES); - - // Compute batched multivariate evaluation - 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 - size_t commitment_idx = 0; - for (auto& commitment : commitments.get_unshifted()) { - batched_commitment_unshifted += commitment * rhos[commitment_idx]; - ++commitment_idx; - } - - // Construct batched commitment for to-be-shifted polynomials - 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 - // - d+1 evaluations a_0_pos, and a_l, l = 0:d-1 - auto gemini_claim = Gemini::reduce_verification(multivariate_challenge, - batched_evaluation, - batched_commitment_unshifted, - batched_commitment_to_be_shifted, - transcript); - - // Produce a Shplonk claim: commitment [Q] - [Q_z], evaluation zero (at random challenge z) - auto shplonk_claim = Shplonk::reduce_verification(pcs_verification_key, gemini_claim, transcript); - - // Verify the Shplonk claim with KZG or IPA - return PCS::verify(pcs_verification_key, shplonk_claim, transcript); -} - -template class StandardVerifier_; -template class StandardVerifier_; - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp deleted file mode 100644 index d90cb61f863a..000000000000 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include "barretenberg/honk/flavor/standard.hpp" -#include "barretenberg/honk/flavor/standard_grumpkin.hpp" -#include "barretenberg/honk/sumcheck/sumcheck.hpp" -#include "barretenberg/plonk/proof_system/types/proof.hpp" - -namespace proof_system::honk { -template class StandardVerifier_ { - using FF = typename Flavor::FF; - using Commitment = typename Flavor::Commitment; - using VerificationKey = typename Flavor::VerificationKey; - using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; - - public: - 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 commitments; - std::shared_ptr pcs_verification_key; - VerifierTranscript transcript; -}; - -extern template class StandardVerifier_; -extern template class StandardVerifier_; - -using StandardVerifier = StandardVerifier_; - -} // namespace proof_system::honk diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp index 990376c5a8e2..49560829db94 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp @@ -1,4 +1,4 @@ -#include "barretenberg/honk/flavor/standard.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include @@ -7,7 +7,7 @@ namespace test_sumcheck_polynomials { template class PartialEvaluationTests : public testing::Test {}; -using Flavors = testing::Types; +using Flavors = testing::Types; TYPED_TEST_SUITE(PartialEvaluationTests, Flavors); diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relation_correctness.test.cpp index 1f86e061916a..d73918737cc8 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relation_correctness.test.cpp @@ -1,7 +1,5 @@ -#include "barretenberg/honk/composer/standard_composer.hpp" #include "barretenberg/honk/composer/ultra_composer.hpp" #include "barretenberg/honk/proof_system/grand_product_library.hpp" -#include "barretenberg/proof_system/relations/arithmetic_relation.hpp" #include "barretenberg/proof_system/relations/auxiliary_relation.hpp" #include "barretenberg/proof_system/relations/ecc_op_queue_relation.hpp" #include "barretenberg/proof_system/relations/elliptic_relation.hpp" @@ -77,15 +75,13 @@ template void create_some_add_gates(auto& circuit_builder) circuit_builder.create_add_gate({ d_idx, c_idx, a_idx, 1, -1, -1, 0 }); } - // If Ultra arithmetization, add a big add gate with use of next row to test q_arith = 2 - if constexpr (proof_system::IsUltraFlavor) { - FF e = a + b + c + d; - uint32_t e_idx = circuit_builder.add_variable(e); + // Add an Ultra-style big add gate with use of next row to test q_arith = 2 + FF e = a + b + c + d; + uint32_t e_idx = circuit_builder.add_variable(e); - uint32_t zero_idx = circuit_builder.zero_idx; - circuit_builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); // use next row - circuit_builder.create_big_add_gate({ zero_idx, zero_idx, zero_idx, e_idx, 0, 0, 0, 0, 0 }, false); - } + uint32_t zero_idx = circuit_builder.zero_idx; + circuit_builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); // use next row + circuit_builder.create_big_add_gate({ zero_idx, zero_idx, zero_idx, e_idx, 0, 0, 0, 0, 0 }, false); } template void create_some_lookup_gates(auto& circuit_builder) @@ -207,49 +203,6 @@ class RelationCorrectnessTests : public ::testing::Test { static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } }; -/** - * @brief Test the correctness of the Standard Honk relations - * - * @details Check that the constraints encoded by the relations are satisfied by the polynomials produced by the - * Standard Honk Composer for a real circuit. - * - * TODO(Kesha): We'll have to update this function once we add zk, since the relation will be incorrect for he first few - * indices - * - */ -TEST_F(RelationCorrectnessTests, StandardRelationCorrectness) -{ - using Flavor = flavor::Standard; - using FF = typename Flavor::FF; - - // Create a composer and a dummy circuit with a few gates - auto builder = proof_system::StandardCircuitBuilder(); - - create_some_add_gates(builder); - - // Create a prover (it will compute proving key and witness) - auto composer = StandardComposer(); - auto instance = composer.create_instance(builder); - auto proving_key = instance->proving_key; - auto circuit_size = proving_key->circuit_size; - - // Generate beta and gamma - FF beta = FF::random_element(); - FF gamma = FF::random_element(); - - instance->initialise_prover_polynomials(); - instance->compute_grand_product_polynomials(beta, gamma); - - // Construct the round for applying sumcheck relations and results for storing computed results - auto relations = std::tuple(proof_system::ArithmeticRelation(), proof_system::PermutationRelation()); - - auto prover_polynomials = instance->prover_polynomials; - auto params = instance->relation_parameters; - // Check that each relation is satisfied across each row of the prover polynomials - check_relation(std::get<0>(relations), circuit_size, prover_polynomials, params); - check_relation(std::get<1>(relations), circuit_size, prover_polynomials, params); -} - /** * @brief Test the correctness of the Ultra Honk relations * diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp index 7723864f4b03..06847d055092 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.hpp @@ -1,7 +1,6 @@ #pragma once #include "barretenberg/common/serialize.hpp" #include "barretenberg/common/throw_or_abort.hpp" -#include "barretenberg/honk/proof_system/prover.hpp" #include "barretenberg/honk/sumcheck/sumcheck_output.hpp" #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/honk/utils/grand_product_delta.hpp" diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp index 37dfbf907711..c79d96f5ecc1 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp @@ -1,10 +1,8 @@ #include "sumcheck.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/honk/composer/standard_composer.hpp" #include "barretenberg/honk/composer/ultra_composer.hpp" #include "barretenberg/honk/proof_system/grand_product_library.hpp" #include "barretenberg/honk/transcript/transcript.hpp" -#include "barretenberg/proof_system/relations/arithmetic_relation.hpp" #include "barretenberg/proof_system/relations/auxiliary_relation.hpp" #include "barretenberg/proof_system/relations/elliptic_relation.hpp" #include "barretenberg/proof_system/relations/gen_perm_sort_relation.hpp" @@ -15,52 +13,68 @@ using namespace proof_system::honk; using namespace proof_system::honk::sumcheck; -using Flavor = proof_system::honk::flavor::Standard; // TODO(Cody): Generalize this test. +using Flavor = proof_system::honk::flavor::Ultra; // 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 { -template -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) +barretenberg::Polynomial random_poly(size_t size) +{ + auto poly = barretenberg::Polynomial(size); + for (auto& coeff : poly) { + coeff = FF::random_element(); + } + return poly; +} + +ProverPolynomials construct_ultra_full_polynomials(auto& input_polynomials) { 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; + full_polynomials.q_c = input_polynomials[0]; + full_polynomials.q_l = input_polynomials[1]; + full_polynomials.q_r = input_polynomials[2]; + full_polynomials.q_o = input_polynomials[3]; + full_polynomials.q_4 = input_polynomials[4]; + full_polynomials.q_m = input_polynomials[5]; + full_polynomials.q_arith = input_polynomials[6]; + full_polynomials.q_sort = input_polynomials[7]; + full_polynomials.q_elliptic = input_polynomials[8]; + full_polynomials.q_aux = input_polynomials[9]; + full_polynomials.q_lookup = input_polynomials[10]; + full_polynomials.sigma_1 = input_polynomials[11]; + full_polynomials.sigma_2 = input_polynomials[12]; + full_polynomials.sigma_3 = input_polynomials[13]; + full_polynomials.sigma_4 = input_polynomials[14]; + full_polynomials.id_1 = input_polynomials[15]; + full_polynomials.id_2 = input_polynomials[16]; + full_polynomials.id_3 = input_polynomials[17]; + full_polynomials.id_4 = input_polynomials[18]; + full_polynomials.table_1 = input_polynomials[19]; + full_polynomials.table_2 = input_polynomials[20]; + full_polynomials.table_3 = input_polynomials[21]; + full_polynomials.table_4 = input_polynomials[22]; + full_polynomials.lagrange_first = input_polynomials[23]; + full_polynomials.lagrange_last = input_polynomials[24]; + full_polynomials.w_l = input_polynomials[25]; + full_polynomials.w_r = input_polynomials[26]; + full_polynomials.w_o = input_polynomials[27]; + full_polynomials.w_4 = input_polynomials[28]; + full_polynomials.sorted_accum = input_polynomials[29]; + full_polynomials.z_perm = input_polynomials[30]; + full_polynomials.z_lookup = input_polynomials[31]; + full_polynomials.table_1_shift = input_polynomials[32]; + full_polynomials.table_2_shift = input_polynomials[33]; + full_polynomials.table_3_shift = input_polynomials[34]; + full_polynomials.table_4_shift = input_polynomials[35]; + full_polynomials.w_l_shift = input_polynomials[36]; + full_polynomials.w_r_shift = input_polynomials[37]; + full_polynomials.w_o_shift = input_polynomials[38]; + full_polynomials.w_4_shift = input_polynomials[39]; + full_polynomials.sorted_accum_shift = input_polynomials[40]; + full_polynomials.z_perm_shift = input_polynomials[41]; + full_polynomials.z_lookup_shift = input_polynomials[42]; return full_polynomials; } @@ -76,63 +90,18 @@ TEST_F(SumcheckTests, PolynomialNormalization) const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); - 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; - for (size_t i = 0; i < multivariate_n; i++) { - w_l[i] = FF::random_element(); - w_r[i] = FF::random_element(); - w_o[i] = FF::random_element(); - z_perm[i] = FF::random_element(); - z_perm_shift[i] = FF::random_element(); - q_m[i] = FF::random_element(); - q_l[i] = FF::random_element(); - q_r[i] = FF::random_element(); - q_o[i] = FF::random_element(); - q_c[i] = FF::random_element(); - sigma_1[i] = FF::random_element(); - sigma_2[i] = FF::random_element(); - sigma_3[i] = FF::random_element(); - id_1[i] = FF::random_element(); - id_2[i] = FF::random_element(); - id_3[i] = FF::random_element(); - lagrange_first[i] = FF::random_element(); - lagrange_last[i] = FF::random_element(); + // Randomly construct the prover polynomials that are input to Sumcheck. + // Note: ProverPolynomials are defined as spans so the polynomials they point to need to exist in memory. + std::array, NUM_POLYNOMIALS> random_polynomials; + for (auto& poly : random_polynomials) { + poly = random_poly(multivariate_n); } + auto full_polynomials = construct_ultra_full_polynomials(random_polynomials); - 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); + info(full_polynomials.w_l[0]); + info(full_polynomials.w_l[1]); + info(full_polynomials.w_l[2]); + info(full_polynomials.w_l[3]); auto transcript = ProverTranscript::init_empty(); @@ -178,201 +147,83 @@ TEST_F(SumcheckTests, PolynomialNormalization) TEST_F(SumcheckTests, Prover) { - auto run_test = [](bool is_random_input) { - const size_t multivariate_d(2); - const size_t multivariate_n(1 << multivariate_d); - std::array, NUM_POLYNOMIALS> input_polynomials; - if (is_random_input) { - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = { - FF::random_element(), FF::random_element(), FF::random_element(), FF::random_element() - }; - } - } else { - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = { 1, 2, 0, 0 }; - } - }; - std::array w_l = input_polynomials[0]; - std::array w_r = input_polynomials[1]; - std::array w_o = input_polynomials[2]; - std::array z_perm = input_polynomials[3]; - std::array z_perm_shift = input_polynomials[4]; - std::array q_m = input_polynomials[5]; - std::array q_l = input_polynomials[6]; - std::array q_r = input_polynomials[7]; - std::array q_o = input_polynomials[8]; - std::array q_c = input_polynomials[9]; - std::array sigma_1 = input_polynomials[10]; - std::array sigma_2 = input_polynomials[11]; - std::array sigma_3 = input_polynomials[12]; - std::array id_1 = input_polynomials[13]; - std::array id_2 = input_polynomials[14]; - std::array id_3 = input_polynomials[15]; - std::array lagrange_first = input_polynomials[16]; - std::array 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); - - auto transcript = ProverTranscript::init_empty(); - - auto sumcheck = SumcheckProver(multivariate_n, transcript); - - auto [multivariate_challenge, evaluations] = sumcheck.prove(full_polynomials, {}); - FF u_0 = multivariate_challenge[0]; - FF u_1 = multivariate_challenge[1]; - std::vector expected_values; - for (auto& polynomial : full_polynomials) { - // using knowledge of inputs here to derive the evaluation - FF expected_lo = polynomial[0] * (FF(1) - u_0) + polynomial[1] * u_0; - expected_lo *= (FF(1) - u_1); - FF expected_hi = polynomial[2] * (FF(1) - u_0) + polynomial[3] * u_0; - expected_hi *= u_1; - expected_values.emplace_back(expected_lo + expected_hi); - } - - for (size_t poly_idx = 0; poly_idx < NUM_POLYNOMIALS; poly_idx++) { - EXPECT_EQ(evaluations[poly_idx], expected_values[poly_idx]); - } - }; - run_test(/* is_random_input=*/false); - run_test(/* is_random_input=*/true); -} - -// TODO(#223)(Cody): write standalone test of the verifier. -// Note(luke): This test (and ProverAndVerifierLonger) are slighly misleading in that they include the grand product -// realtions but do not test their correctness due to the choice of zero polynomials for sigma, id etc. -TEST_F(SumcheckTests, ProverAndVerifier) -{ - const size_t multivariate_d(1); + const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); - std::array w_l = { 0, 1 }; - std::array w_r = { 0, 1 }; - std::array w_o = { 0, 2 }; - std::array z_perm = { 0, 0 }; - std::array z_perm_shift = { 0, 0 }; // NOTE: Not set up to be valid. - std::array q_m = { 0, 0 }; - std::array q_l = { 1, 1 }; - std::array q_r = { 0, 1 }; - std::array q_o = { 0, -1 }; - std::array q_c = { 0, 0 }; - std::array sigma_1 = { 0, 0 }; // NOTE: Not set up to be valid. - std::array sigma_2 = { 0, 0 }; // NOTE: Not set up to be valid. - std::array sigma_3 = { 0, 0 }; // NOTE: Not set up to be valid. - std::array id_1 = { 0, 0 }; // NOTE: Not set up to be valid. - std::array id_2 = { 0, 0 }; // NOTE: Not set up to be valid. - std::array id_3 = { 0, 0 }; // NOTE: Not set up to be valid. - std::array lagrange_first = { 0, 0 }; - std::array lagrange_last = { 0, 0 }; // NOTE: Not set up to be valid. - - 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); - // Set aribitrary random relation parameters - proof_system::RelationParameters relation_parameters{ - .beta = FF::random_element(), - .gamma = FF::random_element(), - .public_input_delta = FF::one(), - }; - - auto prover_transcript = ProverTranscript::init_empty(); - - auto sumcheck_prover = SumcheckProver(multivariate_n, prover_transcript); - - auto prover_output = sumcheck_prover.prove(full_polynomials, relation_parameters); + // Randomly construct the prover polynomials that are input to Sumcheck. + // Note: ProverPolynomials are defined as spans so the polynomials they point to need to exist in memory. + std::array, NUM_POLYNOMIALS> random_polynomials; + for (auto& poly : random_polynomials) { + poly = random_poly(multivariate_n); + } + auto full_polynomials = construct_ultra_full_polynomials(random_polynomials); - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); + auto transcript = ProverTranscript::init_empty(); - auto sumcheck_verifier = SumcheckVerifier(multivariate_n); + auto sumcheck = SumcheckProver(multivariate_n, transcript); - std::optional verifier_output = sumcheck_verifier.verify(relation_parameters, verifier_transcript); + auto [multivariate_challenge, evaluations] = sumcheck.prove(full_polynomials, {}); + FF u_0 = multivariate_challenge[0]; + FF u_1 = multivariate_challenge[1]; + std::vector expected_values; + for (auto& polynomial : full_polynomials) { + // using knowledge of inputs here to derive the evaluation + FF expected_lo = polynomial[0] * (FF(1) - u_0) + polynomial[1] * u_0; + expected_lo *= (FF(1) - u_1); + FF expected_hi = polynomial[2] * (FF(1) - u_0) + polynomial[3] * u_0; + expected_hi *= u_1; + expected_values.emplace_back(expected_lo + expected_hi); + } - ASSERT_TRUE(verifier_output.has_value()); - ASSERT_EQ(prover_output, *verifier_output); + for (size_t poly_idx = 0; poly_idx < NUM_POLYNOMIALS; poly_idx++) { + EXPECT_EQ(evaluations[poly_idx], expected_values[poly_idx]); + } } -// TODO(#225): make the inputs to this test more interesting, e.g. num_public_inputs > 0 and non-trivial permutations -TEST_F(SumcheckTests, ProverAndVerifierLonger) +// TODO(#225): make the inputs to this test more interesting, e.g. non-trivial permutations +TEST_F(SumcheckTests, ProverAndVerifierSimple) { auto run_test = [](bool expect_verified) { const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); - // clang-format off - std::array w_l; - if (expect_verified) { w_l = { 0, 1, 2, 0 }; - } else { w_l = { 0, 0, 2, 0 }; - } - std::array w_r = { 0, 1, 2, 0 }; - std::array w_o = { 0, 2, 4, 0 }; - std::array z_perm = { 0, 0, 0, 0 }; - std::array z_perm_shift = { 0, 0, 0, 0 }; - std::array q_m = { 0, 0, 1, 0 }; - std::array q_l = { 1, 1, 0, 0 }; - std::array q_r = { 0, 1, 0, 0 }; - std::array q_o = { 0, -1, -1, 0 }; - std::array q_c = { 0, 0, 0, 0 }; - // Setting all of these to 0 ensures the GrandProductRelation is satisfied - std::array sigma_1 = { 0, 0, 0, 0 }; - std::array sigma_2 = { 0, 0, 0, 0 }; - std::array sigma_3 = { 0, 0, 0, 0 }; - std::array id_1 = { 0, 0, 0, 0 }; - std::array id_2 = { 0, 0, 0, 0 }; - std::array id_3 = { 0, 0, 0, 0 }; - std::array lagrange_first = { 0, 0, 0, 0 }; - std::array lagrange_last = { 0, 0, 0, 0 }; - // clang-format on - - 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); + // Construct prover polynomials where each is the zero polynomial. + // Note: ProverPolynomials are defined as spans so the polynomials they point to need to exist in memory. + std::array, NUM_POLYNOMIALS> zero_polynomials; + for (auto& poly : zero_polynomials) { + poly = barretenberg::Polynomial(multivariate_n); + } + auto full_polynomials = construct_ultra_full_polynomials(zero_polynomials); + + // Add some non-trivial values to certain polynomials so that the arithmetic relation will have non-trivial + // contribution. Note: since all other polynomials are set to 0, all other relations are trivially satisfied. + std::array w_l; + if (expect_verified) { + w_l = { 0, 1, 2, 0 }; + } else { + w_l = { 0, 0, 2, 0 }; + } + std::array w_r = { 0, 1, 2, 0 }; + std::array w_o = { 0, 2, 4, 0 }; + std::array w_4 = { 0, 0, 0, 0 }; + std::array q_m = { 0, 0, 1, 0 }; + std::array q_l = { 0, 1, 0, 0 }; + std::array q_r = { 0, 1, 0, 0 }; + std::array q_o = { 0, -1, -1, 0 }; + std::array q_c = { 0, 0, 0, 0 }; + std::array q_arith = { 0, 1, 1, 0 }; + // Setting all of these to 0 ensures the GrandProductRelation is satisfied + + full_polynomials.w_l = w_l; + full_polynomials.w_r = w_r; + full_polynomials.w_o = w_o; + full_polynomials.w_4 = w_4; + 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.q_arith = q_arith; // Set aribitrary random relation parameters proof_system::RelationParameters relation_parameters{ @@ -400,54 +251,6 @@ TEST_F(SumcheckTests, ProverAndVerifierLonger) run_test(/* expect_verified=*/false); } -/** - * @brief Test the Standard Sumcheck Prover and Verifier for a real circuit - * - */ -TEST_F(SumcheckTests, RealCircuitStandard) -{ - // Create a composer and a dummy circuit with a few gates - auto builder = proof_system::StandardCircuitBuilder(); - FF a = FF::one(); - // Using the public variable to check that public_input_delta is computed and added to the relation correctly - uint32_t a_idx = builder.add_public_variable(a); - FF b = FF::one(); - FF c = a + b; - FF d = a + c; - uint32_t b_idx = builder.add_variable(b); - uint32_t c_idx = builder.add_variable(c); - uint32_t d_idx = builder.add_variable(d); - for (size_t i = 0; i < 16; i++) { - builder.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - builder.create_add_gate({ d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); - } - // Create a prover (it will compute proving key and witness) - auto composer = StandardComposer(); - auto instance = composer.create_instance(builder); - - // Generate beta and gamma - FF beta = FF::random_element(); - FF gamma = FF::random_element(); - - instance->initialise_prover_polynomials(); - instance->compute_grand_product_polynomials(beta, gamma); - - auto prover_transcript = ProverTranscript::init_empty(); - auto circuit_size = instance->proving_key->circuit_size; - - auto sumcheck_prover = SumcheckProver(circuit_size, prover_transcript); - - auto prover_output = sumcheck_prover.prove(instance->prover_polynomials, instance->relation_parameters); - - auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); - - auto sumcheck_verifier = SumcheckVerifier(circuit_size); - - std::optional verifier_output = sumcheck_verifier.verify(instance->relation_parameters, verifier_transcript); - - ASSERT_TRUE(verifier_output.has_value()); -} - /** * @brief Test the Ultra Sumcheck Prover and Verifier for a real circuit * diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp index 68690080f7a0..a5f3e2cd57b4 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck_round.test.cpp @@ -1,289 +1,27 @@ #include "sumcheck_round.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/honk/flavor/standard.hpp" -#include "barretenberg/numeric/random/engine.hpp" -#include "barretenberg/polynomials/univariate.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" -#include - -#include "barretenberg/common/mem.hpp" #include -/** - * We want to test if the univariate (S_l in the thesis) computed by the prover in a particular round is correct. We - * also want to verify given the purported evaluations of all the relevant polynomials, the verifer can correctly verify - * the purported evaluation of S_l. For the prover, we use a couple of methods to compute the univariate by the sumcheck - * method `compute_univariate` and by step by step manual computation respectively. For the verifier, we follow a - * similar approach. - */ using namespace proof_system::honk; using namespace proof_system::honk::sumcheck; -using namespace proof_system; using barretenberg::BarycentricData; using barretenberg::PowUnivariate; using barretenberg::Univariate; -using Flavor = flavor::Standard; +using Flavor = flavor::Ultra; using FF = typename Flavor::FF; -using ProverPolynomials = typename Flavor::ProverPolynomials; -using ClaimedEvaluations = typename Flavor::ClaimedEvaluations; - -const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; -const size_t max_relation_length = Flavor::MAX_RANDOM_RELATION_LENGTH; -const size_t input_polynomial_length = 2; namespace test_sumcheck_round { -// The below two methods are used in the test ComputeUnivariateProver -static Univariate compute_round_univariate( - std::array, NUM_POLYNOMIALS>& input_polynomials, - const RelationParameters& relation_parameters, - const FF alpha) -{ - size_t round_size = 2; - // Improvement(Cody): This is ugly? Maye supply some/all of this data through "flavor" class? - auto round = SumcheckProverRound(round_size); - - ProverPolynomials full_polynomials; - full_polynomials.w_l = input_polynomials[0]; - full_polynomials.w_r = input_polynomials[1]; - full_polynomials.w_o = input_polynomials[2]; - full_polynomials.z_perm = input_polynomials[3]; - full_polynomials.z_perm_shift = input_polynomials[4]; - full_polynomials.q_m = input_polynomials[5]; - full_polynomials.q_l = input_polynomials[6]; - full_polynomials.q_r = input_polynomials[7]; - full_polynomials.q_o = input_polynomials[8]; - full_polynomials.q_c = input_polynomials[9]; - full_polynomials.sigma_1 = input_polynomials[10]; - full_polynomials.sigma_2 = input_polynomials[11]; - full_polynomials.sigma_3 = input_polynomials[12]; - full_polynomials.id_1 = input_polynomials[13]; - full_polynomials.id_2 = input_polynomials[14]; - full_polynomials.id_3 = input_polynomials[15]; - full_polynomials.lagrange_first = input_polynomials[16]; - full_polynomials.lagrange_last = input_polynomials[17]; - - PowUnivariate pow_zeta(1); - Univariate round_univariate = - round.compute_univariate(full_polynomials, relation_parameters, pow_zeta, alpha); - return round_univariate; -} - -static Univariate compute_expected_round_univariate( - std::array, NUM_POLYNOMIALS>& input_univariates, - const RelationParameters& relation_parameters, - const FF alpha) -{ - 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]); - } - auto w_l_univariate = Univariate(extended_univariates[0]); - auto w_r_univariate = Univariate(extended_univariates[1]); - auto w_o_univariate = Univariate(extended_univariates[2]); - auto z_perm_univariate = Univariate(extended_univariates[3]); - auto z_perm_shift_univariate = - Univariate(extended_univariates[4]); // this is not real shifted data - auto q_m_univariate = Univariate(extended_univariates[5]); - auto q_l_univariate = Univariate(extended_univariates[6]); - auto q_r_univariate = Univariate(extended_univariates[7]); - auto q_o_univariate = Univariate(extended_univariates[8]); - auto q_c_univariate = Univariate(extended_univariates[9]); - auto sigma_1_univariate = Univariate(extended_univariates[10]); - auto sigma_2_univariate = Univariate(extended_univariates[11]); - auto sigma_3_univariate = Univariate(extended_univariates[12]); - auto id_1_univariate = Univariate(extended_univariates[13]); - auto id_2_univariate = Univariate(extended_univariates[14]); - auto id_3_univariate = Univariate(extended_univariates[15]); - auto lagrange_first_univariate = Univariate(extended_univariates[16]); - auto lagrange_last_univariate = Univariate(extended_univariates[17]); - - auto expected_arithmetic_relation = - ((q_m_univariate * w_r_univariate * w_l_univariate) + (q_r_univariate * w_r_univariate) + - (q_l_univariate * w_l_univariate) + (q_o_univariate * w_o_univariate) + (q_c_univariate)); - auto expected_grand_product_computation_relation = - ((z_perm_univariate + lagrange_first_univariate) * - (w_l_univariate + id_1_univariate * relation_parameters.beta + relation_parameters.gamma) * - (w_r_univariate + id_2_univariate * relation_parameters.beta + relation_parameters.gamma) * - (w_o_univariate + id_3_univariate * relation_parameters.beta + relation_parameters.gamma)); - expected_grand_product_computation_relation -= - ((z_perm_shift_univariate + lagrange_last_univariate * relation_parameters.public_input_delta) * - (w_l_univariate + sigma_1_univariate * relation_parameters.beta + relation_parameters.gamma) * - (w_r_univariate + sigma_2_univariate * relation_parameters.beta + relation_parameters.gamma) * - (w_o_univariate + sigma_3_univariate * relation_parameters.beta + relation_parameters.gamma)); - auto expected_grand_product_initialization_relation = (z_perm_shift_univariate * lagrange_last_univariate); - Univariate expected_round_univariate = - expected_arithmetic_relation + expected_grand_product_computation_relation * alpha + - expected_grand_product_initialization_relation * alpha.sqr(); - return expected_round_univariate; -} - -// The below two methods are used in the test ComputeUnivariateVerifier -static FF compute_full_purported_value(std::array& input_values, - const RelationParameters& relation_parameters, - const FF alpha) -{ - ClaimedEvaluations 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 round = SumcheckVerifierRound(); - PowUnivariate pow_univariate(1); - FF full_purported_value = round.compute_full_honk_relation_purported_value( - purported_evaluations, relation_parameters, pow_univariate, alpha); - return full_purported_value; -} - -static FF compute_full_purported_value_expected(std::array& input_values, - const RelationParameters& relation_parameters, - const FF alpha) -{ - FF w_l = input_values[0]; - FF w_r = input_values[1]; - FF w_o = input_values[2]; - FF z_perm = input_values[3]; - FF z_perm_shift = input_values[4]; - FF q_m = input_values[5]; - FF q_l = input_values[6]; - FF q_r = input_values[7]; - FF q_o = input_values[8]; - FF q_c = input_values[9]; - FF sigma_1 = input_values[10]; - FF sigma_2 = input_values[11]; - FF sigma_3 = input_values[12]; - FF id_1 = input_values[13]; - FF id_2 = input_values[14]; - FF id_3 = input_values[15]; - FF lagrange_first = input_values[16]; - FF lagrange_last = input_values[17]; - auto expected_arithmetic_relation = (q_m * w_r * w_l) + (q_r * w_r) + (q_l * w_l) + (q_o * w_o) + q_c; - auto expected_grand_product_computation_relation = - (z_perm + lagrange_first) * (w_l + id_1 * relation_parameters.beta + relation_parameters.gamma) * - (w_r + id_2 * relation_parameters.beta + relation_parameters.gamma) * - (w_o + id_3 * relation_parameters.beta + relation_parameters.gamma); - expected_grand_product_computation_relation -= - (z_perm_shift + lagrange_last * relation_parameters.public_input_delta) * - (w_l + sigma_1 * relation_parameters.beta + relation_parameters.gamma) * - (w_r + sigma_2 * relation_parameters.beta + relation_parameters.gamma) * - (w_o + sigma_3 * relation_parameters.beta + relation_parameters.gamma); - auto expected_grand_product_initialization_relation = z_perm_shift * lagrange_last; - auto expected_full_purported_value = expected_arithmetic_relation + - expected_grand_product_computation_relation * alpha + - expected_grand_product_initialization_relation * alpha.sqr(); - return expected_full_purported_value; -} - -TEST(SumcheckRound, ComputeUnivariateProver) -{ - auto run_test = [](bool is_random_input) { - if (is_random_input) { - std::array, NUM_POLYNOMIALS> input_polynomials; - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = { FF::random_element(), FF::random_element() }; - } - - const FF alpha = FF::random_element(); - const RelationParameters relation_parameters = RelationParameters{ - .beta = FF::random_element(), .gamma = FF::random_element(), .public_input_delta = FF::random_element() - }; - - auto round_univariate = compute_round_univariate(input_polynomials, relation_parameters, alpha); - - // Compute round_univariate manually - std::array, NUM_POLYNOMIALS> input_univariates; - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_univariates[i] = Univariate(input_polynomials[i]); - } - auto expected_round_univariate = - compute_expected_round_univariate(input_univariates, relation_parameters, alpha); - EXPECT_EQ(round_univariate, expected_round_univariate); - } else { - std::array, NUM_POLYNOMIALS> input_polynomials; - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_polynomials[i] = { 1, 2 }; - } - const FF alpha = 1; - const RelationParameters relation_parameters = - RelationParameters{ .beta = 1, .gamma = 1, .public_input_delta = 1 }; - auto round_univariate = compute_round_univariate(input_polynomials, relation_parameters, alpha); - // Compute round_univariate manually - std::array, NUM_POLYNOMIALS> input_univariates; - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_univariates[i] = Univariate(input_polynomials[i]); - } - // expected_round_univariate = { 6, 26, 66, 132, 230, 366 } - auto expected_round_univariate = - compute_expected_round_univariate(input_univariates, relation_parameters, alpha); - EXPECT_EQ(round_univariate, expected_round_univariate); - }; - }; - run_test(/* is_random_input=*/false); - run_test(/* is_random_input=*/true); -} - -TEST(SumcheckRound, ComputeUnivariateVerifier) -{ - auto run_test = [](bool is_random_input) { - if (is_random_input) { - std::array input_values; - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_values[i] = FF::random_element(); - } - const FF alpha = FF::random_element(); - const RelationParameters relation_parameters = RelationParameters{ - .beta = FF::random_element(), .gamma = FF::random_element(), .public_input_delta = FF::random_element() - }; - auto full_purported_value = compute_full_purported_value(input_values, relation_parameters, alpha); - // Compute round_univariate manually - auto expected_full_purported_value = - compute_full_purported_value_expected(input_values, relation_parameters, alpha); - EXPECT_EQ(full_purported_value, expected_full_purported_value); - } else { - std::array input_values; - for (size_t i = 0; i < NUM_POLYNOMIALS; ++i) { - input_values[i] = FF(2); - } - const FF alpha = 1; - const RelationParameters relation_parameters = - RelationParameters{ .beta = 1, .gamma = 1, .public_input_delta = 1 }; - auto full_purported_value = compute_full_purported_value(input_values, relation_parameters, alpha); - // Compute round_univariate manually - auto expected_full_purported_value = - compute_full_purported_value_expected(input_values, relation_parameters, alpha); - EXPECT_EQ(full_purported_value, expected_full_purported_value); - }; - }; - run_test(/* is_random_input=*/false); - run_test(/* is_random_input=*/true); -} - /** - * @brief Test utility functions for applying operations to tuple of tuple of Univariates + * @brief Test SumcheckRound functions for operations on tuples (and tuples of tuples) of Univariates * */ TEST(SumcheckRound, TupleOfTuplesOfUnivariates) { - using Flavor = proof_system::honk::flavor::Standard; + using Flavor = proof_system::honk::flavor::Ultra; using FF = typename Flavor::FF; // Define three linear univariates of different sizes @@ -336,7 +74,7 @@ TEST(SumcheckRound, TupleOfTuplesOfUnivariates) */ TEST(SumcheckRound, TuplesOfEvaluationArrays) { - using Flavor = proof_system::honk::flavor::Standard; + using Flavor = proof_system::honk::flavor::Ultra; using FF = typename Flavor::FF; // Define two arrays of arbitrary elements @@ -373,7 +111,7 @@ TEST(SumcheckRound, TuplesOfEvaluationArrays) */ TEST(SumcheckRound, AddTuplesOfTuplesOfUnivariates) { - using Flavor = proof_system::honk::flavor::Standard; + using Flavor = proof_system::honk::flavor::Ultra; using FF = typename Flavor::FF; // Define some arbitrary univariates @@ -389,7 +127,7 @@ TEST(SumcheckRound, AddTuplesOfTuplesOfUnivariates) Univariate expected_sum_2 = univariate_2 + univariate_5; Univariate expected_sum_3 = univariate_3 + univariate_6; - // Construct two tuples of tuples + // Construct two tuples of tuples of univariates auto tuple_of_tuples_1 = std::make_tuple(std::make_tuple(univariate_1), std::make_tuple(univariate_2, univariate_3)); auto tuple_of_tuples_2 = diff --git a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp b/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp index 7981a048503e..9e789932c889 100644 --- a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp @@ -1,8 +1,6 @@ #include "transcript.hpp" #include "barretenberg/ecc/curves/bn254/g1.hpp" -#include "barretenberg/honk/composer/standard_composer.hpp" #include "barretenberg/honk/composer/ultra_composer.hpp" -#include "barretenberg/honk/flavor/standard.hpp" #include "barretenberg/numeric/bitop/get_msb.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/proof_system/flavor/flavor.hpp" @@ -10,25 +8,17 @@ using namespace proof_system::honk; -template class TranscriptTests : public testing::Test { - protected: - // TODO(https://github.com/AztecProtocol/barretenberg/issues/640): The Standard Honk on Grumpkin test suite fails - // unless the SRS is initialised for every test. - virtual void SetUp() - { - if constexpr (proof_system::IsGrumpkinFlavor) { - barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } else { - barretenberg::srs::init_crs_factory("../srs_db/ignition"); - } - }; +class UltraTranscriptTests : public ::testing::Test { + public: + static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } - using FF = typename Flavor::FF; + using Flavor = proof_system::honk::flavor::Ultra; + using FF = Flavor::FF; /** - * @brief Construct a manifest for a standard Honk proof + * @brief Construct a manifest for a Ultra Honk proof * - * @details This is where we define the "Manifest" for a Standard Honk proof. The tests in this suite are + * @details This is where we define the "Manifest" for a Ultra Honk proof. The tests in this suite are * intented to warn the developer if the Prover/Verifier has deviated from this manifest, however, the * Transcript class is not otherwise contrained to follow the manifest. * @@ -36,7 +26,7 @@ template class TranscriptTests : public testing::Test { * * @return TranscriptManifest */ - TranscriptManifest construct_standard_honk_manifest(size_t circuit_size) + TranscriptManifest construct_ultra_honk_manifest(size_t circuit_size) { TranscriptManifest manifest_expected; @@ -53,14 +43,21 @@ template class TranscriptTests : public testing::Test { size_t round = 0; manifest_expected.add_entry(round, "circuit_size", size_uint32); manifest_expected.add_entry(round, "public_input_size", size_uint32); + manifest_expected.add_entry(round, "pub_inputs_offset", size_uint32); manifest_expected.add_entry(round, "public_input_0", size_FF); - manifest_expected.add_entry(round, "W_1", size_G); - manifest_expected.add_entry(round, "W_2", size_G); - manifest_expected.add_entry(round, "W_3", size_G); + manifest_expected.add_entry(round, "W_L", size_G); + manifest_expected.add_entry(round, "W_R", size_G); + manifest_expected.add_entry(round, "W_O", size_G); + manifest_expected.add_challenge(round, "eta"); + + round++; + manifest_expected.add_entry(round, "SORTED_ACCUM", size_G); + manifest_expected.add_entry(round, "W_4", size_G); manifest_expected.add_challenge(round, "beta", "gamma"); round++; manifest_expected.add_entry(round, "Z_PERM", size_G); + manifest_expected.add_entry(round, "Z_LOOKUP", size_G); manifest_expected.add_challenge(round, "Sumcheck:alpha", "Sumcheck:zeta"); for (size_t i = 0; i < log_n; ++i) { @@ -120,16 +117,12 @@ template class TranscriptTests : public testing::Test { } }; -using StandardFlavorTypes = testing::Types; -TYPED_TEST_SUITE(TranscriptTests, StandardFlavorTypes); - /** * @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(TranscriptTests, ProverManifestConsistency) +TEST_F(UltraTranscriptTests, ProverManifestConsistency) { - using Flavor = TypeParam; // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) typename Flavor::FF a = 1; auto builder = typename Flavor::CircuitBuilder(); @@ -137,169 +130,28 @@ TYPED_TEST(TranscriptTests, ProverManifestConsistency) builder.add_public_variable(a); // Automatically generate a transcript manifest by constructing a proof - auto composer = StandardComposer_(); + auto composer = UltraComposer(); auto instance = composer.create_instance(builder); auto prover = composer.create_prover(instance); auto proof = prover.construct_proof(); // Check that the prover generated manifest agrees with the manifest hard coded in this suite - auto manifest_expected = TestFixture::construct_standard_honk_manifest(instance->proving_key->circuit_size); + auto manifest_expected = construct_ultra_honk_manifest(instance->proving_key->circuit_size); auto prover_manifest = prover.transcript.get_manifest(); // Note: a manifest can be printed using manifest.print() + prover_manifest.print(); + manifest_expected.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; } } -/** - * @brief Ensure consistency between the manifest generated by the standard honk prover over the course of proof - * construction and the one generated by the verifier over the course of proof verification. - * - */ -TYPED_TEST(TranscriptTests, VerifierManifestConsistency) -{ - using Flavor = TypeParam; - // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) - typename Flavor::FF a = 1; - auto builder = typename Flavor::CircuitBuilder(); - builder.add_variable(a); - builder.add_public_variable(a); - - // Automatically generate a transcript manifest in the prover by constructing a proof - auto composer = StandardComposer_(); - auto instance = composer.create_instance(builder); - auto prover = composer.create_prover(instance); - auto proof = prover.construct_proof(); - - // Automatically generate a transcript manifest in the verifier by verifying a proof - auto verifier = composer.create_verifier(instance); - verifier.verify_proof(proof); - prover.transcript.print(); - verifier.transcript.print(); - - // Check consistency between the manifests generated by the prover and verifier - auto prover_manifest = prover.transcript.get_manifest(); - auto verifier_manifest = verifier.transcript.get_manifest(); - - // Note: a manifest can be printed using manifest.print() - for (size_t round = 0; round < prover_manifest.size(); ++round) { - ASSERT_EQ(prover_manifest[round], verifier_manifest[round]) - << "Prover/Verifier manifest discrepency in round " << round; - } -} - -/** - * @brief Test and demonstrate the basic functionality of the prover and verifier transcript - * - */ -TYPED_TEST(TranscriptTests, ProverAndVerifierBasic) -{ - constexpr size_t LENGTH = 8; - - using Fr = barretenberg::fr; - using Univariate = barretenberg::Univariate; - using Commitment = barretenberg::g1::affine_element; - - std::array evaluations; - for (auto& eval : evaluations) { - eval = Fr::random_element(); - } - - // Add some junk to the transcript and compute challenges - uint32_t data = 25; - auto scalar = Fr::random_element(); - auto commitment = Commitment::one(); - auto univariate = Univariate(evaluations); - - // Instantiate a prover transcript and mock an example protocol - ProverTranscript prover_transcript; - - // round 0 - prover_transcript.send_to_verifier("data", data); - Fr alpha = prover_transcript.get_challenge("alpha"); - - // round 1 - prover_transcript.send_to_verifier("scalar", scalar); - prover_transcript.send_to_verifier("commitment", commitment); - Fr beta = prover_transcript.get_challenge("beta"); - - // round 2 - prover_transcript.send_to_verifier("univariate", univariate); - auto [gamma, delta] = prover_transcript.get_challenges("gamma", "delta"); - - // Instantiate a verifier transcript from the raw bytes of the prover transcript; receive data and generate - // challenges according to the example protocol - VerifierTranscript verifier_transcript(prover_transcript.proof_data); - - // round 0 - auto data_received = verifier_transcript.template receive_from_prover("data"); - Fr verifier_alpha = verifier_transcript.get_challenge("alpha"); - - // round 1 - auto scalar_received = verifier_transcript.template receive_from_prover("scalar"); - auto commitment_received = verifier_transcript.template receive_from_prover("commitment"); - Fr verifier_beta = verifier_transcript.get_challenge("beta"); - - // round 2 - auto univariate_received = verifier_transcript.template receive_from_prover("univariate"); - auto [verifier_gamma, verifier_delta] = verifier_transcript.get_challenges("gamma", "delta"); - - // Check the correctness of the elements received by the verifier - EXPECT_EQ(data_received, data); - EXPECT_EQ(scalar_received, scalar); - EXPECT_EQ(commitment_received, commitment); - EXPECT_EQ(univariate_received, univariate); - - // Check consistency of prover and verifier challenges - EXPECT_EQ(alpha, verifier_alpha); - EXPECT_EQ(beta, verifier_beta); - EXPECT_EQ(gamma, verifier_gamma); - EXPECT_EQ(delta, verifier_delta); - - // Check consistency of the generated manifests - EXPECT_EQ(prover_transcript.get_manifest(), verifier_transcript.get_manifest()); -} - -/** - * @brief Demonstrate extent to which verifier transcript is flexible / constrained - * - */ -TYPED_TEST(TranscriptTests, VerifierMistake) -{ - using Fr = barretenberg::fr; - - auto scalar_1 = Fr::random_element(); - auto scalar_2 = Fr::random_element(); - - ProverTranscript prover_transcript; - - prover_transcript.send_to_verifier("scalar1", scalar_1); - prover_transcript.send_to_verifier("scalar2", scalar_2); - auto prover_alpha = prover_transcript.get_challenge("alpha"); - - VerifierTranscript verifier_transcript(prover_transcript.proof_data); - - verifier_transcript.template receive_from_prover("scalar1"); - // accidentally skip receipt of "scalar2"... - // but then generate a challenge anyway - auto verifier_alpha = verifier_transcript.get_challenge("alpha"); - - // Challenges will not agree but neither will the manifests - EXPECT_NE(prover_alpha, verifier_alpha); - EXPECT_NE(prover_transcript.get_manifest(), verifier_transcript.get_manifest()); -} - -class UltraTranscriptTests : public ::testing::Test { - public: - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } -}; - /** * @brief Ensure consistency between the manifest generated by the ultra honk prover over the course of proof * construction and the one generated by the verifier over the course of proof verification. * */ -TEST_F(UltraTranscriptTests, UltraVerifierManifestConsistency) +TEST_F(UltraTranscriptTests, VerifierManifestConsistency) { // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.test.cpp index fcec018acd3c..fc692ab02de3 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.test.cpp @@ -1,6 +1,6 @@ #include "barretenberg/proof_system/composer/composer_lib.hpp" #include "barretenberg/common/slab_allocator.hpp" -#include "barretenberg/honk/flavor/standard.hpp" // TODO: needed? +#include "barretenberg/honk/flavor/ultra.hpp" #include "barretenberg/proof_system/types/circuit_type.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" #include @@ -10,13 +10,13 @@ namespace proof_system::test_composer_lib { class ComposerLibTests : public ::testing::Test { protected: - using Flavor = honk::flavor::Standard; + using Flavor = honk::flavor::Ultra; using FF = typename Flavor::FF; Flavor::CircuitBuilder circuit_constructor; Flavor::ProvingKey proving_key = []() { auto crs_factory = barretenberg::srs::factories::CrsFactory(); auto crs = crs_factory.get_prover_crs(4); - return Flavor::ProvingKey(/*circuit_size=*/4, /*num_public_inputs=*/0); + return Flavor::ProvingKey(/*circuit_size=*/8, /*num_public_inputs=*/0); }(); }; @@ -29,110 +29,35 @@ TEST_F(ComposerLibTests, ConstructSelectors) circuit_constructor.q_c = { 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, 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 - - */ - - const size_t dyadic_circuit_size = circuit_constructor.get_circuit_subgroup_size( - circuit_constructor.num_gates + circuit_constructor.public_inputs.size()); - - auto wires = construct_wire_polynomials_base(circuit_constructor, dyadic_circuit_size); - 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); + size_t offset = 0; + if (Flavor::has_zero_row) { + offset += 1; + } + + EXPECT_EQ(proving_key.q_m[0 + offset], 1); + EXPECT_EQ(proving_key.q_m[1 + offset], 2); + EXPECT_EQ(proving_key.q_m[2 + offset], 3); + EXPECT_EQ(proving_key.q_m[3 + offset], 4); + + EXPECT_EQ(proving_key.q_l[0 + offset], 5); + EXPECT_EQ(proving_key.q_l[1 + offset], 6); + EXPECT_EQ(proving_key.q_l[2 + offset], 7); + EXPECT_EQ(proving_key.q_l[3 + offset], 8); + + EXPECT_EQ(proving_key.q_r[0 + offset], 9); + EXPECT_EQ(proving_key.q_r[1 + offset], 10); + EXPECT_EQ(proving_key.q_r[2 + offset], 11); + EXPECT_EQ(proving_key.q_r[3 + offset], 12); + + EXPECT_EQ(proving_key.q_o[0 + offset], 13); + EXPECT_EQ(proving_key.q_o[1 + offset], 14); + EXPECT_EQ(proving_key.q_o[2 + offset], 15); + EXPECT_EQ(proving_key.q_o[3 + offset], 16); + + EXPECT_EQ(proving_key.q_c[0 + offset], 17); + EXPECT_EQ(proving_key.q_c[1 + offset], 18); + EXPECT_EQ(proving_key.q_c[2 + offset], 19); + EXPECT_EQ(proving_key.q_c[3 + offset], 20); } } // namespace proof_system::test_composer_lib diff --git a/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.hpp b/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.hpp index bf2e4e5676ca..73750323b9a2 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.hpp @@ -443,29 +443,6 @@ void compute_monomial_and_coset_fft_polynomials_from_lagrange(std::string label, } } -/** - * @brief Compute standard honk id polynomials and put them into cache - * - * @details Honk permutations involve using id and sigma polynomials to generate variable cycles. This function - * generates the id polynomials and puts them into polynomial cache, so that they can be used by the prover. - * - * @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 proving_key) // TODO(Cody): proving_key* and shared_ptr -{ - // Fill id polynomials with default values - // 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; - } - ++coset_idx; - } -} - /** * @brief Compute sigma permutation polynomials for standard plonk and put them in the polynomial cache * @@ -526,31 +503,6 @@ void compute_plonk_generalized_sigma_permutations(const typename Flavor::Circuit compute_monomial_and_coset_fft_polynomials_from_lagrange("id", key); } -/** - * @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 - * the witness vector and index within the vector. These values are permuted to account for wire copy cycles - * - * @tparam program_width - * @tparam CircuitBuilder - * @param circuit_constructor - * @param key - */ -// TODO(#293): Update this (and all similar functions) to take a smart pointer. -template -void compute_standard_honk_sigma_permutations(const typename Flavor::CircuitBuilder& circuit_constructor, - typename Flavor::ProvingKey* proving_key) -{ - // Compute the permutation table specifying which element becomes which - 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); -} - /** * @brief Compute generalized permutation sigmas and ids for ultra plonk * diff --git a/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.test.cpp index e45c630d0669..df0a67c537d1 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.test.cpp @@ -1,5 +1,5 @@ #include "barretenberg/proof_system/composer/permutation_lib.hpp" -#include "barretenberg/honk/flavor/standard.hpp" // TODO: needed? +#include "barretenberg/honk/flavor/ultra.hpp" #include "barretenberg/proof_system/composer/composer_lib.hpp" #include "barretenberg/proof_system/types/circuit_type.hpp" #include "barretenberg/srs/factories/crs_factory.hpp" @@ -10,7 +10,7 @@ namespace proof_system::test_composer_lib { class PermutationHelperTests : public ::testing::Test { protected: - using Flavor = honk::flavor::Standard; + using Flavor = honk::flavor::Ultra; using FF = typename Flavor::FF; using ProvingKey = Flavor::ProvingKey; Flavor::CircuitBuilder circuit_constructor; @@ -88,8 +88,6 @@ TEST_F(PermutationHelperTests, ComputeHonkStyleSigmaLagrangePolynomialsFromMappi 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); } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp b/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp index e723ea1c7924..c97c9e3c125c 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/flavor/flavor.hpp @@ -284,7 +284,7 @@ template concept IsPlonkFlavor = IsAnyOf; template -concept IsHonkFlavor = IsAnyOf; +concept IsHonkFlavor = IsAnyOf; template concept IsUltraFlavor = IsAnyOf; @@ -300,9 +300,7 @@ concept IsRecursiveFlavor = IsAnyOf, honk::flavor::GoblinUltraRecursive_>; -template concept IsGrumpkinFlavor = IsAnyOf; - -template concept StandardFlavor = IsAnyOf; +template concept IsGrumpkinFlavor = IsAnyOf; template concept UltraFlavor = IsAnyOf; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/arithmetic_relation.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/arithmetic_relation.hpp deleted file mode 100644 index b3bb4e84132f..000000000000 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/arithmetic_relation.hpp +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once -#include "relation_parameters.hpp" -#include "relation_types.hpp" - -namespace proof_system { - -template class ArithmeticRelationImpl { - public: - using FF = FF_; - - // 1 + polynomial degree of this relation - static constexpr size_t RELATION_LENGTH = 4; - - static constexpr size_t LEN_1 = 4; // arithmetic sub-relation - template