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 e3c7cf7fadf..e2727fb5f17 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/honk_bench/benchmark_utilities.hpp @@ -1,5 +1,8 @@ #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" #include "barretenberg/stdlib/hash/keccak/keccak.hpp" #include "barretenberg/stdlib/hash/sha256/sha256.hpp" @@ -192,11 +195,20 @@ void construct_proof_with_specified_num_gates(State& state, test_circuit_function(builder, num_gates); auto composer = Composer(); - auto ext_prover = composer.create_prover(builder); - state.ResumeTiming(); - - // Construct proof - auto proof = ext_prover.construct_proof(); + 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(); + + // Construct proof + auto proof = ext_prover.construct_proof(); + } } } @@ -224,11 +236,21 @@ void construct_proof_with_specified_num_iterations(State& state, test_circuit_function(builder, num_iterations); auto composer = Composer(); - auto ext_prover = composer.create_prover(builder); - state.ResumeTiming(); + 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(); - // Construct proof - auto proof = ext_prover.construct_proof(); + // Construct proof + auto proof = ext_prover.construct_proof(); + } } } diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/goblin_ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/goblin_ultra_composer.test.cpp index ff4249f37b1..07656ebd591 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/goblin_ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/goblin_ultra_composer.test.cpp @@ -27,7 +27,9 @@ class GoblinUltraHonkComposerTests : public ::testing::Test { */ TEST_F(GoblinUltraHonkComposerTests, SimpleCircuit) { - auto builder = UltraCircuitBuilder(); + using fr = barretenberg::fr; + using g1 = barretenberg::g1; + auto builder = proof_system::UltraCircuitBuilder(); // Define an arbitrary number of operations/gates size_t num_ecc_ops = 3; @@ -55,8 +57,9 @@ TEST_F(GoblinUltraHonkComposerTests, SimpleCircuit) } auto composer = GoblinUltraComposer(); - auto prover = composer.create_prover(builder); - auto verifier = composer.create_verifier(builder); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); + auto verifier = composer.create_verifier(instance); auto proof = prover.construct_proof(); bool verified = verifier.verify_proof(proof); EXPECT_EQ(verified, true); diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.cpp index 571ac034634..d7d8b55b1e8 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.cpp @@ -9,122 +9,30 @@ namespace proof_system::honk { -/** - * Compute witness polynomials (w_1, w_2, w_3, w_4). - * - * @details Fills 3 or 4 witness polynomials w_1, w_2, w_3, w_4 with the values of in-circuit variables. The beginning - * of w_1, w_2 polynomials is filled with public_input values. - * @return Witness with computed witness polynomials. - * - * @tparam Program settings needed to establish if w_4 is being used. - * */ template -void StandardComposer_::compute_witness(const CircuitBuilder& circuit_constructor, const size_t /*unused*/) +std::shared_ptr> StandardComposer_::create_instance(CircuitBuilder& circuit) { - if (computed_witness) { - return; - } - auto wire_polynomials = construct_wire_polynomials_base(circuit_constructor, dyadic_circuit_size); - - proving_key->w_l = wire_polynomials[0]; - proving_key->w_r = wire_polynomials[1]; - proving_key->w_o = wire_polynomials[2]; - - computed_witness = true; -} - -/** - * Compute proving key. - * Compute the polynomials q_l, q_r, etc. and sigma polynomial. - * - * @return Proving key with saved computed polynomials. - * */ - -template -std::shared_ptr StandardComposer_::compute_proving_key( - const CircuitBuilder& circuit_constructor) -{ - if (proving_key) { - return proving_key; - } - - // Construct a proving key - proving_key = std::make_shared(dyadic_circuit_size, num_public_inputs); - - // Compute lagrange selectors - construct_selector_polynomials(circuit_constructor, proving_key.get()); - - // Compute sigma polynomials (we should update that late) - compute_standard_honk_sigma_permutations(circuit_constructor, proving_key.get()); - compute_standard_honk_id_polynomials(proving_key.get()); - - compute_first_and_last_lagrange_polynomials(proving_key.get()); - - return proving_key; + auto instance = std::make_shared(circuit); + instance->commitment_key = compute_commitment_key(instance->proving_key->circuit_size); + return instance; } -/** - * Compute verification key consisting of selector precommitments. - * - * @return Pointer to created circuit verification key. - * */ template -std::shared_ptr StandardComposer_::compute_verification_key( - const CircuitBuilder& /*unused*/) +StandardVerifier_ StandardComposer_::create_verifier(std::shared_ptr instance) { - if (verification_key) { - return verification_key; - } - - verification_key = - std::make_shared(proving_key->circuit_size, proving_key->num_public_inputs); - - // Compute and store commitments to all precomputed polynomials - verification_key->q_m = commitment_key->commit(proving_key->q_m); - verification_key->q_l = commitment_key->commit(proving_key->q_l); - verification_key->q_r = commitment_key->commit(proving_key->q_r); - verification_key->q_o = commitment_key->commit(proving_key->q_o); - verification_key->q_c = commitment_key->commit(proving_key->q_c); - verification_key->sigma_1 = commitment_key->commit(proving_key->sigma_1); - verification_key->sigma_2 = commitment_key->commit(proving_key->sigma_2); - verification_key->sigma_3 = commitment_key->commit(proving_key->sigma_3); - verification_key->id_1 = commitment_key->commit(proving_key->id_1); - verification_key->id_2 = commitment_key->commit(proving_key->id_2); - verification_key->id_3 = commitment_key->commit(proving_key->id_3); - verification_key->lagrange_first = commitment_key->commit(proving_key->lagrange_first); - verification_key->lagrange_last = commitment_key->commit(proving_key->lagrange_last); - - return verification_key; -} - -template -StandardVerifier_ StandardComposer_::create_verifier(const CircuitBuilder& circuit_constructor) -{ - compute_verification_key(circuit_constructor); + 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(const CircuitBuilder& circuit_constructor) +StandardProver_ StandardComposer_::create_prover(std::shared_ptr instance) { - // Compute some key cicuit size paramaters - num_public_inputs = circuit_constructor.public_inputs.size(); - total_num_gates = circuit_constructor.num_gates + num_public_inputs; - dyadic_circuit_size = circuit_constructor.get_circuit_subgroup_size(total_num_gates); - - compute_proving_key(circuit_constructor); - compute_witness(circuit_constructor); - - compute_commitment_key(proving_key->circuit_size); - - StandardProver_ output_state(proving_key, commitment_key); + StandardProver_ output_state(instance); return output_state; } diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.hpp b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.hpp index 2117058d747..6763a4a29d1 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.hpp @@ -1,5 +1,6 @@ #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" @@ -18,6 +19,7 @@ template class StandardComposer_ { 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; @@ -29,14 +31,11 @@ template class StandardComposer_ { // The commitment key is passed to the prover but also used herein to compute the verfication key commitments std::shared_ptr commitment_key; - - size_t total_num_gates; // total num gates prior to computing dyadic size - size_t dyadic_circuit_size; // final dyadic circuit size - size_t num_public_inputs; + ; bool computed_witness = false; // TODO(Luke): use make_shared - // TODO(#637): design the crs factory better + // TODO(https://github.com/AztecProtocol/barretenberg/issues/637): design the crs factory better StandardComposer_() { if constexpr (IsGrumpkinFlavor) { @@ -64,18 +63,15 @@ template class StandardComposer_ { StandardComposer_& operator=(const StandardComposer_& other) = delete; ~StandardComposer_() = default; - std::shared_ptr compute_proving_key(const CircuitBuilder& circuit_constructor); - std::shared_ptr compute_verification_key(const CircuitBuilder& circuit_constructor); - - StandardVerifier_ create_verifier(const CircuitBuilder& circuit_constructor); - - StandardProver_ create_prover(const CircuitBuilder& circuit_constructor); + std::shared_ptr create_instance(CircuitBuilder& circuit); - void compute_witness(const CircuitBuilder& circuit_constructor, const size_t minimum_circuit_size = 0); + StandardProver_ create_prover(std::shared_ptr); + StandardVerifier_ create_verifier(std::shared_ptr); - void compute_commitment_key(size_t circuit_size) + std::shared_ptr compute_commitment_key(size_t circuit_size) { commitment_key = std::make_shared(circuit_size, crs_factory_); + return commitment_key; }; }; diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.test.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.test.cpp index bccb233a4f9..7a5efaede99 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/standard_composer.test.cpp @@ -18,7 +18,7 @@ using namespace proof_system::honk; #define TYPE_ALIASES \ using Flavor = TypeParam; \ using FF = typename Flavor::FF; \ - using CircuitBuilder = StandardCircuitBuilder_; \ + using CircuitBuilder = proof_system::StandardCircuitBuilder_; \ using Composer = StandardComposer_; namespace test_standard_honk_composer { @@ -28,7 +28,7 @@ template class StandardHonkComposerTests : public ::testing::T // TODO(640): The Standard Honk on Grumpkin test suite fails unless the SRS is initialised for every test. virtual void SetUp() { - if constexpr (IsGrumpkinFlavor) { + if constexpr (proof_system::IsGrumpkinFlavor) { barretenberg::srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); } else { barretenberg::srs::init_crs_factory("../srs_db/ignition"); @@ -50,15 +50,16 @@ TYPED_TEST_SUITE(StandardHonkComposerTests, FlavorTypes); TYPED_TEST(StandardHonkComposerTests, SigmaIDCorrectness) { TYPE_ALIASES - auto test_permutation = [](CircuitBuilder& circuit_constructor, Composer& composer) { - auto prover = composer.create_prover(circuit_constructor); - auto proving_key = prover.key; + 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 = circuit_constructor.get_public_inputs(); + auto public_inputs = builder.get_public_inputs(); auto num_public_inputs = public_inputs.size(); - auto num_gates = circuit_constructor.get_num_gates(); + auto num_gates = builder.get_num_gates(); // Using the same random beta and gamma as in the permutation argument FF beta = FF::random_element(); @@ -131,30 +132,30 @@ TYPED_TEST(StandardHonkComposerTests, SigmaIDCorrectness) EXPECT_EQ(left, right); }; - auto circuit_constructor = CircuitBuilder(); + auto builder = CircuitBuilder(); FF a = FF::one(); - uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t a_idx = builder.add_variable(a); FF b = FF::one(); FF c = a + b; - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); + uint32_t b_idx = builder.add_variable(b); + uint32_t c_idx = builder.add_variable(c); FF d = a + c; - uint32_t d_idx = circuit_constructor.add_public_variable(d); + uint32_t d_idx = builder.add_public_variable(d); - uint32_t e_idx = circuit_constructor.put_constant_variable(d); - circuit_constructor.assert_equal(e_idx, d_idx, ""); + uint32_t e_idx = builder.put_constant_variable(d); + builder.assert_equal(e_idx, d_idx, ""); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - circuit_constructor.create_add_gate({ d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - circuit_constructor.create_add_gate({ b_idx, a_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({ 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) { - circuit_constructor.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() }); } auto composer = Composer(); - test_permutation(circuit_constructor, composer); + test_permutation(builder, composer); } /** @@ -166,25 +167,25 @@ TYPED_TEST(StandardHonkComposerTests, LagrangeCorrectness) TYPE_ALIASES using Polynomial = typename Flavor::Polynomial; // Create a dummy circuit with a few gates - auto circuit_constructor = CircuitBuilder(); + auto builder = CircuitBuilder(); FF a = FF::one(); - uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t a_idx = builder.add_variable(a); FF b = FF::one(); FF c = a + b; FF d = a + c; - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); + 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++) { - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - circuit_constructor.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({ d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); } // Generate proving key auto composer = Composer(); - auto prover = composer.create_prover(circuit_constructor); - auto proving_key = prover.key; + 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); @@ -225,19 +226,17 @@ TYPED_TEST(StandardHonkComposerTests, AssertEquals) * @brief A function that creates a simple circuit with repeated gates, leading to large permutation cycles * */ - auto create_simple_circuit = [](auto& circuit_constructor) { + auto create_simple_circuit = [](auto& builder) { FF a = FF::one(); - uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t a_idx = builder.add_variable(a); FF b = FF::one(); FF c = a + b; - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); + uint32_t b_idx = builder.add_variable(b); + uint32_t c_idx = builder.add_variable(c); for (size_t i = 0; i < 10; i++) { - circuit_constructor.create_add_gate( - { a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - circuit_constructor.create_add_gate( - { b_idx, a_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() }); } return std::make_tuple(a_idx, b_idx); }; @@ -245,10 +244,11 @@ TYPED_TEST(StandardHonkComposerTests, AssertEquals) * @brief A function that computes the largest cycle from the sigma permutation generated by the composer * */ - auto get_maximum_cycle = [](auto& circuit_constructor, auto& composer) { + auto get_maximum_cycle = [](auto& builder, auto& composer) { // Compute the proving key for sigma polynomials - auto prover = composer.create_prover(circuit_constructor); - auto proving_key = prover.key; + 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(); @@ -302,23 +302,23 @@ TYPED_TEST(StandardHonkComposerTests, AssertEquals) }; // Get 2 circuits - auto circuit_constructor_no_assert_equal = CircuitBuilder(); - auto circuit_constructor_with_assert_equal = CircuitBuilder(); + auto builder_no_assert_equal = CircuitBuilder(); + auto builder_with_assert_equal = CircuitBuilder(); // Construct circuits - create_simple_circuit(circuit_constructor_no_assert_equal); - auto assert_eq_params = create_simple_circuit(circuit_constructor_with_assert_equal); + 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 - circuit_constructor_with_assert_equal.assert_equal(std::get<0>(assert_eq_params), - std::get<1>(assert_eq_params), - "Equality asssertion in standard honk composer test"); + 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(circuit_constructor_with_assert_equal, composer_with_assert_equal), - get_maximum_cycle(circuit_constructor_no_assert_equal, composer_no_assert_equal) * 2); + 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) @@ -326,41 +326,41 @@ TYPED_TEST(StandardHonkComposerTests, VerificationKeyCreation) TYPE_ALIASES // Create a composer and a dummy circuit with a few gates - auto circuit_constructor = CircuitBuilder(); + auto builder = CircuitBuilder(); FF a = FF::one(); - uint32_t a_idx = circuit_constructor.add_variable(a); + uint32_t a_idx = builder.add_variable(a); FF b = FF::one(); FF c = a + b; FF d = a + c; - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); + 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++) { - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - circuit_constructor.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({ d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); } auto composer = Composer(); - composer.create_prover(circuit_constructor); - auto verification_key = composer.compute_verification_key(circuit_constructor); + 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(), circuit_constructor.selectors.size() + composer.NUM_WIRES * 2 + 2); + EXPECT_EQ(verification_key->size(), builder.selectors.size() + composer.NUM_WIRES * 2 + 2); } TYPED_TEST(StandardHonkComposerTests, BaseCase) { TYPE_ALIASES - auto circuit_constructor = CircuitBuilder(); + auto builder = CircuitBuilder(); FF a = 1; - circuit_constructor.add_variable(a); + builder.add_variable(a); auto composer = Composer(); - auto prover = composer.create_prover(circuit_constructor); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(circuit_constructor); + auto verifier = composer.create_verifier(instance); bool verified = verifier.verify_proof(proof); ASSERT_TRUE(verified); } @@ -369,29 +369,33 @@ TYPED_TEST(StandardHonkComposerTests, TwoGates) { TYPE_ALIASES auto run_test = [](bool expect_verified) { - auto circuit_constructor = CircuitBuilder(); + 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 = circuit_constructor.add_variable(1); + w_l_1_idx = builder.add_variable(1); } else { - w_l_1_idx = circuit_constructor.add_variable(0); + w_l_1_idx = builder.add_variable(0); } - uint32_t w_r_1_idx = circuit_constructor.add_variable(1); - uint32_t w_o_1_idx = circuit_constructor.add_variable(2); - circuit_constructor.create_add_gate({ w_l_1_idx, w_r_1_idx, w_o_1_idx, 1, 1, -1, 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 = circuit_constructor.add_variable(2); - uint32_t w_r_2_idx = circuit_constructor.add_variable(2); - uint32_t w_o_2_idx = circuit_constructor.add_variable(4); - circuit_constructor.create_mul_gate({ w_l_2_idx, w_r_2_idx, w_o_2_idx, 1, -1, 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 prover = composer.create_prover(circuit_constructor); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(circuit_constructor); + auto verifier = composer.create_verifier(instance); bool verified = verifier.verify_proof(proof); EXPECT_EQ(verified, expect_verified); @@ -405,10 +409,15 @@ TYPED_TEST(StandardHonkComposerTests, SumcheckEvaluations) { TYPE_ALIASES auto run_test = [](bool expected_result) { - auto circuit_constructor = CircuitBuilder(); + 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 = circuit_constructor.add_public_variable(a); + uint32_t a_idx = builder.add_public_variable(a); FF b = FF::one(); FF c = a + b; FF d = a + c; @@ -417,20 +426,19 @@ TYPED_TEST(StandardHonkComposerTests, SumcheckEvaluations) d += 1; }; - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); - for (size_t i = 0; i < 16; i++) { - circuit_constructor.create_add_gate( - { a_idx, b_idx, c_idx, FF::one(), FF::one(), FF::neg_one(), FF::zero() }); - circuit_constructor.create_add_gate( - { d_idx, c_idx, a_idx, FF::one(), FF::neg_one(), FF::neg_one(), FF::zero() }); + 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 prover = composer.create_prover(circuit_constructor); + auto instance = composer.create_instance(builder); + auto prover = composer.create_prover(instance); auto proof = prover.construct_proof(); - auto verifier = composer.create_verifier(circuit_constructor); + auto verifier = composer.create_verifier(instance); bool verified = verifier.verify_proof(proof); ASSERT_EQ(verified, expected_result); }; diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.cpp index 6d088299f4b..93aba6f71bf 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.cpp @@ -1,356 +1,67 @@ -#include "ultra_composer.hpp" -#include "barretenberg/honk/proof_system/ultra_prover.hpp" +#include "barretenberg/honk/composer/ultra_composer.hpp" +#include "barretenberg/honk/proof_system/grand_product_library.hpp" #include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" #include "barretenberg/proof_system/composer/composer_lib.hpp" #include "barretenberg/proof_system/composer/permutation_lib.hpp" namespace proof_system::honk { -/** - * @brief Helper method to compute quantities like total number of gates and dyadic circuit size - * - * @tparam Flavor - * @param circuit_constructor - */ template -void UltraComposer_::compute_circuit_size_parameters(CircuitBuilder& circuit_constructor) +std::shared_ptr> UltraComposer_::create_instance(CircuitBuilder& 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_constructor.lookup_tables) { - tables_size += table.size; - lookups_size += table.lookup_gates.size(); - } - - // Get num conventional gates, num public inputs and num Goblin style ECC op gates - const size_t num_gates = circuit_constructor.num_gates; - num_public_inputs = circuit_constructor.public_inputs.size(); - num_ecc_op_gates = circuit_constructor.num_ecc_op_gates; - - // minimum circuit size due to the length of lookups plus tables - const size_t minimum_circuit_size_due_to_lookups = tables_size + lookups_size + num_zero_rows; - - // number of populated rows in the execution trace - size_t num_rows_populated_in_execution_trace = num_zero_rows + num_ecc_op_gates + num_public_inputs + num_gates; - - // The number of gates is max(lookup gates + tables, rows already populated in trace) + 1, where the +1 is due to - // addition of a "zero row" at top of the execution trace to ensure wires and other polys are shiftable. - total_num_gates = std::max(minimum_circuit_size_due_to_lookups, num_rows_populated_in_execution_trace); - - // Next power of 2 - dyadic_circuit_size = circuit_constructor.get_circuit_subgroup_size(total_num_gates); -} - -/** - * @brief Compute witness polynomials - * - */ -template void UltraComposer_::compute_witness(CircuitBuilder& circuit_constructor) -{ - if (computed_witness) { - return; - } - - // Construct the conventional wire polynomials - auto wire_polynomials = construct_wire_polynomials_base(circuit_constructor, dyadic_circuit_size); - - 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 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_constructor.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()); -#else - 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; - } - } - - // 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_constructor.memory_read_records.begin(), - circuit_constructor.memory_read_records.end(), - std::back_inserter(proving_key->memory_read_records), - add_public_inputs_offset); - std::transform(circuit_constructor.memory_write_records.begin(), - circuit_constructor.memory_write_records.end(), - std::back_inserter(proving_key->memory_write_records), - add_public_inputs_offset); - - computed_witness = true; -} - -/** - * @brief Construct Goblin style ECC op wire polynomials - * @details The Ecc op wire values are assumed to have already been stored in the corresponding block of the - * conventional wire polynomials. The values for the ecc op wire polynomials are set based on those values. - * - * @tparam Flavor - * @param wire_polynomials - */ -template void UltraComposer_::construct_ecc_op_wire_polynomials(auto& wire_polynomials) -{ - std::array op_wire_polynomials; - for (auto& poly : op_wire_polynomials) { - poly = polynomial(dyadic_circuit_size); - } - - // The ECC op wires are constructed to contain the op data on the appropriate range and to vanish everywhere else. - // The op data is assumed to have already been stored at the correct location in the convetional wires so the data - // can simply be copied over directly. - const size_t op_wire_offset = Flavor::has_zero_row ? 1 : 0; - for (size_t poly_idx = 0; poly_idx < Flavor::NUM_WIRES; ++poly_idx) { - for (size_t i = 0; i < num_ecc_op_gates; ++i) { - size_t idx = i + op_wire_offset; - op_wire_polynomials[poly_idx][idx] = wire_polynomials[poly_idx][idx]; - } - } - - proving_key->ecc_op_wire_1 = op_wire_polynomials[0]; - proving_key->ecc_op_wire_2 = op_wire_polynomials[1]; - proving_key->ecc_op_wire_3 = op_wire_polynomials[2]; - proving_key->ecc_op_wire_4 = op_wire_polynomials[3]; + circuit.add_gates_to_ensure_all_polys_are_non_zero(); + circuit.finalize_circuit(); + auto instance = std::make_shared(circuit); + instance->commitment_key = compute_commitment_key(instance->proving_key->circuit_size); + return instance; } template -UltraProver_ UltraComposer_::create_prover(CircuitBuilder& circuit_constructor) +UltraProver_ UltraComposer_::create_prover(std::shared_ptr instance) { - circuit_constructor.add_gates_to_ensure_all_polys_are_non_zero(); - circuit_constructor.finalize_circuit(); - - // Compute total number of gates, dyadic circuit size, etc. - compute_circuit_size_parameters(circuit_constructor); - - compute_proving_key(circuit_constructor); - compute_witness(circuit_constructor); - - compute_commitment_key(proving_key->circuit_size); - - UltraProver_ output_state(proving_key, commitment_key); + UltraProver_ output_state(instance); return output_state; } -/** - * Create verifier: compute verification key, - * initialize verifier with it and an initial manifest and initialize commitment_scheme. - * - * @return The verifier. - * */ template -UltraVerifier_ UltraComposer_::create_verifier(const CircuitBuilder& circuit_constructor) +UltraVerifier_ UltraComposer_::create_verifier(std::shared_ptr instance) { - auto verification_key = compute_verification_key(circuit_constructor); - + auto verification_key = instance->compute_verification_key(); UltraVerifier_ 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 -std::shared_ptr UltraComposer_::compute_proving_key( - const CircuitBuilder& circuit_constructor) +ProtoGalaxyProver_ UltraComposer_::create_folding_prover( + std::vector> instances) { - if (proving_key) { - return proving_key; + uint32_t idx = 0; + for (const auto& inst : instances) { + inst->index = idx; + idx++; } + ProtoGalaxyProver_ output_state(instances); - proving_key = std::make_shared(dyadic_circuit_size, num_public_inputs); - - construct_selector_polynomials(circuit_constructor, proving_key.get()); - - compute_honk_generalized_sigma_permutations(circuit_constructor, 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); - - 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. - - 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_constructor.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 - - 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->contains_recursive_proof = contains_recursive_proof; - - if constexpr (IsGoblinFlavor) { - proving_key->num_ecc_op_gates = num_ecc_op_gates; - } - - return proving_key; + return output_state; } -/** - * Compute verification key consisting of selector precommitments. - * - * @return Pointer to created circuit verification key. - * */ template -std::shared_ptr UltraComposer_::compute_verification_key( - const CircuitBuilder& circuit_constructor) +ProtoGalaxyVerifier_ UltraComposer_::create_folding_verifier( + std::vector> instances) { - if (verification_key) { - return verification_key; - } - - if (!proving_key) { - compute_proving_key(circuit_constructor); + std::vector> vks; + for (const auto& inst : instances) { + vks.emplace_back(inst->compute_verification_key()); } + ProtoGalaxyVerifier_ output_state(vks); - verification_key = - std::make_shared(proving_key->circuit_size, proving_key->num_public_inputs); - - // Compute and store commitments to all precomputed polynomials - verification_key->q_m = commitment_key->commit(proving_key->q_m); - verification_key->q_l = commitment_key->commit(proving_key->q_l); - verification_key->q_r = commitment_key->commit(proving_key->q_r); - verification_key->q_o = commitment_key->commit(proving_key->q_o); - verification_key->q_4 = commitment_key->commit(proving_key->q_4); - verification_key->q_c = commitment_key->commit(proving_key->q_c); - 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_1 = commitment_key->commit(proving_key->sigma_1); - verification_key->sigma_2 = commitment_key->commit(proving_key->sigma_2); - verification_key->sigma_3 = commitment_key->commit(proving_key->sigma_3); - verification_key->sigma_4 = commitment_key->commit(proving_key->sigma_4); - verification_key->id_1 = commitment_key->commit(proving_key->id_1); - verification_key->id_2 = commitment_key->commit(proving_key->id_2); - verification_key->id_3 = commitment_key->commit(proving_key->id_3); - 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); - verification_key->lagrange_first = commitment_key->commit(proving_key->lagrange_first); - verification_key->lagrange_last = commitment_key->commit(proving_key->lagrange_last); - - // 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()); - - // verification_key->contains_recursive_proof = contains_recursive_proof; - - return verification_key; + return output_state; } + template class UltraComposer_; template class UltraComposer_; template class UltraComposer_; diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.hpp b/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.hpp index ec9c39b9149..0a33f748ba3 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.hpp @@ -1,5 +1,7 @@ #pragma once - +#include "barretenberg/honk/instance/prover_instance.hpp" +#include "barretenberg/honk/proof_system/protogalaxy_prover.hpp" +#include "barretenberg/honk/proof_system/protogalaxy_verifier.hpp" #include "barretenberg/honk/proof_system/ultra_prover.hpp" #include "barretenberg/honk/proof_system/ultra_verifier.hpp" #include "barretenberg/proof_system/composer/composer_lib.hpp" @@ -20,6 +22,7 @@ template class UltraComposer_ { using PCS = typename Flavor::PCS; using CommitmentKey = typename Flavor::CommitmentKey; using VerifierCommitmentKey = typename Flavor::VerifierCommitmentKey; + using Instance = ProverInstance_; // offset due to placing zero wires at the start of execution trace static constexpr size_t num_zero_rows = Flavor::has_zero_row ? 1 : 0; @@ -31,20 +34,9 @@ template class UltraComposer_ { // 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; - std::vector recursive_proof_public_input_indices; - bool contains_recursive_proof = false; - bool computed_witness = false; - size_t total_num_gates = 0; // num_gates + num_pub_inputs + tables + zero_row_offset (used to compute dyadic size) - size_t dyadic_circuit_size = 0; // final power-of-2 circuit size - size_t lookups_size = 0; // total number of lookup gates - size_t tables_size = 0; // total number of table entries - size_t num_public_inputs = 0; - size_t num_ecc_op_gates = 0; - UltraComposer_() { crs_factory_ = barretenberg::srs::get_crs_factory(); } explicit UltraComposer_(std::shared_ptr> crs_factory) @@ -62,24 +54,23 @@ template class UltraComposer_ { UltraComposer_& operator=(UltraComposer_ const& other) noexcept = default; ~UltraComposer_() = default; - std::shared_ptr compute_proving_key(const CircuitBuilder& circuit_constructor); - std::shared_ptr compute_verification_key(const CircuitBuilder& circuit_constructor); - - void compute_circuit_size_parameters(CircuitBuilder& circuit_constructor); - - void compute_witness(CircuitBuilder& circuit_constructor); + std::shared_ptr compute_commitment_key(size_t circuit_size) + { + if (commitment_key) { + return commitment_key; + } - void construct_ecc_op_wire_polynomials(auto&); + commitment_key = std::make_shared(circuit_size, crs_factory_); + return commitment_key; + }; - UltraProver_ create_prover(CircuitBuilder& circuit_constructor); - UltraVerifier_ create_verifier(const CircuitBuilder& circuit_constructor); + std::shared_ptr create_instance(CircuitBuilder& circuit); - void add_table_column_selector_poly_to_proving_key(polynomial& small, const std::string& tag); + UltraProver_ create_prover(std::shared_ptr); + UltraVerifier_ create_verifier(std::shared_ptr); - void compute_commitment_key(size_t circuit_size) - { - commitment_key = std::make_shared(circuit_size, crs_factory_); - }; + ProtoGalaxyProver_ create_folding_prover(std::vector>); + ProtoGalaxyVerifier_ create_folding_verifier(std::vector>); }; extern template class UltraComposer_; // TODO: the UltraGrumpkin flavor still works on BN254 because plookup needs to be templated to be able to construct diff --git a/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.test.cpp b/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.test.cpp index ec3196186ef..65a15a2249f 100644 --- a/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/composer/ultra_composer.test.cpp @@ -1,12 +1,5 @@ -#include -#include -#include -#include -#include - -#include "barretenberg/common/log.hpp" #include "barretenberg/honk/composer/ultra_composer.hpp" -#include "barretenberg/honk/proof_system/prover.hpp" +#include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/honk/proof_system/ultra_prover.hpp" #include "barretenberg/honk/sumcheck/sumcheck_round.hpp" #include "barretenberg/honk/utils/grand_product_delta.hpp" @@ -15,6 +8,11 @@ #include "barretenberg/proof_system/plookup_tables/types.hpp" #include "barretenberg/proof_system/relations/permutation_relation.hpp" #include "barretenberg/proof_system/relations/relation_parameters.hpp" +#include +#include +#include +#include +#include using namespace proof_system::honk; @@ -24,19 +22,20 @@ namespace { auto& engine = numeric::random::get_debug_engine(); } -std::vector add_variables(auto& circuit_constructor, std::vector variables) +std::vector add_variables(auto& circuit_builder, std::vector variables) { std::vector res; for (size_t i = 0; i < variables.size(); i++) { - res.emplace_back(circuit_constructor.add_variable(variables[i])); + res.emplace_back(circuit_builder.add_variable(variables[i])); } return res; } -void prove_and_verify(auto& circuit_constructor, auto& composer, bool expected_result) +void prove_and_verify(auto& circuit_builder, auto& composer, bool expected_result) { - auto prover = composer.create_prover(circuit_constructor); - auto verifier = composer.create_verifier(circuit_constructor); + auto instance = composer.create_instance(circuit_builder); + auto prover = composer.create_prover(instance); + auto verifier = composer.create_verifier(instance); auto proof = prover.construct_proof(); bool verified = verifier.verify_proof(proof); EXPECT_EQ(verified, expected_result); @@ -65,21 +64,23 @@ class UltraHonkComposerTests : public ::testing::Test { */ TEST_F(UltraHonkComposerTests, ANonZeroPolynomialIsAGoodPolynomial) { - auto circuit_constructor = UltraCircuitBuilder(); + auto circuit_builder = proof_system::UltraCircuitBuilder(); auto composer = UltraComposer(); - auto prover = composer.create_prover(circuit_constructor); + auto instance = composer.create_instance(circuit_builder); + auto prover = composer.create_prover(instance); auto proof = prover.construct_proof(); + auto proving_key = instance->proving_key; - for (auto& poly : prover.key->get_selectors()) { + for (auto& poly : proving_key->get_selectors()) { ensure_non_zero(poly); } - for (auto& poly : prover.key->get_table_polynomials()) { + for (auto& poly : proving_key->get_table_polynomials()) { ensure_non_zero(poly); } - for (auto& poly : prover.key->get_wires()) { + for (auto& poly : proving_key->get_wires()) { ensure_non_zero(poly); } } @@ -90,7 +91,8 @@ TEST_F(UltraHonkComposerTests, ANonZeroPolynomialIsAGoodPolynomial) */ TEST_F(UltraHonkComposerTests, PublicInputs) { - auto builder = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto builder = proof_system::UltraCircuitBuilder(); size_t num_gates = 10; // Add some arbitrary arithmetic gates that utilize public inputs @@ -114,7 +116,8 @@ TEST_F(UltraHonkComposerTests, PublicInputs) TEST_F(UltraHonkComposerTests, XorConstraint) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); uint32_t left_value = engine.get_random_uint32(); uint32_t right_value = engine.get_random_uint32(); @@ -122,8 +125,8 @@ TEST_F(UltraHonkComposerTests, XorConstraint) fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = circuit_constructor.add_variable(left_witness_value); - uint32_t right_witness_index = circuit_constructor.add_variable(right_witness_value); + uint32_t left_witness_index = circuit_builder.add_variable(left_witness_value); + uint32_t right_witness_index = circuit_builder.add_variable(right_witness_value); uint32_t xor_result_expected = left_value ^ right_value; @@ -133,29 +136,30 @@ TEST_F(UltraHonkComposerTests, XorConstraint) [0]; // The zeroth index in the 3rd column is the fully accumulated xor EXPECT_EQ(xor_result, xor_result_expected); - circuit_constructor.create_gates_from_plookup_accumulators( + circuit_builder.create_gates_from_plookup_accumulators( plookup::MultiTableId::UINT32_XOR, lookup_accumulators, left_witness_index, right_witness_index); auto composer = UltraComposer(barretenberg::srs::get_crs_factory()); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, create_gates_from_plookup_accumulators) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); barretenberg::fr input_value = fr::random_element(); const fr input_hi = uint256_t(input_value).slice(126, 256); const fr input_lo = uint256_t(input_value).slice(0, 126); - const auto input_hi_index = circuit_constructor.add_variable(input_hi); - const auto input_lo_index = circuit_constructor.add_variable(input_lo); + const auto input_hi_index = circuit_builder.add_variable(input_hi); + const auto input_lo_index = circuit_builder.add_variable(input_lo); const auto sequence_data_hi = plookup::get_lookup_accumulators(plookup::MultiTableId::PEDERSEN_LEFT_HI, input_hi); const auto sequence_data_lo = plookup::get_lookup_accumulators(plookup::MultiTableId::PEDERSEN_LEFT_LO, input_lo); - const auto lookup_witnesses_hi = circuit_constructor.create_gates_from_plookup_accumulators( + const auto lookup_witnesses_hi = circuit_builder.create_gates_from_plookup_accumulators( plookup::MultiTableId::PEDERSEN_LEFT_HI, sequence_data_hi, input_hi_index); - const auto lookup_witnesses_lo = circuit_constructor.create_gates_from_plookup_accumulators( + const auto lookup_witnesses_lo = circuit_builder.create_gates_from_plookup_accumulators( plookup::MultiTableId::PEDERSEN_LEFT_LO, sequence_data_lo, input_lo_index); std::vector expected_x; @@ -203,29 +207,31 @@ TEST_F(UltraHonkComposerTests, create_gates_from_plookup_accumulators) } size_t hi_shift = 126; - const fr hi_cumulative = circuit_constructor.get_variable(lookup_witnesses_hi[plookup::ColumnIdx::C1][0]); + const fr hi_cumulative = circuit_builder.get_variable(lookup_witnesses_hi[plookup::ColumnIdx::C1][0]); for (size_t i = 0; i < num_lookups_lo; ++i) { const fr hi_mult = fr(uint256_t(1) << hi_shift); - EXPECT_EQ(circuit_constructor.get_variable(lookup_witnesses_lo[plookup::ColumnIdx::C1][i]) + + EXPECT_EQ(circuit_builder.get_variable(lookup_witnesses_lo[plookup::ColumnIdx::C1][i]) + (hi_cumulative * hi_mult), expected_scalars[i]); - EXPECT_EQ(circuit_constructor.get_variable(lookup_witnesses_lo[plookup::ColumnIdx::C2][i]), expected_x[i]); - EXPECT_EQ(circuit_constructor.get_variable(lookup_witnesses_lo[plookup::ColumnIdx::C3][i]), expected_y[i]); + EXPECT_EQ(circuit_builder.get_variable(lookup_witnesses_lo[plookup::ColumnIdx::C2][i]), expected_x[i]); + EXPECT_EQ(circuit_builder.get_variable(lookup_witnesses_lo[plookup::ColumnIdx::C3][i]), expected_y[i]); hi_shift -= crypto::pedersen_hash::lookup::BITS_PER_TABLE; } for (size_t i = 0; i < num_lookups_hi; ++i) { - EXPECT_EQ(circuit_constructor.get_variable(lookup_witnesses_hi[plookup::ColumnIdx::C1][i]), + EXPECT_EQ(circuit_builder.get_variable(lookup_witnesses_hi[plookup::ColumnIdx::C1][i]), expected_scalars[i + num_lookups_lo]); - EXPECT_EQ(circuit_constructor.get_variable(lookup_witnesses_hi[plookup::ColumnIdx::C2][i]), + EXPECT_EQ(circuit_builder.get_variable(lookup_witnesses_hi[plookup::ColumnIdx::C2][i]), expected_x[i + num_lookups_lo]); - EXPECT_EQ(circuit_constructor.get_variable(lookup_witnesses_hi[plookup::ColumnIdx::C3][i]), + EXPECT_EQ(circuit_builder.get_variable(lookup_witnesses_hi[plookup::ColumnIdx::C3][i]), expected_y[i + num_lookups_lo]); } auto composer = UltraComposer(); - auto prover = composer.create_prover(circuit_constructor); - auto verifier = composer.create_verifier(circuit_constructor); + auto instance = composer.create_instance(circuit_builder); + auto prover = composer.create_prover(instance); + auto verifier = composer.create_verifier(instance); + auto proof = prover.construct_proof(); bool result = verifier.verify_proof(proof); @@ -235,203 +241,210 @@ TEST_F(UltraHonkComposerTests, create_gates_from_plookup_accumulators) TEST_F(UltraHonkComposerTests, test_no_lookup_proof) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); for (size_t i = 0; i < 16; ++i) { for (size_t j = 0; j < 16; ++j) { uint64_t left = static_cast(j); uint64_t right = static_cast(i); - uint32_t left_idx = circuit_constructor.add_variable(fr(left)); - uint32_t right_idx = circuit_constructor.add_variable(fr(right)); - uint32_t result_idx = circuit_constructor.add_variable(fr(left ^ right)); + uint32_t left_idx = circuit_builder.add_variable(fr(left)); + uint32_t right_idx = circuit_builder.add_variable(fr(right)); + uint32_t result_idx = circuit_builder.add_variable(fr(left ^ right)); uint32_t add_idx = - circuit_constructor.add_variable(fr(left) + fr(right) + circuit_constructor.get_variable(result_idx)); - circuit_constructor.create_big_add_gate( + circuit_builder.add_variable(fr(left) + fr(right) + circuit_builder.get_variable(result_idx)); + circuit_builder.create_big_add_gate( { left_idx, right_idx, result_idx, add_idx, fr(1), fr(1), fr(1), fr(-1), fr(0) }); } } auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, test_elliptic_gate) { typedef grumpkin::g1::affine_element affine_element; typedef grumpkin::g1::element element; - auto circuit_constructor = UltraCircuitBuilder(); + auto circuit_builder = proof_system::UltraCircuitBuilder(); affine_element p1 = crypto::generators::get_generator_data({ 0, 0 }).generator; affine_element p2 = crypto::generators::get_generator_data({ 0, 1 }).generator; affine_element p3(element(p1) + element(p2)); - uint32_t x1 = circuit_constructor.add_variable(p1.x); - uint32_t y1 = circuit_constructor.add_variable(p1.y); - uint32_t x2 = circuit_constructor.add_variable(p2.x); - uint32_t y2 = circuit_constructor.add_variable(p2.y); - uint32_t x3 = circuit_constructor.add_variable(p3.x); - uint32_t y3 = circuit_constructor.add_variable(p3.y); + uint32_t x1 = circuit_builder.add_variable(p1.x); + uint32_t y1 = circuit_builder.add_variable(p1.y); + uint32_t x2 = circuit_builder.add_variable(p2.x); + uint32_t y2 = circuit_builder.add_variable(p2.y); + uint32_t x3 = circuit_builder.add_variable(p3.x); + uint32_t y3 = circuit_builder.add_variable(p3.y); - circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1, 1 }); + circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1, 1 }); grumpkin::fq beta = grumpkin::fq::cube_root_of_unity(); affine_element p2_endo = p2; p2_endo.x *= beta; p3 = affine_element(element(p1) + element(p2_endo)); - x3 = circuit_constructor.add_variable(p3.x); - y3 = circuit_constructor.add_variable(p3.y); - circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, beta, 1 }); + x3 = circuit_builder.add_variable(p3.x); + y3 = circuit_builder.add_variable(p3.y); + circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, beta, 1 }); p2_endo.x *= beta; p3 = affine_element(element(p1) - element(p2_endo)); - x3 = circuit_constructor.add_variable(p3.x); - y3 = circuit_constructor.add_variable(p3.y); - circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, beta.sqr(), -1 }); + x3 = circuit_builder.add_variable(p3.x); + y3 = circuit_builder.add_variable(p3.y); + circuit_builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, beta.sqr(), -1 }); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); fr a = fr::random_element(); fr b = -a; - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(b); - auto c_idx = circuit_constructor.add_variable(b); - auto d_idx = circuit_constructor.add_variable(a); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(b); + auto d_idx = circuit_builder.add_variable(a); - circuit_constructor.create_add_gate( - { a_idx, b_idx, circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), fr::zero() }); - circuit_constructor.create_add_gate( - { c_idx, d_idx, circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), fr::zero() }); + circuit_builder.create_add_gate( + { a_idx, b_idx, circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), fr::zero() }); + circuit_builder.create_add_gate( + { c_idx, d_idx, circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), fr::zero() }); - circuit_constructor.create_tag(1, 2); - circuit_constructor.create_tag(2, 1); + circuit_builder.create_tag(1, 2); + circuit_builder.create_tag(2, 1); - circuit_constructor.assign_tag(a_idx, 1); - circuit_constructor.assign_tag(b_idx, 1); - circuit_constructor.assign_tag(c_idx, 2); - circuit_constructor.assign_tag(d_idx, 2); + circuit_builder.assign_tag(a_idx, 1); + circuit_builder.assign_tag(b_idx, 1); + circuit_builder.assign_tag(c_idx, 2); + circuit_builder.assign_tag(d_idx, 2); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, non_trivial_tag_permutation_and_cycles) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); fr a = fr::random_element(); fr c = -a; - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(a); - circuit_constructor.assert_equal(a_idx, b_idx); - auto c_idx = circuit_constructor.add_variable(c); - auto d_idx = circuit_constructor.add_variable(c); - circuit_constructor.assert_equal(c_idx, d_idx); - auto e_idx = circuit_constructor.add_variable(a); - auto f_idx = circuit_constructor.add_variable(a); - circuit_constructor.assert_equal(e_idx, f_idx); - auto g_idx = circuit_constructor.add_variable(c); - auto h_idx = circuit_constructor.add_variable(c); - circuit_constructor.assert_equal(g_idx, h_idx); - - circuit_constructor.create_tag(1, 2); - circuit_constructor.create_tag(2, 1); - - circuit_constructor.assign_tag(a_idx, 1); - circuit_constructor.assign_tag(c_idx, 1); - circuit_constructor.assign_tag(e_idx, 2); - circuit_constructor.assign_tag(g_idx, 2); - - circuit_constructor.create_add_gate( - { b_idx, a_idx, circuit_constructor.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); - circuit_constructor.create_add_gate( - { c_idx, g_idx, circuit_constructor.zero_idx, fr::one(), -fr::one(), fr::zero(), fr::zero() }); - circuit_constructor.create_add_gate( - { e_idx, f_idx, circuit_constructor.zero_idx, fr::one(), -fr::one(), fr::zero(), fr::zero() }); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(a); + circuit_builder.assert_equal(a_idx, b_idx); + auto c_idx = circuit_builder.add_variable(c); + auto d_idx = circuit_builder.add_variable(c); + circuit_builder.assert_equal(c_idx, d_idx); + auto e_idx = circuit_builder.add_variable(a); + auto f_idx = circuit_builder.add_variable(a); + circuit_builder.assert_equal(e_idx, f_idx); + auto g_idx = circuit_builder.add_variable(c); + auto h_idx = circuit_builder.add_variable(c); + circuit_builder.assert_equal(g_idx, h_idx); + + circuit_builder.create_tag(1, 2); + circuit_builder.create_tag(2, 1); + + circuit_builder.assign_tag(a_idx, 1); + circuit_builder.assign_tag(c_idx, 1); + circuit_builder.assign_tag(e_idx, 2); + circuit_builder.assign_tag(g_idx, 2); + + circuit_builder.create_add_gate( + { b_idx, a_idx, circuit_builder.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); + circuit_builder.create_add_gate( + { c_idx, g_idx, circuit_builder.zero_idx, fr::one(), -fr::one(), fr::zero(), fr::zero() }); + circuit_builder.create_add_gate( + { e_idx, f_idx, circuit_builder.zero_idx, fr::one(), -fr::one(), fr::zero(), fr::zero() }); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, bad_tag_permutation) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); fr a = fr::random_element(); fr b = -a; - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(b); - auto c_idx = circuit_constructor.add_variable(b); - auto d_idx = circuit_constructor.add_variable(a + 1); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(b); + auto d_idx = circuit_builder.add_variable(a + 1); - circuit_constructor.create_add_gate({ a_idx, b_idx, circuit_constructor.zero_idx, 1, 1, 0, 0 }); - circuit_constructor.create_add_gate({ c_idx, d_idx, circuit_constructor.zero_idx, 1, 1, 0, -1 }); + circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, 1, 1, 0, 0 }); + circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx, 1, 1, 0, -1 }); - circuit_constructor.create_tag(1, 2); - circuit_constructor.create_tag(2, 1); + circuit_builder.create_tag(1, 2); + circuit_builder.create_tag(2, 1); - circuit_constructor.assign_tag(a_idx, 1); - circuit_constructor.assign_tag(b_idx, 1); - circuit_constructor.assign_tag(c_idx, 2); - circuit_constructor.assign_tag(d_idx, 2); + circuit_builder.assign_tag(a_idx, 1); + circuit_builder.assign_tag(b_idx, 1); + circuit_builder.assign_tag(c_idx, 2); + circuit_builder.assign_tag(d_idx, 2); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } // same as above but with turbocomposer to check reason of failue is really tag mismatch TEST_F(UltraHonkComposerTests, bad_tag_turbo_permutation) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); fr a = fr::random_element(); fr b = -a; - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(b); - auto c_idx = circuit_constructor.add_variable(b); - auto d_idx = circuit_constructor.add_variable(a + 1); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(b); + auto d_idx = circuit_builder.add_variable(a + 1); - circuit_constructor.create_add_gate({ a_idx, b_idx, circuit_constructor.zero_idx, 1, 1, 0, 0 }); - circuit_constructor.create_add_gate({ c_idx, d_idx, circuit_constructor.zero_idx, 1, 1, 0, -1 }); + circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, 1, 1, 0, 0 }); + circuit_builder.create_add_gate({ c_idx, d_idx, circuit_builder.zero_idx, 1, 1, 0, -1 }); auto composer = UltraComposer(); - // circuit_constructor.create_add_gate({ a_idx, b_idx, circuit_constructor.zero_idx, fr::one(), fr::neg_one(), - // fr::zero(), fr::zero() }); circuit_constructor.create_add_gate({ a_idx, b_idx, circuit_constructor.zero_idx, - // fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); circuit_constructor.create_add_gate({ a_idx, b_idx, - // circuit_constructor.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); - auto prover = composer.create_prover(circuit_constructor); - auto verifier = composer.create_verifier(circuit_constructor); - - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + // circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, fr::one(), fr::neg_one(), + // fr::zero(), fr::zero() }); circuit_builder.create_add_gate({ a_idx, b_idx, circuit_builder.zero_idx, + // fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); circuit_builder.create_add_gate({ a_idx, b_idx, + // circuit_builder.zero_idx, fr::one(), fr::neg_one(), fr::zero(), fr::zero() }); + // auto prover = composer.create_prover(circuit_builder); + // auto verifier = composer.create_verifier(circuit_builder); + + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, sort_widget) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); fr a = fr::one(); fr b = fr(2); fr c = fr(3); fr d = fr(4); - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(b); - auto c_idx = circuit_constructor.add_variable(c); - auto d_idx = circuit_constructor.add_variable(d); - circuit_constructor.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(c); + auto d_idx = circuit_builder.add_variable(d); + circuit_builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, sort_with_edges_gate) { + using fr = barretenberg::fr; fr a = fr::one(); fr b = fr(2); @@ -443,271 +456,273 @@ TEST_F(UltraHonkComposerTests, sort_with_edges_gate) fr h = fr(8); { - auto circuit_constructor = UltraCircuitBuilder(); - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(b); - auto c_idx = circuit_constructor.add_variable(c); - auto d_idx = circuit_constructor.add_variable(d); - auto e_idx = circuit_constructor.add_variable(e); - auto f_idx = circuit_constructor.add_variable(f); - auto g_idx = circuit_constructor.add_variable(g); - auto h_idx = circuit_constructor.add_variable(h); - circuit_constructor.create_sort_constraint_with_edges( + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(c); + auto d_idx = circuit_builder.add_variable(d); + auto e_idx = circuit_builder.add_variable(e); + auto f_idx = circuit_builder.add_variable(f); + auto g_idx = circuit_builder.add_variable(g); + auto h_idx = circuit_builder.add_variable(h); + circuit_builder.create_sort_constraint_with_edges( { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, h); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(b); - auto c_idx = circuit_constructor.add_variable(c); - auto d_idx = circuit_constructor.add_variable(d); - auto e_idx = circuit_constructor.add_variable(e); - auto f_idx = circuit_constructor.add_variable(f); - auto g_idx = circuit_constructor.add_variable(g); - auto h_idx = circuit_constructor.add_variable(h); - circuit_constructor.create_sort_constraint_with_edges( + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(c); + auto d_idx = circuit_builder.add_variable(d); + auto e_idx = circuit_builder.add_variable(e); + auto f_idx = circuit_builder.add_variable(f); + auto g_idx = circuit_builder.add_variable(g); + auto h_idx = circuit_builder.add_variable(h); + circuit_builder.create_sort_constraint_with_edges( { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, a, g); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(b); - auto c_idx = circuit_constructor.add_variable(c); - auto d_idx = circuit_constructor.add_variable(d); - auto e_idx = circuit_constructor.add_variable(e); - auto f_idx = circuit_constructor.add_variable(f); - auto g_idx = circuit_constructor.add_variable(g); - auto h_idx = circuit_constructor.add_variable(h); - circuit_constructor.create_sort_constraint_with_edges( + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(c); + auto d_idx = circuit_builder.add_variable(d); + auto e_idx = circuit_builder.add_variable(e); + auto f_idx = circuit_builder.add_variable(f); + auto g_idx = circuit_builder.add_variable(g); + auto h_idx = circuit_builder.add_variable(h); + circuit_builder.create_sort_constraint_with_edges( { a_idx, b_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, b, h); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto a_idx = circuit_constructor.add_variable(a); - auto c_idx = circuit_constructor.add_variable(c); - auto d_idx = circuit_constructor.add_variable(d); - auto e_idx = circuit_constructor.add_variable(e); - auto f_idx = circuit_constructor.add_variable(f); - auto g_idx = circuit_constructor.add_variable(g); - auto h_idx = circuit_constructor.add_variable(h); - auto b2_idx = circuit_constructor.add_variable(fr(15)); - circuit_constructor.create_sort_constraint_with_edges( + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto a_idx = circuit_builder.add_variable(a); + auto c_idx = circuit_builder.add_variable(c); + auto d_idx = circuit_builder.add_variable(d); + auto e_idx = circuit_builder.add_variable(e); + auto f_idx = circuit_builder.add_variable(f); + auto g_idx = circuit_builder.add_variable(g); + auto h_idx = circuit_builder.add_variable(h); + auto b2_idx = circuit_builder.add_variable(fr(15)); + circuit_builder.create_sort_constraint_with_edges( { a_idx, b2_idx, c_idx, d_idx, e_idx, f_idx, g_idx, h_idx }, b, h); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto idx = add_variables(circuit_constructor, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, - 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); - circuit_constructor.create_sort_constraint_with_edges(idx, 1, 45); + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto idx = add_variables(circuit_builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, + 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); + circuit_builder.create_sort_constraint_with_edges(idx, 1, 45); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto idx = add_variables(circuit_constructor, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, - 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); - circuit_constructor.create_sort_constraint_with_edges(idx, 1, 29); + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto idx = add_variables(circuit_builder, { 1, 2, 5, 6, 7, 10, 11, 13, 16, 17, 20, 22, 22, 25, + 26, 29, 29, 32, 32, 33, 35, 38, 39, 39, 42, 42, 43, 45 }); + circuit_builder.create_sort_constraint_with_edges(idx, 1, 29); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } } TEST_F(UltraHonkComposerTests, range_constraint) { { - auto circuit_constructor = UltraCircuitBuilder(); - auto indices = add_variables(circuit_constructor, { 1, 2, 3, 4, 5, 6, 7, 8 }); + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto indices = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); for (size_t i = 0; i < indices.size(); i++) { - circuit_constructor.create_new_range_constraint(indices[i], 8); + circuit_builder.create_new_range_constraint(indices[i], 8); } // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx}; - circuit_constructor.create_sort_constraint(indices); + circuit_builder.create_sort_constraint(indices); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto indices = add_variables(circuit_constructor, { 3 }); + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto indices = add_variables(circuit_builder, { 3 }); for (size_t i = 0; i < indices.size(); i++) { - circuit_constructor.create_new_range_constraint(indices[i], 3); + circuit_builder.create_new_range_constraint(indices[i], 3); } // auto ind = {a_idx,b_idx,c_idx,d_idx,e_idx,f_idx,g_idx,h_idx}; - circuit_constructor.create_dummy_constraints(indices); + circuit_builder.create_dummy_constraints(indices); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto indices = add_variables(circuit_constructor, { 1, 2, 3, 4, 5, 6, 8, 25 }); + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto indices = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 8, 25 }); for (size_t i = 0; i < indices.size(); i++) { - circuit_constructor.create_new_range_constraint(indices[i], 8); + circuit_builder.create_new_range_constraint(indices[i], 8); } - circuit_constructor.create_sort_constraint(indices); + circuit_builder.create_sort_constraint(indices); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto indices = add_variables(circuit_constructor, - { 1, 2, 3, 4, 5, 6, 10, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 19, 51 }); + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto indices = + add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 10, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 19, 51 }); for (size_t i = 0; i < indices.size(); i++) { - circuit_constructor.create_new_range_constraint(indices[i], 128); + circuit_builder.create_new_range_constraint(indices[i], 128); } - circuit_constructor.create_dummy_constraints(indices); + circuit_builder.create_dummy_constraints(indices); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto indices = add_variables(circuit_constructor, - { 1, 2, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto indices = + add_variables(circuit_builder, { 1, 2, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); for (size_t i = 0; i < indices.size(); i++) { - circuit_constructor.create_new_range_constraint(indices[i], 79); + circuit_builder.create_new_range_constraint(indices[i], 79); } - circuit_constructor.create_dummy_constraints(indices); + circuit_builder.create_dummy_constraints(indices); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } { - auto circuit_constructor = UltraCircuitBuilder(); - auto indices = add_variables(circuit_constructor, - { 1, 0, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto indices = + add_variables(circuit_builder, { 1, 0, 3, 80, 5, 6, 29, 8, 15, 11, 32, 21, 42, 79, 16, 10, 3, 26, 13, 14 }); for (size_t i = 0; i < indices.size(); i++) { - circuit_constructor.create_new_range_constraint(indices[i], 79); + circuit_builder.create_new_range_constraint(indices[i], 79); } - circuit_constructor.create_dummy_constraints(indices); + circuit_builder.create_dummy_constraints(indices); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } } TEST_F(UltraHonkComposerTests, range_with_gates) { - auto circuit_constructor = UltraCircuitBuilder(); - auto idx = add_variables(circuit_constructor, { 1, 2, 3, 4, 5, 6, 7, 8 }); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto idx = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); for (size_t i = 0; i < idx.size(); i++) { - circuit_constructor.create_new_range_constraint(idx[i], 8); + circuit_builder.create_new_range_constraint(idx[i], 8); } - circuit_constructor.create_add_gate( - { idx[0], idx[1], circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), -3 }); - circuit_constructor.create_add_gate( - { idx[2], idx[3], circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), -7 }); - circuit_constructor.create_add_gate( - { idx[4], idx[5], circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), -11 }); - circuit_constructor.create_add_gate( - { idx[6], idx[7], circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); + circuit_builder.create_add_gate({ idx[0], idx[1], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -3 }); + circuit_builder.create_add_gate({ idx[2], idx[3], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -7 }); + circuit_builder.create_add_gate( + { idx[4], idx[5], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -11 }); + circuit_builder.create_add_gate( + { idx[6], idx[7], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, range_with_gates_where_range_is_not_a_power_of_two) { - auto circuit_constructor = UltraCircuitBuilder(); - auto idx = add_variables(circuit_constructor, { 1, 2, 3, 4, 5, 6, 7, 8 }); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); + auto idx = add_variables(circuit_builder, { 1, 2, 3, 4, 5, 6, 7, 8 }); for (size_t i = 0; i < idx.size(); i++) { - circuit_constructor.create_new_range_constraint(idx[i], 12); + circuit_builder.create_new_range_constraint(idx[i], 12); } - circuit_constructor.create_add_gate( - { idx[0], idx[1], circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), -3 }); - circuit_constructor.create_add_gate( - { idx[2], idx[3], circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), -7 }); - circuit_constructor.create_add_gate( - { idx[4], idx[5], circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), -11 }); - circuit_constructor.create_add_gate( - { idx[6], idx[7], circuit_constructor.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); + circuit_builder.create_add_gate({ idx[0], idx[1], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -3 }); + circuit_builder.create_add_gate({ idx[2], idx[3], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -7 }); + circuit_builder.create_add_gate( + { idx[4], idx[5], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -11 }); + circuit_builder.create_add_gate( + { idx[6], idx[7], circuit_builder.zero_idx, fr::one(), fr::one(), fr::zero(), -15 }); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, sort_widget_complex) { + using fr = barretenberg::fr; { - auto circuit_constructor = UltraCircuitBuilder(); + auto circuit_builder = proof_system::UltraCircuitBuilder(); std::vector a = { 1, 3, 4, 7, 7, 8, 11, 14, 15, 15, 18, 19, 21, 21, 24, 25, 26, 27, 30, 32 }; std::vector ind; for (size_t i = 0; i < a.size(); i++) - ind.emplace_back(circuit_constructor.add_variable(a[i])); - circuit_constructor.create_sort_constraint(ind); + ind.emplace_back(circuit_builder.add_variable(a[i])); + circuit_builder.create_sort_constraint(ind); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } { - auto circuit_constructor = UltraCircuitBuilder(); + auto circuit_builder = proof_system::UltraCircuitBuilder(); std::vector a = { 1, 3, 4, 7, 7, 8, 16, 14, 15, 15, 18, 19, 21, 21, 24, 25, 26, 27, 30, 32 }; std::vector ind; for (size_t i = 0; i < a.size(); i++) - ind.emplace_back(circuit_constructor.add_variable(a[i])); - circuit_constructor.create_sort_constraint(ind); + ind.emplace_back(circuit_builder.add_variable(a[i])); + circuit_builder.create_sort_constraint(ind); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } } TEST_F(UltraHonkComposerTests, sort_widget_neg) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); fr a = fr::one(); fr b = fr(2); fr c = fr(3); fr d = fr(8); - auto a_idx = circuit_constructor.add_variable(a); - auto b_idx = circuit_constructor.add_variable(b); - auto c_idx = circuit_constructor.add_variable(c); - auto d_idx = circuit_constructor.add_variable(d); - circuit_constructor.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); + auto a_idx = circuit_builder.add_variable(a); + auto b_idx = circuit_builder.add_variable(b); + auto c_idx = circuit_builder.add_variable(c); + auto d_idx = circuit_builder.add_variable(d); + circuit_builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/false); + prove_and_verify(circuit_builder, composer, /*expected_result=*/false); } TEST_F(UltraHonkComposerTests, composed_range_constraint) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); auto c = fr::random_element(); auto d = uint256_t(c).slice(0, 133); auto e = fr(d); - auto a_idx = circuit_constructor.add_variable(fr(e)); - circuit_constructor.create_add_gate( - { a_idx, circuit_constructor.zero_idx, circuit_constructor.zero_idx, 1, 0, 0, -fr(e) }); - circuit_constructor.decompose_into_default_range(a_idx, 134); + auto a_idx = circuit_builder.add_variable(fr(e)); + circuit_builder.create_add_gate({ a_idx, circuit_builder.zero_idx, circuit_builder.zero_idx, 1, 0, 0, -fr(e) }); + circuit_builder.decompose_into_default_range(a_idx, 134); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, non_native_field_multiplication) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + using fq = barretenberg::fq; + auto circuit_builder = proof_system::UltraCircuitBuilder(); fq a = fq::random_element(); fq b = fq::random_element(); @@ -736,11 +751,11 @@ TEST_F(UltraHonkComposerTests, non_native_field_multiplication) const auto get_limb_witness_indices = [&](const std::array& limbs) { std::array limb_indices; - limb_indices[0] = circuit_constructor.add_variable(limbs[0]); - limb_indices[1] = circuit_constructor.add_variable(limbs[1]); - limb_indices[2] = circuit_constructor.add_variable(limbs[2]); - limb_indices[3] = circuit_constructor.add_variable(limbs[3]); - limb_indices[4] = circuit_constructor.add_variable(limbs[4]); + limb_indices[0] = circuit_builder.add_variable(limbs[0]); + limb_indices[1] = circuit_builder.add_variable(limbs[1]); + limb_indices[2] = circuit_builder.add_variable(limbs[2]); + limb_indices[3] = circuit_builder.add_variable(limbs[3]); + limb_indices[4] = circuit_builder.add_variable(limbs[4]); return limb_indices; }; const uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (68 * 4); @@ -754,40 +769,41 @@ TEST_F(UltraHonkComposerTests, non_native_field_multiplication) proof_system::UltraCircuitBuilder::non_native_field_witnesses inputs{ a_indices, b_indices, q_indices, r_indices, modulus_limbs, fr(uint256_t(modulus)), }; - const auto [lo_1_idx, hi_1_idx] = circuit_constructor.evaluate_non_native_field_multiplication(inputs); - circuit_constructor.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70); + const auto [lo_1_idx, hi_1_idx] = circuit_builder.evaluate_non_native_field_multiplication(inputs); + circuit_builder.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, rom) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); uint32_t rom_values[8]{ - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), + circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), + circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), + circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), + circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), }; - size_t rom_id = circuit_constructor.create_ROM_array(8); + size_t rom_id = circuit_builder.create_ROM_array(8); for (size_t i = 0; i < 8; ++i) { - circuit_constructor.set_ROM_element(rom_id, i, rom_values[i]); + circuit_builder.set_ROM_element(rom_id, i, rom_values[i]); } - uint32_t a_idx = circuit_constructor.read_ROM_array(rom_id, circuit_constructor.add_variable(5)); + uint32_t a_idx = circuit_builder.read_ROM_array(rom_id, circuit_builder.add_variable(5)); EXPECT_EQ(a_idx != rom_values[5], true); - uint32_t b_idx = circuit_constructor.read_ROM_array(rom_id, circuit_constructor.add_variable(4)); - uint32_t c_idx = circuit_constructor.read_ROM_array(rom_id, circuit_constructor.add_variable(1)); + uint32_t b_idx = circuit_builder.read_ROM_array(rom_id, circuit_builder.add_variable(4)); + uint32_t c_idx = circuit_builder.read_ROM_array(rom_id, circuit_builder.add_variable(1)); - const auto d_value = circuit_constructor.get_variable(a_idx) + circuit_constructor.get_variable(b_idx) + - circuit_constructor.get_variable(c_idx); - uint32_t d_idx = circuit_constructor.add_variable(d_value); + const auto d_value = + circuit_builder.get_variable(a_idx) + circuit_builder.get_variable(b_idx) + circuit_builder.get_variable(c_idx); + uint32_t d_idx = circuit_builder.add_variable(d_value); - circuit_constructor.create_big_add_gate({ + circuit_builder.create_big_add_gate({ a_idx, b_idx, c_idx, @@ -800,44 +816,44 @@ TEST_F(UltraHonkComposerTests, rom) }); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST_F(UltraHonkComposerTests, ram) { - auto circuit_constructor = UltraCircuitBuilder(); + using fr = barretenberg::fr; + auto circuit_builder = proof_system::UltraCircuitBuilder(); uint32_t ram_values[8]{ - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), + circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), + circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), + circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), + circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), }; - size_t ram_id = circuit_constructor.create_RAM_array(8); + size_t ram_id = circuit_builder.create_RAM_array(8); for (size_t i = 0; i < 8; ++i) { - circuit_constructor.init_RAM_element(ram_id, i, ram_values[i]); + circuit_builder.init_RAM_element(ram_id, i, ram_values[i]); } - uint32_t a_idx = circuit_constructor.read_RAM_array(ram_id, circuit_constructor.add_variable(5)); + uint32_t a_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(5)); EXPECT_EQ(a_idx != ram_values[5], true); - uint32_t b_idx = circuit_constructor.read_RAM_array(ram_id, circuit_constructor.add_variable(4)); - uint32_t c_idx = circuit_constructor.read_RAM_array(ram_id, circuit_constructor.add_variable(1)); + uint32_t b_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(4)); + uint32_t c_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(1)); - circuit_constructor.write_RAM_array( - ram_id, circuit_constructor.add_variable(4), circuit_constructor.add_variable(500)); - uint32_t d_idx = circuit_constructor.read_RAM_array(ram_id, circuit_constructor.add_variable(4)); + circuit_builder.write_RAM_array(ram_id, circuit_builder.add_variable(4), circuit_builder.add_variable(500)); + uint32_t d_idx = circuit_builder.read_RAM_array(ram_id, circuit_builder.add_variable(4)); - EXPECT_EQ(circuit_constructor.get_variable(d_idx), 500); + EXPECT_EQ(circuit_builder.get_variable(d_idx), 500); // ensure these vars get used in another arithmetic gate - const auto e_value = circuit_constructor.get_variable(a_idx) + circuit_constructor.get_variable(b_idx) + - circuit_constructor.get_variable(c_idx) + circuit_constructor.get_variable(d_idx); - uint32_t e_idx = circuit_constructor.add_variable(e_value); + const auto e_value = circuit_builder.get_variable(a_idx) + circuit_builder.get_variable(b_idx) + + circuit_builder.get_variable(c_idx) + circuit_builder.get_variable(d_idx); + uint32_t e_idx = circuit_builder.add_variable(e_value); - circuit_constructor.create_big_add_gate( + circuit_builder.create_big_add_gate( { a_idx, b_idx, @@ -850,11 +866,11 @@ TEST_F(UltraHonkComposerTests, ram) 0, }, true); - circuit_constructor.create_big_add_gate( + circuit_builder.create_big_add_gate( { - circuit_constructor.zero_idx, - circuit_constructor.zero_idx, - circuit_constructor.zero_idx, + circuit_builder.zero_idx, + circuit_builder.zero_idx, + circuit_builder.zero_idx, e_idx, 0, 0, @@ -865,14 +881,15 @@ TEST_F(UltraHonkComposerTests, ram) false); auto composer = UltraComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } TEST(UltraGrumpkinHonkComposer, XorConstraint) { + using fr = barretenberg::fr; // NOTE: as a WIP, this test may not actually use the Grumpkin SRS (just the IPA PCS). - auto circuit_constructor = UltraCircuitBuilder(); + auto circuit_builder = proof_system::UltraCircuitBuilder(); uint32_t left_value = engine.get_random_uint32(); uint32_t right_value = engine.get_random_uint32(); @@ -880,8 +897,8 @@ TEST(UltraGrumpkinHonkComposer, XorConstraint) fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = circuit_constructor.add_variable(left_witness_value); - uint32_t right_witness_index = circuit_constructor.add_variable(right_witness_value); + uint32_t left_witness_index = circuit_builder.add_variable(left_witness_value); + uint32_t right_witness_index = circuit_builder.add_variable(right_witness_value); uint32_t xor_result_expected = left_value ^ right_value; @@ -891,12 +908,12 @@ TEST(UltraGrumpkinHonkComposer, XorConstraint) [0]; // The zeroth index in the 3rd column is the fully accumulated xor EXPECT_EQ(xor_result, xor_result_expected); - circuit_constructor.create_gates_from_plookup_accumulators( + circuit_builder.create_gates_from_plookup_accumulators( plookup::MultiTableId::UINT32_XOR, lookup_accumulators, left_witness_index, right_witness_index); barretenberg::srs::init_crs_factory("../srs_db/ignition"); auto composer = UltraGrumpkinComposer(); - prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); + prove_and_verify(circuit_builder, composer, /*expected_result=*/true); } // TODO(#378)(luke): this is a recent update from Zac and fails; do we need a corresponding bug fix in ultra circuit @@ -904,21 +921,21 @@ TEST(UltraGrumpkinHonkComposer, XorConstraint) // { // auto composer = UltraComposer(); -// uint32_t a = circuit_constructor.add_variable(100); -// uint32_t b = circuit_constructor.add_variable(100); -// uint32_t c = circuit_constructor.add_variable(100); -// uint32_t d = circuit_constructor.add_variable(100); +// uint32_t a = circuit_builder.add_variable(100); +// uint32_t b = circuit_builder.add_variable(100); +// uint32_t c = circuit_builder.add_variable(100); +// uint32_t d = circuit_builder.add_variable(100); -// circuit_constructor.assert_equal(a, b); -// circuit_constructor.assert_equal(a, c); -// circuit_constructor.assert_equal(a, d); +// circuit_builder.assert_equal(a, b); +// circuit_builder.assert_equal(a, c); +// circuit_builder.assert_equal(a, d); -// circuit_constructor.create_new_range_constraint(a, 1000); -// circuit_constructor.create_new_range_constraint(b, 1001); -// circuit_constructor.create_new_range_constraint(c, 999); -// circuit_constructor.create_new_range_constraint(d, 1000); +// circuit_builder.create_new_range_constraint(a, 1000); +// circuit_builder.create_new_range_constraint(b, 1001); +// circuit_builder.create_new_range_constraint(c, 999); +// circuit_builder.create_new_range_constraint(d, 1000); -// circuit_constructor.create_big_add_gate( +// circuit_builder.create_big_add_gate( // { // a, // b, @@ -932,7 +949,7 @@ TEST(UltraGrumpkinHonkComposer, XorConstraint) // }, // false); -// prove_and_verify(circuit_constructor, composer, /*expected_result=*/true); +// prove_and_verify(circuit_builder, composer, /*expected_result=*/true); // } // TODO(#378)(luke): this is a new test from Zac; ultra circuit constructor does not yet have create_range_constraint @@ -946,21 +963,21 @@ TEST(UltraGrumpkinHonkComposer, XorConstraint) // auto composer = UltraComposer(); // uint16_t mask = (1 << 8) - 1; // int a = engine.get_random_uint16() & mask; -// uint32_t a_idx = circuit_constructor.add_variable(fr(a)); -// uint32_t b_idx = circuit_constructor.add_variable(fr(a)); +// uint32_t a_idx = circuit_builder.add_variable(fr(a)); +// uint32_t b_idx = circuit_builder.add_variable(fr(a)); // ASSERT_NE(a_idx, b_idx); -// uint32_t c_idx = circuit_constructor.add_variable(fr(a)); +// uint32_t c_idx = circuit_builder.add_variable(fr(a)); // ASSERT_NE(c_idx, b_idx); // composer.create_range_constraint(b_idx, 8, "bad range"); -// circuit_constructor.assert_equal(a_idx, b_idx); +// circuit_builder.assert_equal(a_idx, b_idx); // composer.create_range_constraint(c_idx, 8, "bad range"); -// circuit_constructor.assert_equal(a_idx, c_idx); +// circuit_builder.assert_equal(a_idx, c_idx); -// auto prover = composer.create_prover(circuit_constructor); +// auto prover = composer.create_prover(circuit_builder); // auto proof = prover.construct_proof(); -// auto verifier = composer.create_verifier(circuit_constructor); +// auto verifier = composer.create_verifier(circuit_builder); // bool result = verifier.verify_proof(proof); // EXPECT_EQ(result, true); // } -} // namespace test_ultra_honk_composer +} // namespace test_ultra_honk_composer \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp index 37049f21866..ae5411f7e32 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/goblin_ultra.hpp @@ -427,6 +427,12 @@ class GoblinUltra { lagrange_ecc_op = verification_key->lagrange_ecc_op; } }; + + 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.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp index 55006bdfaa9..0f503179a6a 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/standard.hpp @@ -298,6 +298,12 @@ class Standard { 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 index dbb013241b0..bee22076a59 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/standard_grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/standard_grumpkin.hpp @@ -296,5 +296,11 @@ class StandardGrumpkin { 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/flavor/ultra.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp index df21ba0ce55..2e1ca263dfe 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/ultra.hpp @@ -22,11 +22,11 @@ class Ultra { public: using CircuitBuilder = UltraCircuitBuilder; using Curve = curve::BN254; - using PCS = pcs::kzg::KZG; + using FF = Curve::ScalarField; using GroupElement = Curve::Element; using Commitment = Curve::AffineElement; using CommitmentHandle = Curve::AffineElement; - using FF = Curve::ScalarField; + using PCS = pcs::kzg::KZG; using Polynomial = barretenberg::Polynomial; using PolynomialHandle = std::span; using CommitmentKey = pcs::CommitmentKey; @@ -390,6 +390,12 @@ class Ultra { 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/ultra_grumpkin.hpp b/barretenberg/cpp/src/barretenberg/honk/flavor/ultra_grumpkin.hpp index 609421f74c6..979aaceed7b 100644 --- a/barretenberg/cpp/src/barretenberg/honk/flavor/ultra_grumpkin.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/flavor/ultra_grumpkin.hpp @@ -397,6 +397,11 @@ class UltraGrumpkin { 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/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp new file mode 100644 index 00000000000..890a006ce55 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp @@ -0,0 +1,513 @@ +#include "prover_instance.hpp" +#include "barretenberg/honk/proof_system/grand_product_library.hpp" +#include "barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp" +#include "barretenberg/proof_system/composer/permutation_lib.hpp" + +namespace proof_system::honk { +/** + * @brief Helper method to compute quantities like total number of gates and dyadic circuit size + * + * @tparam Flavor + * @param circuit + */ +template +void ProverInstance_::compute_circuit_size_parameters(Circuit& circuit) + requires IsUltraFlavor +{ + // 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) { + tables_size += table.size; + lookups_size += table.lookup_gates.size(); + } + + // Get num conventional gates, num public inputs and num Goblin style ECC op gates + const size_t num_gates = circuit.num_gates; + num_public_inputs = circuit.public_inputs.size(); + num_ecc_op_gates = circuit.num_ecc_op_gates; + + // minimum circuit size due to the length of lookups plus tables + const size_t minimum_circuit_size_due_to_lookups = tables_size + lookups_size + num_zero_rows; + + // number of populated rows in the execution trace + size_t num_rows_populated_in_execution_trace = num_zero_rows + num_ecc_op_gates + num_public_inputs + num_gates; + + // The number of gates is max(lookup gates + tables, rows already populated in trace) + 1, where the +1 is due to + // addition of a "zero row" at top of the execution trace to ensure wires and other polys are shiftable. + total_num_gates = std::max(minimum_circuit_size_due_to_lookups, num_rows_populated_in_execution_trace); + + // Next power of 2 + dyadic_circuit_size = circuit.get_circuit_subgroup_size(total_num_gates); +} + +/** + * @brief Compute witness polynomials + * + */ +template void ProverInstance_::compute_witness(Circuit& circuit) +{ + if (computed_witness) { + return; + } + + // Construct the conventional wire polynomials + auto wire_polynomials = construct_wire_polynomials_base(circuit, dyadic_circuit_size); + + proving_key->w_l = wire_polynomials[0]; + proving_key->w_r = wire_polynomials[1]; + proving_key->w_o = wire_polynomials[2]; + + 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); + } + + // 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()); +#else + 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; + } + } + + // 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; +} + +/** + * @brief Construct Goblin style ECC op wire polynomials + * @details The Ecc op wire values are assumed to have already been stored in the corresponding block of the + * conventional wire polynomials. The values for the ecc op wire polynomials are set based on those values. + * + * @tparam Flavor + * @param wire_polynomials + */ +template +void ProverInstance_::construct_ecc_op_wire_polynomials(auto& wire_polynomials) + requires IsUltraFlavor +{ + std::array op_wire_polynomials; + for (auto& poly : op_wire_polynomials) { + poly = static_cast(dyadic_circuit_size); + } + + // The ECC op wires are constructed to contain the op data on the appropriate range and to vanish everywhere else. + // The op data is assumed to have already been stored at the correct location in the convetional wires so the data + // can simply be copied over directly. + const size_t op_wire_offset = Flavor::has_zero_row ? 1 : 0; + for (size_t poly_idx = 0; poly_idx < Flavor::NUM_WIRES; ++poly_idx) { + for (size_t i = 0; i < num_ecc_op_gates; ++i) { + size_t idx = i + op_wire_offset; + op_wire_polynomials[poly_idx][idx] = wire_polynomials[poly_idx][idx]; + } + } + + proving_key->ecc_op_wire_1 = op_wire_polynomials[0]; + proving_key->ecc_op_wire_2 = op_wire_polynomials[1]; + proving_key->ecc_op_wire_3 = op_wire_polynomials[2]; + proving_key->ecc_op_wire_4 = op_wire_polynomials[3]; +} + +template +std::shared_ptr ProverInstance_::compute_proving_key(Circuit& circuit) +{ + if (proving_key) { + return proving_key; + } + + // 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()); + } + + if constexpr (IsUltraFlavor) { + + compute_honk_generalized_sigma_permutations(circuit, 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); + + 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. + + 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 < 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 + + 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->contains_recursive_proof = contains_recursive_proof; + + if constexpr (IsGoblinFlavor) { + proving_key->num_ecc_op_gates = num_ecc_op_gates; + } + } + + return proving_key; +} + +template void ProverInstance_::initialise_prover_polynomials() +{ + prover_polynomials.q_c = proving_key->q_c; + prover_polynomials.q_l = proving_key->q_l; + prover_polynomials.q_r = proving_key->q_r; + prover_polynomials.q_o = proving_key->q_o; + prover_polynomials.q_m = proving_key->q_m; + prover_polynomials.sigma_1 = proving_key->sigma_1; + prover_polynomials.sigma_2 = proving_key->sigma_2; + prover_polynomials.sigma_3 = proving_key->sigma_3; + prover_polynomials.id_1 = proving_key->id_1; + prover_polynomials.id_2 = proving_key->id_2; + prover_polynomials.id_3 = proving_key->id_3; + prover_polynomials.lagrange_first = proving_key->lagrange_first; + prover_polynomials.lagrange_last = proving_key->lagrange_last; + prover_polynomials.w_l = proving_key->w_l; + 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(); + } + + if constexpr (IsGoblinFlavor) { + prover_polynomials.ecc_op_wire_1 = proving_key->ecc_op_wire_1; + prover_polynomials.ecc_op_wire_2 = proving_key->ecc_op_wire_2; + prover_polynomials.ecc_op_wire_3 = proving_key->ecc_op_wire_3; + prover_polynomials.ecc_op_wire_4 = proving_key->ecc_op_wire_4; + prover_polynomials.lagrange_ecc_op = proving_key->lagrange_ecc_op; + } + + 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]); + } + } +} + +template +void ProverInstance_::compute_sorted_accumulator_polynomials(FF eta) + requires IsUltraFlavor +{ + relation_parameters.eta = eta; + // Compute sorted witness-table accumulator + compute_sorted_list_accumulator(eta); + prover_polynomials.sorted_accum = proving_key->sorted_accum; + prover_polynomials.sorted_accum_shift = proving_key->sorted_accum.shifted(); + + // Finalize fourth wire polynomial by adding lookup memory records + add_plookup_memory_records_to_wire_4(eta); + prover_polynomials.w_4 = proving_key->w_4; + prover_polynomials.w_4_shift = proving_key->w_4.shifted(); +} + +/** + * @brief Construct sorted list accumulator polynomial 's'. + * + * @details Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 (via Horner) where s_i are the + * sorted concatenated witness/table polynomials + * + * @param key proving key + * @param sorted_list_polynomials sorted concatenated witness/table polynomials + * @param eta random challenge + * @return Polynomial + */ +template +void ProverInstance_::compute_sorted_list_accumulator(FF eta) + requires IsUltraFlavor +{ + const size_t circuit_size = proving_key->circuit_size; + + auto sorted_list_accumulator = Polynomial{ circuit_size }; + + auto sorted_polynomials = proving_key->get_sorted_polynomials(); + + // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) + for (size_t i = 0; i < circuit_size; ++i) { + FF T0 = sorted_polynomials[3][i]; + T0 *= eta; + T0 += sorted_polynomials[2][i]; + T0 *= eta; + T0 += sorted_polynomials[1][i]; + T0 *= eta; + T0 += sorted_polynomials[0][i]; + sorted_list_accumulator[i] = T0; + } + proving_key->sorted_accum = sorted_list_accumulator; +} + +/** + * @brief Add plookup memory records to the fourth wire polynomial + * + * @details This operation must be performed after the first three wires have been committed to, hence the dependence on + * the `eta` challenge. + * + * @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 +{ + // The plookup memory record values are computed at the indicated indices as + // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; + // (See plookup_auxiliary_widget.hpp for details) + auto wires = proving_key->get_wires(); + + // Compute read record values + for (const auto& gate_idx : proving_key->memory_read_records) { + wires[3][gate_idx] += wires[2][gate_idx]; + wires[3][gate_idx] *= eta; + wires[3][gate_idx] += wires[1][gate_idx]; + wires[3][gate_idx] *= eta; + wires[3][gate_idx] += wires[0][gate_idx]; + wires[3][gate_idx] *= eta; + } + + // Compute write record values + for (const auto& gate_idx : proving_key->memory_write_records) { + wires[3][gate_idx] += wires[2][gate_idx]; + wires[3][gate_idx] *= eta; + wires[3][gate_idx] += wires[1][gate_idx]; + wires[3][gate_idx] *= eta; + wires[3][gate_idx] += wires[0][gate_idx]; + wires[3][gate_idx] *= eta; + wires[3][gate_idx] += 1; + } +} + +template void ProverInstance_::compute_grand_product_polynomials(FF beta, FF gamma) +{ + auto public_input_delta = + compute_public_input_delta(public_inputs, beta, gamma, proving_key->circuit_size, pub_inputs_offset); + + relation_parameters.beta = beta; + 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; + } + + // Compute permutation and lookup grand product polynomials + grand_product_library::compute_grand_products(proving_key, prover_polynomials, relation_parameters); +} + +/** + * Compute verification key consisting of selector precommitments. + * + * @return Pointer to the resulting verification key of the Instance. + * */ +template +std::shared_ptr ProverInstance_::compute_verification_key() +{ + if (verification_key) { + return verification_key; + } + + verification_key = + std::make_shared(proving_key->circuit_size, proving_key->num_public_inputs); + + // Compute and store commitments to all precomputed polynomials + verification_key->q_m = commitment_key->commit(proving_key->q_m); + verification_key->q_l = commitment_key->commit(proving_key->q_l); + verification_key->q_r = commitment_key->commit(proving_key->q_r); + verification_key->q_o = commitment_key->commit(proving_key->q_o); + verification_key->q_c = commitment_key->commit(proving_key->q_c); + verification_key->sigma_1 = commitment_key->commit(proving_key->sigma_1); + verification_key->sigma_2 = commitment_key->commit(proving_key->sigma_2); + verification_key->sigma_3 = commitment_key->commit(proving_key->sigma_3); + verification_key->id_1 = commitment_key->commit(proving_key->id_1); + verification_key->id_2 = commitment_key->commit(proving_key->id_2); + verification_key->id_3 = commitment_key->commit(proving_key->id_3); + 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); + } + + // // 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; + } + 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 new file mode 100644 index 00000000000..f65a06e79e9 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp @@ -0,0 +1,121 @@ +#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" +#include "barretenberg/proof_system/composer/composer_lib.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" +#include "barretenberg/proof_system/relations/relation_parameters.hpp" +#include "barretenberg/srs/factories/file_crs_factory.hpp" +namespace proof_system::honk { +/** + * @brief An Instance is normally constructed from a finalised circuit and it's role is to compute all the polynomials + * involved in creating a proof and, if requested, the verification key. + * In case of folded Instance, this will be created from the FoldingResult, the aggregated work from the folding prover + * and verifier. More specifically, a folded instance will be constructed from the complete set of folded polynomials + * and folded public inputs and its FoldingParams are expected to be non-zero + * + */ +// TODO(https://github.com/AztecProtocol/barretenberg/issues/725): create an Instances class that manages several +// Instance and passes them to ProtoGakaxy prover and verifier so that Instance objects don't need to mantain an index +template class ProverInstance_ { + using Circuit = typename Flavor::CircuitBuilder; + using ProvingKey = typename Flavor::ProvingKey; + using VerificationKey = typename Flavor::VerificationKey; + using CommitmentKey = typename Flavor::CommitmentKey; + using FF = typename Flavor::FF; + using FoldingParameters = typename Flavor::FoldingParameters; + using ProverPolynomials = typename Flavor::ProverPolynomials; + using Polynomial = typename Flavor::Polynomial; + + public: + // offset due to placing zero wires at the start of execution trace + + std::shared_ptr proving_key; + std::shared_ptr verification_key; + std::shared_ptr commitment_key; + + ProverPolynomials prover_polynomials; + + // The number of public inputs has to be the same for all instances because they are + // folded element by element. + std::vector public_inputs; + size_t pub_inputs_offset = 0; + proof_system::RelationParameters relation_parameters; + std::vector recursive_proof_public_input_indices; + FoldingParameters folding_params; + // Used by the prover for domain separation in the transcript + uint32_t index; + + 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_proving_key(circuit); + compute_witness(circuit); + } + + ProverInstance_(FoldingResult result) + : verification_key(std::move(result.verification_key)) + , prover_polynomials(result.folded_prover_polynomials) + , public_inputs(result.folded_public_inputs) + , folding_params(result.params){}; + + ~ProverInstance_() = default; + + std::shared_ptr compute_verification_key(); + + void initialise_prover_polynomials(); + + void compute_sorted_accumulator_polynomials(FF) + requires IsUltraFlavor; + + void compute_sorted_list_accumulator(FF) + requires IsUltraFlavor; + + void compute_grand_product_polynomials(FF, FF); + + private: + static constexpr size_t num_zero_rows = Flavor::has_zero_row ? 1 : 0; + static constexpr size_t NUM_WIRES = Circuit::NUM_WIRES; + bool contains_recursive_proof = false; + bool computed_witness = false; + size_t total_num_gates = 0; // num_gates + num_pub_inputs + tables + zero_row_offset (used to compute dyadic size) + size_t dyadic_circuit_size = 0; // final power-of-2 circuit size + size_t lookups_size = 0; // total number of lookup gates + size_t tables_size = 0; // total number of table entries + size_t num_public_inputs = 0; + size_t num_ecc_op_gates = 0; + + std::shared_ptr compute_proving_key(Circuit&); + + void compute_circuit_size_parameters(Circuit&) + requires IsUltraFlavor; + + void compute_witness(Circuit&); + + void construct_ecc_op_wire_polynomials(auto&) + requires IsUltraFlavor; + + 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; +}; + +extern template class ProverInstance_; +extern template class ProverInstance_; +extern template class ProverInstance_; +extern template class ProverInstance_; +extern template class ProverInstance_; + +using ProverInstance = ProverInstance_; + +} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.test.cpp b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.test.cpp new file mode 100644 index 00000000000..1cced414dd2 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.test.cpp @@ -0,0 +1,98 @@ + +#include "prover_instance.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/honk/proof_system/grand_product_library.hpp" +#include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/srs/factories/file_crs_factory.hpp" +#include + +using namespace proof_system::honk; +namespace instance_tests { + +template class InstanceTests : public testing::Test { + using FF = typename Flavor::FF; + using Polynomial = barretenberg::Polynomial; + + public: + /** + * @brief Get a random polynomial + * + * @param size + * @return Polynomial + */ + static constexpr Polynomial get_random_polynomial(size_t size) + { + Polynomial random_polynomial{ size }; + for (auto& coeff : random_polynomial) { + coeff = FF::random_element(); + } + return random_polynomial; + } + + static void populate_span(auto& polynomial_view, const auto& polynomial) + { + ASSERT(polynomial_view.size() <= polynomial.size()); + for (size_t idx = 0; idx < polynomial.size(); idx++) { + polynomial_view[idx] = polynomial[idx]; + } + }; + /** + * @brief Check consistency of the computation of the sorted list accumulator + * @details This test compares a simple, unoptimized, easily readable calculation of the sorted list accumulator + * to the optimized implementation used by the prover. It's purpose is to provide confidence that some optimization + * introduced into the calculation has not changed the result. + * @note This test does confirm the correctness of the sorted list accumulator, only that the two implementations + * yield an identical result. + */ + static void test_sorted_list_accumulator_construction() + { + // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) + auto builder = proof_system::UltraCircuitBuilder(); + + auto a = 2; + builder.add_variable(a); + + builder.add_gates_to_ensure_all_polys_are_non_zero(); + builder.finalize_circuit(); + auto instance = ProverInstance_(builder); + + // Get random challenge eta + auto eta = FF::random_element(); + + // Construct mock sorted list polynomials. + std::vector sorted_lists; + auto sorted_list_polynomials = instance.proving_key->get_sorted_polynomials(); + for (auto& sorted_list_poly : sorted_list_polynomials) { + Polynomial random_polynomial = get_random_polynomial(instance.proving_key->circuit_size); + sorted_lists.emplace_back(random_polynomial); + populate_span(sorted_list_poly, random_polynomial); + } + + // Method 1: computed sorted list accumulator polynomial using prover library method + instance.compute_sorted_list_accumulator(eta); + auto sorted_list_accumulator = instance.proving_key->sorted_accum; + + // Method 2: Compute local sorted list accumulator simply and inefficiently + const FF eta_sqr = eta.sqr(); + const FF eta_cube = eta_sqr * eta; + + // Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 + Polynomial sorted_list_accumulator_expected{ sorted_lists[0] }; + for (size_t i = 0; i < instance.proving_key->circuit_size; ++i) { + sorted_list_accumulator_expected[i] += + sorted_lists[1][i] * eta + sorted_lists[2][i] * eta_sqr + sorted_lists[3][i] * eta_cube; + } + + EXPECT_EQ(sorted_list_accumulator, sorted_list_accumulator_expected); + }; +}; + +using FlavorTypes = testing::Types; +TYPED_TEST_SUITE(InstanceTests, FlavorTypes); + +TYPED_TEST(InstanceTests, SortedListAccumulator) +{ + TestFixture::test_sorted_list_accumulator_construction(); +} + +} // namespace instance_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/instance/verifier_instance.hpp b/barretenberg/cpp/src/barretenberg/honk/instance/verifier_instance.hpp new file mode 100644 index 00000000000..7adb643d441 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/instance/verifier_instance.hpp @@ -0,0 +1,20 @@ +#pragma once +#include "barretenberg/proof_system/flavor/flavor.hpp" +#include "barretenberg/proof_system/relations/relation_parameters.hpp" +namespace proof_system::honk { +template class VerifierInstance_ { + public: + using FF = typename Flavor::FF; + using VerificationKey = typename Flavor::VerificationKey; + using FoldingParameters = typename Flavor::FoldingParameters; + + std::shared_ptr verification_key; + std::vector public_inputs; + size_t pub_inputs_offset; + size_t public_input_size; + size_t circuit_size; + RelationParameters relation_parameters; + FoldingParameters folding_params; + size_t index; +}; +} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.cpp index 2a39a4cecba..5e3c91504b2 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.cpp @@ -54,9 +54,9 @@ namespace proof_system::honk::pcs::gemini { */ template std::vector> GeminiProver_< - Curve>::compute_fold_polynomials(std::span mle_opening_point, - Polynomial&& batched_unshifted, - Polynomial&& batched_to_be_shifted) + Curve>::compute_gemini_polynomials(std::span mle_opening_point, + Polynomial&& batched_unshifted, + Polynomial&& batched_to_be_shifted) { const size_t num_variables = mle_opening_point.size(); // m @@ -69,12 +69,12 @@ std::vector> Gemi // The first two are populated here with the batched unshifted and to-be-shifted polynomial respectively. // They will eventually contain the full batched polynomial A₀ partially evaluated at the challenges r,-r. // This function populates the other m-1 polynomials with the foldings of A₀. - std::vector fold_polynomials; - fold_polynomials.reserve(num_variables + 1); + std::vector gemini_polynomials; + gemini_polynomials.reserve(num_variables + 1); // F(X) = ∑ⱼ ρʲ fⱼ(X) and G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) - Polynomial& batched_F = fold_polynomials.emplace_back(std::move(batched_unshifted)); - Polynomial& batched_G = fold_polynomials.emplace_back(std::move(batched_to_be_shifted)); + Polynomial& batched_F = gemini_polynomials.emplace_back(std::move(batched_unshifted)); + Polynomial& batched_G = gemini_polynomials.emplace_back(std::move(batched_to_be_shifted)); constexpr size_t offset_to_folded = 2; // Offset because of F an G // A₀(X) = F(X) + G↺(X) = F(X) + G(X)/X. Polynomial A_0(batched_F); @@ -86,7 +86,7 @@ std::vector> Gemi const size_t n_l = 1 << (num_variables - l - 1); // A_l_fold = Aₗ₊₁(X) = (1-uₗ)⋅even(Aₗ)(X) + uₗ⋅odd(Aₗ)(X) - fold_polynomials.emplace_back(Polynomial(n_l)); + gemini_polynomials.emplace_back(Polynomial(n_l)); } // A_l = Aₗ(X) is the polynomial being folded @@ -108,7 +108,7 @@ std::vector> Gemi const Fr u_l = mle_opening_point[l]; // A_l_fold = Aₗ₊₁(X) = (1-uₗ)⋅even(Aₗ)(X) + uₗ⋅odd(Aₗ)(X) - auto A_l_fold = fold_polynomials[l + offset_to_folded].data(); + auto A_l_fold = gemini_polynomials[l + offset_to_folded].data(); parallel_for(num_used_threads, [&](size_t i) { size_t current_chunk_size = (i == (num_used_threads - 1)) ? last_chunk_size : chunk_size; @@ -125,31 +125,31 @@ std::vector> Gemi A_l = A_l_fold; } - return fold_polynomials; + return gemini_polynomials; }; /** * @brief Computes/aggragates d+1 Fold polynomials and their opening pairs (challenge, evaluation) * - * @details This function assumes that, upon input, last d-1 entries in fold_polynomials are Fold_i. + * @details This function assumes that, upon input, last d-1 entries in gemini_polynomials are Fold_i. * The first two entries are assumed to be, respectively, the batched unshifted and batched to-be-shifted * polynomials F(X) = ∑ⱼ ρʲfⱼ(X) and G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X). This function completes the computation * of the first two Fold polynomials as F + G/r and F - G/r. It then evaluates each of the d+1 * fold polynomials at, respectively, the points r, rₗ = r^{2ˡ} for l = 0, 1, ..., d-1. * * @param mle_opening_point u = (u₀,...,uₘ₋₁) is the MLE opening point - * @param fold_polynomials vector of polynomials whose first two elements are F(X) = ∑ⱼ ρʲfⱼ(X) + * @param gemini_polynomials vector of polynomials whose first two elements are F(X) = ∑ⱼ ρʲfⱼ(X) * and G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X), and the next d-1 elements are Fold_i, i = 1, ..., d-1. * @param r_challenge univariate opening challenge */ template ProverOutput GeminiProver_::compute_fold_polynomial_evaluations( - std::span mle_opening_point, std::vector&& fold_polynomials, const Fr& r_challenge) + std::span mle_opening_point, std::vector&& gemini_polynomials, const Fr& r_challenge) { const size_t num_variables = mle_opening_point.size(); // m - Polynomial& batched_F = fold_polynomials[0]; // F(X) = ∑ⱼ ρʲ fⱼ(X) - Polynomial& batched_G = fold_polynomials[1]; // G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) + Polynomial& batched_F = gemini_polynomials[0]; // F(X) = ∑ⱼ ρʲ fⱼ(X) + Polynomial& batched_G = gemini_polynomials[1]; // G(X) = ∑ⱼ ρᵏ⁺ʲ gⱼ(X) // Compute univariate opening queries rₗ = r^{2ˡ} for l = 0, 1, ..., m-1 std::vector r_squares = squares_of_r(r_challenge, num_variables); @@ -158,16 +158,16 @@ ProverOutput GeminiProver_::compute_fold_polynomial_evaluations( Fr r_inv = r_challenge.invert(); batched_G *= r_inv; - // Construct A₀₊ = F + G/r and A₀₋ = F - G/r in place in fold_polynomials + // Construct A₀₊ = F + G/r and A₀₋ = F - G/r in place in gemini_polynomials Polynomial tmp = batched_F; - Polynomial& A_0_pos = fold_polynomials[0]; + Polynomial& A_0_pos = gemini_polynomials[0]; // A₀₊(X) = F(X) + G(X)/r, s.t. A₀₊(r) = A₀(r) A_0_pos += batched_G; // Perform a swap so that tmp = G(X)/r and A_0_neg = F(X) std::swap(tmp, batched_G); - Polynomial& A_0_neg = fold_polynomials[1]; + Polynomial& A_0_neg = gemini_polynomials[1]; // A₀₋(X) = F(X) - G(X)/r, s.t. A₀₋(-r) = A₀(-r) A_0_neg -= tmp; @@ -176,15 +176,16 @@ ProverOutput GeminiProver_::compute_fold_polynomial_evaluations( fold_poly_opening_pairs.reserve(num_variables + 1); // Compute first opening pair {r, A₀(r)} - fold_poly_opening_pairs.emplace_back(OpeningPair{ r_challenge, fold_polynomials[0].evaluate(r_challenge) }); + fold_poly_opening_pairs.emplace_back( + OpeningPair{ r_challenge, gemini_polynomials[0].evaluate(r_challenge) }); // Compute the remaining m opening pairs {−r^{2ˡ}, Aₗ(−r^{2ˡ})}, l = 0, ..., m-1. for (size_t l = 0; l < num_variables; ++l) { fold_poly_opening_pairs.emplace_back( - OpeningPair{ -r_squares[l], fold_polynomials[l + 1].evaluate(-r_squares[l]) }); + OpeningPair{ -r_squares[l], gemini_polynomials[l + 1].evaluate(-r_squares[l]) }); } - return { fold_poly_opening_pairs, std::move(fold_polynomials) }; + return { fold_poly_opening_pairs, std::move(gemini_polynomials) }; }; template class GeminiProver_; diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp b/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp index f46d55ae71f..e24f89b76da 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.hpp @@ -102,12 +102,12 @@ template class GeminiProver_ { using Polynomial = barretenberg::Polynomial; public: - static std::vector compute_fold_polynomials(std::span mle_opening_point, - Polynomial&& batched_unshifted, - Polynomial&& batched_to_be_shifted); + static std::vector compute_gemini_polynomials(std::span mle_opening_point, + Polynomial&& batched_unshifted, + Polynomial&& batched_to_be_shifted); static ProverOutput compute_fold_polynomial_evaluations(std::span mle_opening_point, - std::vector&& fold_polynomials, + std::vector&& gemini_polynomials, const Fr& r_challenge); }; // namespace proof_system::honk::pcs::gemini diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp index c9208592271..117b35d3cc4 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/gemini/gemini.test.cpp @@ -56,19 +56,19 @@ template class GeminiTest : public CommitmentTest { // Compute: // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1 - auto fold_polynomials = GeminiProver::compute_fold_polynomials( + auto gemini_polynomials = GeminiProver::compute_gemini_polynomials( multilinear_evaluation_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); for (size_t l = 0; l < log_n - 1; ++l) { std::string label = "FOLD_" + std::to_string(l + 1); - auto commitment = this->ck()->commit(fold_polynomials[l + 2]); + auto commitment = this->ck()->commit(gemini_polynomials[l + 2]); prover_transcript.send_to_verifier(label, commitment); } const Fr r_challenge = prover_transcript.get_challenge("Gemini:r"); auto prover_output = GeminiProver::compute_fold_polynomial_evaluations( - multilinear_evaluation_point, std::move(fold_polynomials), r_challenge); + multilinear_evaluation_point, std::move(gemini_polynomials), r_challenge); for (size_t l = 0; l < log_n; ++l) { std::string label = "Gemini:a_" + std::to_string(l); diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp index 78b70ecc307..d015bfa6d21 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/ipa/ipa.test.cpp @@ -131,19 +131,19 @@ TEST_F(IPATest, GeminiShplonkIPAWithShift) auto prover_transcript = ProverTranscript::init_empty(); - auto fold_polynomials = GeminiProver::compute_fold_polynomials( + auto gemini_polynomials = GeminiProver::compute_gemini_polynomials( mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); for (size_t l = 0; l < log_n - 1; ++l) { std::string label = "FOLD_" + std::to_string(l + 1); - auto commitment = this->ck()->commit(fold_polynomials[l + 2]); + auto commitment = this->ck()->commit(gemini_polynomials[l + 2]); prover_transcript.send_to_verifier(label, commitment); } const Fr r_challenge = prover_transcript.get_challenge("Gemini:r"); - const auto [gemini_opening_pairs, gemini_witnesses] = - GeminiProver::compute_fold_polynomial_evaluations(mle_opening_point, std::move(fold_polynomials), r_challenge); + const auto [gemini_opening_pairs, gemini_witnesses] = GeminiProver::compute_fold_polynomial_evaluations( + mle_opening_point, std::move(gemini_polynomials), r_challenge); for (size_t l = 0; l < log_n; ++l) { std::string label = "Gemini:a_" + std::to_string(l); diff --git a/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp index f86cd961f6e..6fe4d1b2641 100644 --- a/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/pcs/kzg/kzg.test.cpp @@ -116,19 +116,19 @@ TYPED_TEST(KZGTest, GeminiShplonkKzgWithShift) // Compute: // - (d+1) opening pairs: {r, \hat{a}_0}, {-r^{2^i}, a_i}, i = 0, ..., d-1 // - (d+1) Fold polynomials Fold_{r}^(0), Fold_{-r}^(0), and Fold^(i), i = 0, ..., d-1 - auto fold_polynomials = GeminiProver::compute_fold_polynomials( + auto gemini_polynomials = GeminiProver::compute_gemini_polynomials( mle_opening_point, std::move(batched_unshifted), std::move(batched_to_be_shifted)); for (size_t l = 0; l < log_n - 1; ++l) { std::string label = "FOLD_" + std::to_string(l + 1); - auto commitment = this->ck()->commit(fold_polynomials[l + 2]); + auto commitment = this->ck()->commit(gemini_polynomials[l + 2]); prover_transcript.send_to_verifier(label, commitment); } const Fr r_challenge = prover_transcript.get_challenge("Gemini:r"); - const auto [gemini_opening_pairs, gemini_witnesses] = - GeminiProver::compute_fold_polynomial_evaluations(mle_opening_point, std::move(fold_polynomials), r_challenge); + const auto [gemini_opening_pairs, gemini_witnesses] = GeminiProver::compute_fold_polynomial_evaluations( + mle_opening_point, std::move(gemini_polynomials), r_challenge); for (size_t l = 0; l < log_n; ++l) { std::string label = "Gemini:a_" + std::to_string(l); diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.cpp index 43d6d235c4c..b50d9823b0e 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.cpp @@ -3,7 +3,6 @@ #include "barretenberg/honk/pcs/commitment_key.hpp" #include "barretenberg/honk/proof_system/lookup_library.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" -#include "barretenberg/honk/proof_system/prover_library.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp" @@ -261,12 +260,12 @@ template void ECCVMProver_::execute_univariatizatio }; // Compute d-1 polynomials Fold^(i), i = 1, ..., d-1. - fold_polynomials = Gemini::compute_fold_polynomials( + 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(fold_polynomials[l + 2], "Gemini:FOLD_" + std::to_string(l + 1)); + queue.add_commitment(gemini_polynomials[l + 2], "Gemini:FOLD_" + std::to_string(l + 1)); } } @@ -280,7 +279,7 @@ template void ECCVMProver_::execute_pcs_evaluation_ { const FF r_challenge = transcript.get_challenge("Gemini:r"); gemini_output = Gemini::compute_fold_polynomial_evaluations( - sumcheck_output.challenge_point, std::move(fold_polynomials), r_challenge); + sumcheck_output.challenge_point, std::move(gemini_polynomials), r_challenge); for (size_t l = 0; l < key->log_circuit_size; ++l) { std::string label = "Gemini:a_" + std::to_string(l); diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.hpp index 501c2632544..0e5298b7f6a 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/eccvm_prover.hpp @@ -56,7 +56,7 @@ template class ECCVMProver_ { CommitmentLabels commitment_labels; // Container for d + 1 Fold polynomials produced by Gemini - std::vector fold_polynomials; + std::vector gemini_polynomials; Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk FF nu_challenge; // needed in both Shplonk rounds diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/folding_result.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/folding_result.hpp new file mode 100644 index 00000000000..5448f97c2b2 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/folding_result.hpp @@ -0,0 +1,38 @@ +#pragma once +#include "barretenberg/proof_system/flavor/flavor.hpp" +namespace proof_system::honk { +template struct ProverFoldingResult { + public: + using ProverPolynomials = typename Flavor::ProverPolynomials; + using FoldingParameters = typename Flavor::FoldingParameters; + ProverPolynomials folded_prover_polynomials; + // TODO(https://github.com/AztecProtocol/barretenberg/issues/656): turn folding data into a struct + std::vector folding_data; + FoldingParameters params; +}; + +template struct VerifierFoldingResult { + using FF = typename Flavor::FF; + using VerificationKey = typename Flavor::VerificationKey; + using FoldingParameters = typename Flavor::FoldingParameters; + std::vector folded_public_inputs; + VerificationKey folded_verification_key; + FoldingParameters parameters; +}; + +/** + * @brief The aggregated result from the prover and verifier after a round of folding, used to create a new Instance. + * + * @tparam Flavor + */ +template struct FoldingResult { + using FF = typename Flavor::FF; + using ProverPolynomials = typename Flavor::ProverPolynomials; + using VerificationKey = typename Flavor::VerificationKey; + using FoldingParameters = typename Flavor::FoldingParameters; + ProverPolynomials folded_prover_polynomials; + std::vector folded_public_inputs; + std::shared_ptr verification_key; + FoldingParameters params; +}; +} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/grand_product_library.test.cpp similarity index 86% rename from barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp rename to barretenberg/cpp/src/barretenberg/honk/proof_system/grand_product_library.test.cpp index af679985ff3..807c27f7d0f 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/grand_product_library.test.cpp @@ -1,23 +1,17 @@ -#include "prover_library.hpp" +#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/honk/proof_system/grand_product_library.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "prover.hpp" #include "barretenberg/srs/factories/file_crs_factory.hpp" -#include -#include #include -#include -#include using namespace proof_system::honk; -namespace prover_library_tests { +namespace grand_product_library_tests { -template class ProverLibraryTests : public testing::Test { +template class GrandProductTests : public testing::Test { using Polynomial = barretenberg::Polynomial; @@ -216,7 +210,7 @@ template class ProverLibraryTests : public testing::Test { static const size_t num_public_inputs = 0; // Instatiate a proving_key and make a pointer to it. This will be used to instantiate a Prover. - using Flavor = honk::flavor::Ultra; + using Flavor = flavor::Ultra; auto proving_key = std::make_shared(circuit_size, num_public_inputs); // Construct mock wire and permutation polynomials. @@ -375,70 +369,20 @@ template class ProverLibraryTests : public testing::Test { EXPECT_EQ(proving_key->z_lookup, z_lookup_expected); }; - - /** - * @brief Check consistency of the computation of the sorted list accumulator - * @details This test compares a simple, unoptimized, easily readable calculation of the sorted list accumulator - * to the optimized implementation used by the prover. It's purpose is to provide confidence that some optimization - * introduced into the calculation has not changed the result. - * @note This test does confirm the correctness of the sorted list accumulator, only that the two implementations - * yield an identical result. - */ - static void test_sorted_list_accumulator_construction() - { - // Construct a proving_key - static const size_t circuit_size = 8; - static const size_t num_public_inputs = 0; - using Flavor = honk::flavor::Ultra; - auto proving_key = std::make_shared(circuit_size, num_public_inputs); - - // Get random challenge eta - auto eta = FF::random_element(); - - // Construct mock sorted list polynomials. - std::vector sorted_lists; - auto sorted_list_polynomials = proving_key->get_sorted_polynomials(); - for (auto& sorted_list_poly : sorted_list_polynomials) { - Polynomial random_polynomial = get_random_polynomial(circuit_size); - sorted_lists.emplace_back(random_polynomial); - populate_span(sorted_list_poly, random_polynomial); - } - - // Method 1: computed sorted list accumulator polynomial using prover library method - Polynomial sorted_list_accumulator = prover_library::compute_sorted_list_accumulator(proving_key, eta); - - // Method 2: Compute local sorted list accumulator simply and inefficiently - const FF eta_sqr = eta.sqr(); - const FF eta_cube = eta_sqr * eta; - - // Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 - Polynomial sorted_list_accumulator_expected{ sorted_lists[0] }; - for (size_t i = 0; i < circuit_size; ++i) { - sorted_list_accumulator_expected[i] += - sorted_lists[1][i] * eta + sorted_lists[2][i] * eta_sqr + sorted_lists[3][i] * eta_cube; - } - - EXPECT_EQ(sorted_list_accumulator, sorted_list_accumulator_expected); - }; }; using FieldTypes = testing::Types; -TYPED_TEST_SUITE(ProverLibraryTests, FieldTypes); +TYPED_TEST_SUITE(GrandProductTests, FieldTypes); -TYPED_TEST(ProverLibraryTests, PermutationGrandProduct) +TYPED_TEST(GrandProductTests, GrandProductPermutation) { - TestFixture::template test_permutation_grand_product_construction(); - TestFixture::template test_permutation_grand_product_construction(); + TestFixture::template test_permutation_grand_product_construction(); + TestFixture::template test_permutation_grand_product_construction(); } -TYPED_TEST(ProverLibraryTests, LookupGrandProduct) +TYPED_TEST(GrandProductTests, GrandProductLookup) { TestFixture::test_lookup_grand_product_construction(); } -TYPED_TEST(ProverLibraryTests, SortedListAccumulator) -{ - TestFixture::test_sorted_list_accumulator_construction(); -} - -} // namespace prover_library_tests +} // namespace grand_product_library_tests \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.cpp new file mode 100644 index 00000000000..679071c8cb7 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.cpp @@ -0,0 +1,54 @@ +#include "protogalaxy_prover.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" +namespace proof_system::honk { +template +ProtoGalaxyProver_::ProtoGalaxyProver_(std::vector> insts) + : instances(insts) +{} + +/** + * @brief Prior to folding we need to add all the public inputs to the transcript, labelled by their corresponding + * instance index, compute all the instance's polynomials and record the relation parameters involved in computing these + * polynomials in the transcript. + * + */ +template void ProtoGalaxyProver_::prepare_for_folding() +{ + for (const auto& instance : instances) { + instance->initialise_prover_polynomials(); + + const auto instance_index = std::to_string(instance->index); + 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(instance_index + "_circuit_size", circuit_size); + transcript.send_to_verifier(instance_index + "_public_input_size", num_public_inputs); + transcript.send_to_verifier(instance_index + "_pub_inputs_offset", + static_cast(instance->pub_inputs_offset)); + + 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(instance_index + "_public_input_" + std::to_string(i), public_input_i); + } + + auto [eta, beta, gamma] = + transcript.get_challenges(instance_index + "_eta", instance_index + "_beta", instance_index + "_gamma"); + instance->compute_sorted_accumulator_polynomials(eta); + instance->compute_grand_product_polynomials(beta, gamma); + } +} + +// TODO(#689): implement this function +template ProverFoldingResult ProtoGalaxyProver_::fold_instances() +{ + prepare_for_folding(); + ProverFoldingResult res; + res.folding_data = transcript.proof_data; + return res; +} + +template class ProtoGalaxyProver_; +template class ProtoGalaxyProver_; +template class ProtoGalaxyProver_; + +} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.hpp new file mode 100644 index 00000000000..a2e2969c77b --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_prover.hpp @@ -0,0 +1,30 @@ +#pragma once +#include "barretenberg/honk/flavor/goblin_ultra.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" +#include "barretenberg/honk/flavor/ultra_grumpkin.hpp" +#include "barretenberg/honk/instance/prover_instance.hpp" +#include "barretenberg/honk/proof_system/folding_result.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" +namespace proof_system::honk { +template class ProtoGalaxyProver_ { + public: + using FF = typename Flavor::FF; + using Instance = ProverInstance_; + using ProverPolynomials = typename Flavor::ProverPolynomials; + + std::vector> instances; + + ProverTranscript transcript; + + explicit ProtoGalaxyProver_(std::vector>); + ~ProtoGalaxyProver_() = default; + + void prepare_for_folding(); + + ProverFoldingResult fold_instances(); +}; + +extern template class ProtoGalaxyProver_; +extern template class ProtoGalaxyProver_; +extern template class ProtoGalaxyProver_; +} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp new file mode 100644 index 00000000000..8ad3054595f --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.cpp @@ -0,0 +1,49 @@ +#include "protogalaxy_verifier.hpp" +#include "barretenberg/honk/utils/grand_product_delta.hpp" +namespace proof_system::honk { +template +ProtoGalaxyVerifier_::ProtoGalaxyVerifier_(std::vector> vks) +{ + // TODO(https://github.com/AztecProtocol/barretenberg/issues/391): simplify code with C++23 features + uint32_t idx = 0; + for (const auto& vk : vks) { + VerifierInstance inst; + inst.verification_key = std::move(vk); + inst.index = idx; + verifier_instances.emplace_back(inst); + idx++; + } +} + +template +VerifierFoldingResult ProtoGalaxyVerifier_::fold_public_parameters(std::vector fold_data) +{ + transcript = VerifierTranscript{ fold_data }; + for (auto& inst : verifier_instances) { + auto idx = std::to_string(inst.index); + inst.circuit_size = transcript.template receive_from_prover(idx + "_circuit_size"); + inst.public_input_size = transcript.template receive_from_prover(idx + "_public_input_size"); + inst.pub_inputs_offset = transcript.template receive_from_prover(idx + "_pub_inputs_offset"); + + for (size_t i = 0; i < inst.public_input_size; ++i) { + auto public_input_i = + transcript.template receive_from_prover(idx + "_public_input_" + std::to_string(i)); + inst.public_inputs.emplace_back(public_input_i); + } + auto [eta, beta, gamma] = transcript.get_challenges(idx + "_eta", idx + "_beta", idx + "_gamma"); + const FF public_input_delta = compute_public_input_delta( + inst.public_inputs, beta, gamma, inst.circuit_size, inst.pub_inputs_offset); + const FF lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, inst.circuit_size); + inst.relation_parameters = + RelationParameters{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta }; + } + + // TODO(#690): implement the Protogalaxy verifier logic + VerifierFoldingResult res; + return res; +} + +template class ProtoGalaxyVerifier_; +template class ProtoGalaxyVerifier_; +template class ProtoGalaxyVerifier_; +} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.hpp new file mode 100644 index 00000000000..e556480af1c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/protogalaxy_verifier.hpp @@ -0,0 +1,27 @@ +#pragma once +#include "barretenberg/honk/flavor/goblin_ultra.hpp" +#include "barretenberg/honk/flavor/ultra.hpp" +#include "barretenberg/honk/flavor/ultra_grumpkin.hpp" +#include "barretenberg/honk/instance/verifier_instance.hpp" +#include "barretenberg/honk/proof_system/folding_result.hpp" +#include "barretenberg/honk/transcript/transcript.hpp" +#include "barretenberg/proof_system/flavor/flavor.hpp" + +namespace proof_system::honk { +template class ProtoGalaxyVerifier_ { + public: + using FF = typename Flavor::FF; + using VerificationKey = typename Flavor::VerificationKey; + using VerifierInstance = VerifierInstance_; + std::vector verifier_instances; + VerifierTranscript transcript; + + explicit ProtoGalaxyVerifier_(std::vector> vks); + ~ProtoGalaxyVerifier_() = default; + VerifierFoldingResult fold_public_parameters(std::vector fold_data); +}; + +extern template class ProtoGalaxyVerifier_; +extern template class ProtoGalaxyVerifier_; +extern template class ProtoGalaxyVerifier_; +} // namespace proof_system::honk \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp index 1e35a281877..8df098e009f 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.cpp @@ -1,6 +1,5 @@ #include "prover.hpp" #include "barretenberg/honk/proof_system/grand_product_library.hpp" -#include "barretenberg/honk/proof_system/prover_library.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include "barretenberg/honk/transcript/transcript.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" @@ -16,50 +15,12 @@ namespace proof_system::honk { * @tparam settings Settings class. * */ template -StandardProver_::StandardProver_(const std::shared_ptr input_key, - const std::shared_ptr commitment_key) - : key(input_key) - , queue(commitment_key, transcript) - , pcs_commitment_key(commitment_key) +StandardProver_::StandardProver_(std::shared_ptr inst) + : queue(inst->commitment_key, transcript) + , instance(std::move(inst)) + , pcs_commitment_key(instance->commitment_key) { - prover_polynomials.q_c = key->q_c; - prover_polynomials.q_l = key->q_l; - prover_polynomials.q_r = key->q_r; - prover_polynomials.q_o = key->q_o; - prover_polynomials.q_m = key->q_m; - prover_polynomials.sigma_1 = key->sigma_1; - prover_polynomials.sigma_2 = key->sigma_2; - prover_polynomials.sigma_3 = key->sigma_3; - prover_polynomials.id_1 = key->id_1; - prover_polynomials.id_2 = key->id_2; - prover_polynomials.id_3 = key->id_3; - prover_polynomials.lagrange_first = key->lagrange_first; - prover_polynomials.lagrange_last = key->lagrange_last; - prover_polynomials.w_l = key->w_l; - prover_polynomials.w_r = key->w_r; - prover_polynomials.w_o = key->w_o; - - // Add public inputs to transcript from the second wire polynomial - std::span public_wires_source = prover_polynomials.w_r; - - for (size_t i = 0; i < key->num_public_inputs; ++i) { - public_inputs.emplace_back(public_wires_source[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_::compute_wire_commitments() -{ - size_t wire_idx = 0; // TODO(#391) zip - auto wire_polys = key->get_wires(); - for (auto& label : commitment_labels.get_wires()) { - queue.add_commitment(wire_polys[wire_idx], label); - ++wire_idx; - } + instance->initialise_prover_polynomials(); } /** @@ -68,24 +29,31 @@ template void StandardProver_::compute_wire_comm * */ template void StandardProver_::execute_preamble_round() { - const auto circuit_size = static_cast(key->circuit_size); - const auto num_public_inputs = static_cast(key->num_public_inputs); + 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 < key->num_public_inputs; ++i) { - auto public_input_i = public_inputs[i]; + 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); } } /** - * - compute wire commitments + * - 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() { - compute_wire_commitments(); + 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; + } } /** @@ -105,17 +73,9 @@ template void StandardProver_::execute_grand_pro // Compute and store parameters required by relations in Sumcheck auto [beta, gamma] = transcript.get_challenges("beta", "gamma"); - auto public_input_delta = compute_public_input_delta(public_inputs, beta, gamma, key->circuit_size); - - relation_parameters = proof_system::RelationParameters{ - .beta = beta, - .gamma = gamma, - .public_input_delta = public_input_delta, - }; - - grand_product_library::compute_grand_products(key, prover_polynomials, relation_parameters); + instance->compute_grand_product_polynomials(beta, gamma); - queue.add_commitment(key->z_perm, commitment_labels.z_perm); + queue.add_commitment(instance->proving_key->z_perm, commitment_labels.z_perm); } /** @@ -127,9 +87,9 @@ template void StandardProver_::execute_relation_ { using Sumcheck = sumcheck::SumcheckProver; - auto sumcheck = Sumcheck(key->circuit_size, transcript); + auto sumcheck = Sumcheck(instance->proving_key->circuit_size, transcript); - sumcheck_output = sumcheck.prove(prover_polynomials, relation_parameters); + sumcheck_output = sumcheck.prove(instance->prover_polynomials, instance->relation_parameters); } /** @@ -144,6 +104,8 @@ template void StandardProver_::execute_univariat // 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 @@ -160,12 +122,12 @@ template void StandardProver_::execute_univariat }; // Compute d-1 polynomials Fold^(i), i = 1, ..., d-1. - fold_polynomials = Gemini::compute_fold_polynomials( + 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(fold_polynomials[l + 2], "Gemini:FOLD_" + std::to_string(l + 1)); + queue.add_commitment(gemini_polynomials[l + 2], "Gemini:FOLD_" + std::to_string(l + 1)); } } @@ -179,9 +141,9 @@ template void StandardProver_::execute_pcs_evalu { const FF r_challenge = transcript.get_challenge("Gemini:r"); gemini_output = Gemini::compute_fold_polynomial_evaluations( - sumcheck_output.challenge_point, std::move(fold_polynomials), r_challenge); + sumcheck_output.challenge_point, std::move(gemini_polynomials), r_challenge); - for (size_t l = 0; l < key->log_circuit_size; ++l) { + 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); diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp index d871d5c8b6c..a88e8db8b7b 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/prover.hpp @@ -1,9 +1,9 @@ #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/prover_library.hpp" #include "barretenberg/honk/proof_system/work_queue.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include "barretenberg/honk/sumcheck/sumcheck_output.hpp" @@ -24,10 +24,10 @@ template class StandardProver_ { using CommitmentKey = typename Flavor::CommitmentKey; using PCS = typename Flavor::PCS; using Curve = typename Flavor::Curve; + using Instance = ProverInstance_; public: - explicit StandardProver_(std::shared_ptr input_key, std::shared_ptr commitment_key); - + explicit StandardProver_(std::shared_ptr); void execute_preamble_round(); void execute_wire_commitments_round(); void execute_tables_round(); @@ -51,17 +51,10 @@ template class StandardProver_ { std::vector public_inputs; - proof_system::RelationParameters relation_parameters; - - std::shared_ptr key; - - // Container for spans of all polynomials required by the prover (i.e. all multivariates evaluated by Sumcheck). - ProverPolynomials prover_polynomials; - CommitmentLabels commitment_labels; // Container for d + 1 Fold polynomials produced by Gemini - std::vector fold_polynomials; + std::vector gemini_polynomials; Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk FF nu_challenge; // needed in both Shplonk rounds @@ -70,6 +63,8 @@ template class StandardProver_ { work_queue queue; + std::shared_ptr instance; + sumcheck::SumcheckOutput sumcheck_output; pcs::gemini::ProverOutput gemini_output; pcs::shplonk::ProverOutput shplonk_output; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.cpp deleted file mode 100644 index 27da4a422ec..00000000000 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include "prover_library.hpp" -#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 -#include - -namespace proof_system::honk::prover_library { - -/** - * @brief Construct sorted list accumulator polynomial 's'. - * - * @details Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 (via Horner) where s_i are the - * sorted concatenated witness/table polynomials - * - * @param key proving key - * @param sorted_list_polynomials sorted concatenated witness/table polynomials - * @param eta random challenge - * @return Polynomial - */ -template -typename Flavor::Polynomial compute_sorted_list_accumulator(std::shared_ptr& key, - typename Flavor::FF eta) -{ - using FF = typename Flavor::FF; - using Polynomial = typename Flavor::Polynomial; - - const size_t circuit_size = key->circuit_size; - - auto sorted_list_accumulator = Polynomial{ circuit_size }; - - auto sorted_polynomials = key->get_sorted_polynomials(); - - // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) - for (size_t i = 0; i < circuit_size; ++i) { - FF T0 = sorted_polynomials[3][i]; - T0 *= eta; - T0 += sorted_polynomials[2][i]; - T0 *= eta; - T0 += sorted_polynomials[1][i]; - T0 *= eta; - T0 += sorted_polynomials[0][i]; - sorted_list_accumulator[i] = T0; - } - - return sorted_list_accumulator; -} - -/** - * @brief Add plookup memory records to the fourth wire polynomial - * - * @details This operation must be performed after the first three wires have been committed to, hence the dependence on - * the `eta` challenge. - * - * @tparam Flavor - * @param eta challenge produced after commitment to first three wire polynomials - */ -template -void add_plookup_memory_records_to_wire_4(std::shared_ptr& key, typename Flavor::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; - // (See plookup_auxiliary_widget.hpp for details) - auto wires = key->get_wires(); - - // Compute read record values - for (const auto& gate_idx : key->memory_read_records) { - wires[3][gate_idx] += wires[2][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[1][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[0][gate_idx]; - wires[3][gate_idx] *= eta; - } - - // Compute write record values - for (const auto& gate_idx : key->memory_write_records) { - wires[3][gate_idx] += wires[2][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[1][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[0][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += 1; - } -} - -// flavor::Ultra - -template typename honk::flavor::Ultra::Polynomial compute_sorted_list_accumulator( - std::shared_ptr& key, typename honk::flavor::Ultra::FF eta); - -template void add_plookup_memory_records_to_wire_4( - std::shared_ptr& key, typename honk::flavor::Ultra::FF eta); - -// flavor::UltraGrumpkin - -template typename honk::flavor::UltraGrumpkin::Polynomial compute_sorted_list_accumulator( - std::shared_ptr& key, - typename honk::flavor::UltraGrumpkin::FF eta); - -template void add_plookup_memory_records_to_wire_4( - std::shared_ptr& key, - typename honk::flavor::UltraGrumpkin::FF eta); - -// flavor::GoblinUltra - -template typename honk::flavor::GoblinUltra::Polynomial compute_sorted_list_accumulator( - std::shared_ptr& key, typename honk::flavor::GoblinUltra::FF eta); - -template void add_plookup_memory_records_to_wire_4( - std::shared_ptr& key, typename honk::flavor::GoblinUltra::FF eta); - -} // namespace proof_system::honk::prover_library \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.hpp deleted file mode 100644 index 1e01ee8aacb..00000000000 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/prover_library.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include "barretenberg/common/constexpr_utils.hpp" -#include "barretenberg/ecc/curves/bn254/fr.hpp" -#include "barretenberg/plonk/proof_system/proving_key/proving_key.hpp" -#include "barretenberg/plonk/proof_system/types/proof.hpp" -#include "barretenberg/proof_system/relations/relation_parameters.hpp" - -// TODO(@zac-williamson #2216). We used to include `program_settings.hpp` in this file. Needed to remove due to circular -// dependency. `program_settings.hpp` included header files that added "using namespace proof_system" and "using -// namespace barretenberg" declarations. This effects downstream code that relies on these using declarations. This is a -// big code smell (should really not have using declarations in header files!), however fixing it requires changes in a -// LOT of files. This would clutter the eccvm feature PR. Adding these following "using namespace" declarations is a -// temp workaround. Once this work is merged in we should fix the root problem (no using declarations in header files) -// See issue #2216 -using namespace proof_system; -using namespace barretenberg; -namespace proof_system::honk::prover_library { - -template -typename Flavor::Polynomial compute_sorted_list_accumulator(std::shared_ptr& key, - typename Flavor::FF eta); - -template -void add_plookup_memory_records_to_wire_4(std::shared_ptr& key, typename Flavor::FF eta); - -} // namespace proof_system::honk::prover_library diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp index c26dfdbfbc6..f700ea55ab6 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.cpp @@ -1,7 +1,5 @@ #include "ultra_prover.hpp" #include "barretenberg/honk/pcs/claim.hpp" -#include "barretenberg/honk/proof_system/grand_product_library.hpp" -#include "barretenberg/honk/proof_system/prover_library.hpp" #include "barretenberg/honk/sumcheck/sumcheck.hpp" #include "barretenberg/honk/utils/power_polynomial.hpp" #include "barretenberg/polynomials/polynomial.hpp" @@ -10,76 +8,19 @@ namespace proof_system::honk { /** - * Create UltraProver_ from proving key, witness and manifest. + * Create UltraProver_ from an instance. * - * @param input_key Proving key. - * @param input_manifest Input manifest + * @param instance Instance whose proof we want to generate. * - * @tparam settings Settings class. + * @tparam a type of UltraFlavor * */ template -UltraProver_::UltraProver_(std::shared_ptr input_key, - std::shared_ptr commitment_key) - : key(input_key) - , queue(commitment_key, transcript) - , pcs_commitment_key(commitment_key) +UltraProver_::UltraProver_(std::shared_ptr inst) + : queue(inst->commitment_key, transcript) + , instance(std::move(inst)) + , pcs_commitment_key(instance->commitment_key) { - prover_polynomials.q_c = key->q_c; - prover_polynomials.q_l = key->q_l; - prover_polynomials.q_r = key->q_r; - prover_polynomials.q_o = key->q_o; - prover_polynomials.q_4 = key->q_4; - prover_polynomials.q_m = key->q_m; - prover_polynomials.q_arith = key->q_arith; - prover_polynomials.q_sort = key->q_sort; - prover_polynomials.q_elliptic = key->q_elliptic; - prover_polynomials.q_aux = key->q_aux; - prover_polynomials.q_lookup = key->q_lookup; - prover_polynomials.sigma_1 = key->sigma_1; - prover_polynomials.sigma_2 = key->sigma_2; - prover_polynomials.sigma_3 = key->sigma_3; - prover_polynomials.sigma_4 = key->sigma_4; - prover_polynomials.id_1 = key->id_1; - prover_polynomials.id_2 = key->id_2; - prover_polynomials.id_3 = key->id_3; - prover_polynomials.id_4 = key->id_4; - prover_polynomials.table_1 = key->table_1; - prover_polynomials.table_2 = key->table_2; - prover_polynomials.table_3 = key->table_3; - prover_polynomials.table_4 = key->table_4; - prover_polynomials.table_1_shift = key->table_1.shifted(); - prover_polynomials.table_2_shift = key->table_2.shifted(); - prover_polynomials.table_3_shift = key->table_3.shifted(); - prover_polynomials.table_4_shift = key->table_4.shifted(); - prover_polynomials.lagrange_first = key->lagrange_first; - prover_polynomials.lagrange_last = key->lagrange_last; - prover_polynomials.w_l = key->w_l; - prover_polynomials.w_r = key->w_r; - prover_polynomials.w_o = key->w_o; - prover_polynomials.w_l_shift = key->w_l.shifted(); - prover_polynomials.w_r_shift = key->w_r.shifted(); - prover_polynomials.w_o_shift = key->w_o.shifted(); - - if constexpr (IsGoblinFlavor) { - prover_polynomials.ecc_op_wire_1 = key->ecc_op_wire_1; - prover_polynomials.ecc_op_wire_2 = key->ecc_op_wire_2; - prover_polynomials.ecc_op_wire_3 = key->ecc_op_wire_3; - prover_polynomials.ecc_op_wire_4 = key->ecc_op_wire_4; - prover_polynomials.lagrange_ecc_op = key->lagrange_ecc_op; - } - - // Add public inputs to transcript from the second wire polynomial; This requires determination of the offset at - // which the PI have been written into the wires relative to the 0th index. - std::span public_wires_source = prover_polynomials.w_r; - pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; - if constexpr (IsGoblinFlavor) { - pub_inputs_offset += key->num_ecc_op_gates; - } - - for (size_t i = 0; i < key->num_public_inputs; ++i) { - size_t idx = i + pub_inputs_offset; - public_inputs.emplace_back(public_wires_source[idx]); - } + instance->initialise_prover_polynomials(); } /** @@ -88,35 +29,36 @@ UltraProver_::UltraProver_(std::shared_ptr */ template void UltraProver_::execute_preamble_round() { - const auto circuit_size = static_cast(key->circuit_size); - const auto num_public_inputs = static_cast(key->num_public_inputs); + auto proving_key = instance->proving_key; + const auto circuit_size = static_cast(proving_key->circuit_size); + const auto num_public_inputs = static_cast(proving_key->num_public_inputs); transcript.send_to_verifier("circuit_size", circuit_size); transcript.send_to_verifier("public_input_size", num_public_inputs); - transcript.send_to_verifier("pub_inputs_offset", static_cast(pub_inputs_offset)); + transcript.send_to_verifier("pub_inputs_offset", static_cast(instance->pub_inputs_offset)); - for (size_t i = 0; i < key->num_public_inputs; ++i) { - auto public_input_i = public_inputs[i]; + for (size_t i = 0; i < 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); } } /** - * @brief Compute commitments to the first three wires + * @brief Compute commitments to the first three wire polynomials (and ECC op wires if using Goblin). * */ template void UltraProver_::execute_wire_commitments_round() { - // Commit to the first three wire polynomials; the fourth is committed to after the addition of memory records. - auto wire_polys = key->get_wires(); + // Commit to the first three wire polynomials + // We only commit to the fourth wire polynomial after adding memory records + auto wire_polys = instance->proving_key->get_wires(); auto labels = commitment_labels.get_wires(); for (size_t idx = 0; idx < 3; ++idx) { queue.add_commitment(wire_polys[idx], labels[idx]); } - // If Goblin, commit to the ECC op wire polynomials if constexpr (IsGoblinFlavor) { - auto op_wire_polys = key->get_ecc_op_wires(); + auto op_wire_polys = instance->proving_key->get_ecc_op_wires(); auto labels = commitment_labels.get_ecc_op_wires(); for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { queue.add_commitment(op_wire_polys[idx], labels[idx]); @@ -125,31 +67,23 @@ template void UltraProver_::execute_wire_commitment } /** - * @brief Compute sorted witness-table accumulator + * @brief Compute sorted witness-table accumulator and commit to the resulting polynomials. * */ template void UltraProver_::execute_sorted_list_accumulator_round() { - // Compute and add eta to relation parameters auto eta = transcript.get_challenge("eta"); - relation_parameters.eta = eta; - - // Compute sorted witness-table accumulator and its commitment - key->sorted_accum = prover_library::compute_sorted_list_accumulator(key, eta); - queue.add_commitment(key->sorted_accum, commitment_labels.sorted_accum); - // Finalize fourth wire polynomial by adding lookup memory records, then commit - prover_library::add_plookup_memory_records_to_wire_4(key, eta); - queue.add_commitment(key->w_4, commitment_labels.w_4); + instance->compute_sorted_accumulator_polynomials(eta); - prover_polynomials.sorted_accum_shift = key->sorted_accum.shifted(); - prover_polynomials.sorted_accum = key->sorted_accum; - prover_polynomials.w_4 = key->w_4; - prover_polynomials.w_4_shift = key->w_4.shifted(); + // Commit to the sorted withness-table accumulator and the finalised (i.e. with memory records) fourth wire + // polynomial + queue.add_commitment(instance->proving_key->sorted_accum, commitment_labels.sorted_accum); + queue.add_commitment(instance->proving_key->w_4, commitment_labels.w_4); } /** - * @brief Compute permutation and lookup grand product polynomials and commitments + * @brief Compute permutation and lookup grand product polynomials and their commitments * */ template void UltraProver_::execute_grand_product_computation_round() @@ -157,20 +91,10 @@ template void UltraProver_::execute_grand_product_c // Compute and store parameters required by relations in Sumcheck auto [beta, gamma] = transcript.get_challenges("beta", "gamma"); - auto public_input_delta = - compute_public_input_delta(public_inputs, beta, gamma, key->circuit_size, pub_inputs_offset); - auto lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, key->circuit_size); - - relation_parameters.beta = beta; - relation_parameters.gamma = gamma; - relation_parameters.public_input_delta = public_input_delta; - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; - - // Compute permutation + lookup grand product and their commitments - grand_product_library::compute_grand_products(key, prover_polynomials, relation_parameters); + instance->compute_grand_product_polynomials(beta, gamma); - queue.add_commitment(key->z_perm, commitment_labels.z_perm); - queue.add_commitment(key->z_lookup, commitment_labels.z_lookup); + queue.add_commitment(instance->proving_key->z_perm, commitment_labels.z_perm); + queue.add_commitment(instance->proving_key->z_lookup, commitment_labels.z_lookup); } /** @@ -181,9 +105,9 @@ template void UltraProver_::execute_relation_check_ { using Sumcheck = sumcheck::SumcheckProver; - auto sumcheck = Sumcheck(key->circuit_size, transcript); + auto sumcheck = Sumcheck(instance->proving_key->circuit_size, transcript); - sumcheck_output = sumcheck.prove(prover_polynomials, relation_parameters); + sumcheck_output = sumcheck.prove(instance->prover_polynomials, instance->relation_parameters); } /** @@ -200,26 +124,26 @@ template void UltraProver_::execute_univariatizatio std::vector rhos = pcs::gemini::powers_of_rho(rho, NUM_POLYNOMIALS); // Batch the unshifted polynomials and the to-be-shifted polynomials using ρ - Polynomial batched_poly_unshifted(key->circuit_size); // batched unshifted polynomials - size_t poly_idx = 0; // TODO(#391) zip - for (auto& unshifted_poly : prover_polynomials.get_unshifted()) { + Polynomial batched_poly_unshifted(instance->proving_key->circuit_size); // batched unshifted polynomials + size_t poly_idx = 0; // TODO(#391) zip + for (auto& unshifted_poly : instance->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()) { + Polynomial batched_poly_to_be_shifted(instance->proving_key->circuit_size); // batched to-be-shifted polynomials + for (auto& to_be_shifted_poly : instance->prover_polynomials.get_to_be_shifted()) { batched_poly_to_be_shifted.add_scaled(to_be_shifted_poly, rhos[poly_idx]); ++poly_idx; }; // Compute d-1 polynomials Fold^(i), i = 1, ..., d-1. - fold_polynomials = Gemini::compute_fold_polynomials( + 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(fold_polynomials[l + 2], "Gemini:FOLD_" + std::to_string(l + 1)); + for (size_t l = 0; l < instance->proving_key->log_circuit_size - 1; ++l) { + queue.add_commitment(gemini_polynomials[l + 2], "Gemini:FOLD_" + std::to_string(l + 1)); } } @@ -233,9 +157,9 @@ template void UltraProver_::execute_pcs_evaluation_ { const FF r_challenge = transcript.get_challenge("Gemini:r"); gemini_output = Gemini::compute_fold_polynomial_evaluations( - sumcheck_output.challenge_point, std::move(fold_polynomials), r_challenge); + sumcheck_output.challenge_point, std::move(gemini_polynomials), r_challenge); - for (size_t l = 0; l < key->log_circuit_size; ++l) { + 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); @@ -270,7 +194,7 @@ template void UltraProver_::execute_shplonk_partial } /** * - Compute final PCS opening proof: - * - For KZG, this is the quotient commitment [W]_1 + * - For KZG, this is the quotient commitmecnt [W]_1 * - For IPA, the vectors L and R * */ template void UltraProver_::execute_final_pcs_round() diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp index 9aeea1327fc..9012f2ce26a 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_prover.hpp @@ -2,6 +2,7 @@ #include "barretenberg/honk/flavor/goblin_ultra.hpp" #include "barretenberg/honk/flavor/ultra.hpp" #include "barretenberg/honk/flavor/ultra_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" @@ -12,10 +13,7 @@ namespace proof_system::honk { -// We won't compile this class with honk::flavor::Standard, but we will like want to compile it (at least for testing) -// with a flavor that uses the curve Grumpkin, or a flavor that does/does not have zk, etc. template class UltraProver_ { - using FF = typename Flavor::FF; using PCS = typename Flavor::PCS; using CommitmentKey = typename Flavor::CommitmentKey; @@ -24,10 +22,10 @@ template class UltraProver_ { using ProverPolynomials = typename Flavor::ProverPolynomials; using CommitmentLabels = typename Flavor::CommitmentLabels; using Curve = typename Flavor::Curve; + using Instance = ProverInstance_; public: - explicit UltraProver_(std::shared_ptr input_key, std::shared_ptr commitment_key); - + explicit UltraProver_(std::shared_ptr); void execute_preamble_round(); void execute_wire_commitments_round(); void execute_sorted_list_accumulator_round(); @@ -45,19 +43,12 @@ template class UltraProver_ { ProverTranscript transcript; std::vector public_inputs; - size_t pub_inputs_offset; // offset of the PI relative to 0th index in the wire polynomials - - proof_system::RelationParameters relation_parameters; - - std::shared_ptr key; - - // Container for spans of all polynomials required by the prover (i.e. all multivariates evaluated by Sumcheck). - ProverPolynomials prover_polynomials; + size_t pub_inputs_offset; CommitmentLabels commitment_labels; // Container for d + 1 Fold polynomials produced by Gemini - std::vector fold_polynomials; + std::vector gemini_polynomials; Polynomial batched_quotient_Q; // batched quotient poly computed by Shplonk FF nu_challenge; // needed in both Shplonk rounds @@ -66,6 +57,8 @@ template class UltraProver_ { work_queue queue; + std::shared_ptr instance; + sumcheck::SumcheckOutput sumcheck_output; pcs::gemini::ProverOutput gemini_output; pcs::shplonk::ProverOutput shplonk_output; 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 548c8177a81..0c8ce6d72b2 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.cpp @@ -24,12 +24,11 @@ template UltraVerifier_& UltraVerifier_::opera key = other.key; pcs_verification_key = (std::move(other.pcs_verification_key)); commitments.clear(); - pcs_fr_elements.clear(); return *this; } /** - * @brief This function verifies an Ultra Honk proof for given program settings. + * @brief This function verifies an Ultra Honk proof for a given Flavor. * */ template bool UltraVerifier_::verify_proof(const plonk::proof& proof) diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.hpp index 0f290f943ab..339630386c3 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/ultra_verifier.hpp @@ -23,7 +23,6 @@ template class UltraVerifier_ { std::shared_ptr key; std::map commitments; - std::map pcs_fr_elements; std::shared_ptr pcs_verification_key; VerifierTranscript transcript; }; diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp index 3a500f68de7..d708c17bd1e 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.cpp @@ -23,7 +23,6 @@ template StandardVerifier_& StandardVerifier_: key = other.key; pcs_verification_key = (std::move(other.pcs_verification_key)); commitments.clear(); - pcs_fr_elements.clear(); return *this; } diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp index cf6120346ec..d90cb61f863 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/verifier.hpp @@ -22,7 +22,6 @@ template class StandardVerifier_ { std::shared_ptr key; std::map commitments; - std::map pcs_fr_elements; std::shared_ptr pcs_verification_key; VerifierTranscript transcript; }; 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 b84b30c72e8..990376c5a8e 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/partial_evaluation.test.cpp @@ -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); @@ -41,7 +41,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsSpecial) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = honk::ProverTranscript; + using Transcript = proof_system::honk::ProverTranscript; // values here are chosen to check another test const size_t multivariate_d(2); @@ -79,7 +79,7 @@ TYPED_TEST(PartialEvaluationTests, TwoRoundsGeneric) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = honk::ProverTranscript; + using Transcript = proof_system::honk::ProverTranscript; const size_t multivariate_d(2); const size_t multivariate_n(1 << multivariate_d); @@ -136,7 +136,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsSpecial) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = honk::ProverTranscript; + using Transcript = proof_system::honk::ProverTranscript; const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -187,7 +187,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGeneric) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = honk::ProverTranscript; + using Transcript = proof_system::honk::ProverTranscript; const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); @@ -238,7 +238,7 @@ TYPED_TEST(PartialEvaluationTests, ThreeRoundsGenericMultiplePolys) { using Flavor = TypeParam; using FF = typename Flavor::FF; - using Transcript = honk::ProverTranscript; + using Transcript = proof_system::honk::ProverTranscript; const size_t multivariate_d(3); const size_t multivariate_n(1 << multivariate_d); 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 ea98cc35c46..73a0f5ebe61 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,6 @@ #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/proof_system/prover_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" @@ -62,13 +61,14 @@ template void check_relation(auto relation, auto circuit_size, template void create_some_add_gates(auto& circuit_builder) { - fr a = fr::random_element(); + using FF = typename Flavor::FF; + auto a = FF::random_element(); // Add some basic add gates; incorporate a public input for non-trivial PI-delta uint32_t a_idx = circuit_builder.add_public_variable(a); - fr b = fr::random_element(); - fr c = a + b; - fr d = a + c; + FF b = FF::random_element(); + FF c = a + b; + FF d = a + c; uint32_t b_idx = circuit_builder.add_variable(b); uint32_t c_idx = circuit_builder.add_variable(c); uint32_t d_idx = circuit_builder.add_variable(d); @@ -78,8 +78,8 @@ template void create_some_add_gates(auto& circuit_builder) } // If Ultra arithmetization, add a big add gate with use of next row to test q_arith = 2 - if constexpr (IsUltraFlavor) { - fr e = a + b + c + d; + if constexpr (proof_system::IsUltraFlavor) { + FF e = a + b + c + d; uint32_t e_idx = circuit_builder.add_variable(e); uint32_t zero_idx = circuit_builder.zero_idx; @@ -90,10 +90,11 @@ template void create_some_add_gates(auto& circuit_builder) template void create_some_lookup_gates(auto& circuit_builder) { + using FF = typename Flavor::FF; // Add some lookup gates (related to pedersen hashing) - barretenberg::fr pedersen_input_value = fr::random_element(); - const fr input_hi = uint256_t(pedersen_input_value).slice(126, 256); - const fr input_lo = uint256_t(pedersen_input_value).slice(0, 126); + auto pedersen_input_value = FF::random_element(); + const auto input_hi = uint256_t(pedersen_input_value).slice(126, 256); + const auto input_lo = uint256_t(pedersen_input_value).slice(0, 126); const auto input_hi_index = circuit_builder.add_variable(input_hi); const auto input_lo_index = circuit_builder.add_variable(input_lo); @@ -119,12 +120,13 @@ template void create_some_genperm_sort_gates(auto& circuit_bui template void create_some_RAM_gates(auto& circuit_builder) { + using FF = typename Flavor::FF; // Add some RAM gates uint32_t ram_values[8]{ - circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), - circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), - circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), - circuit_builder.add_variable(fr::random_element()), circuit_builder.add_variable(fr::random_element()), + circuit_builder.add_variable(FF::random_element()), circuit_builder.add_variable(FF::random_element()), + circuit_builder.add_variable(FF::random_element()), circuit_builder.add_variable(FF::random_element()), + circuit_builder.add_variable(FF::random_element()), circuit_builder.add_variable(FF::random_element()), + circuit_builder.add_variable(FF::random_element()), circuit_builder.add_variable(FF::random_element()), }; size_t ram_id = circuit_builder.create_RAM_array(8); @@ -189,11 +191,13 @@ template void create_some_elliptic_curve_addition_gates(auto& template void create_some_ecc_op_queue_gates(auto& circuit_builder) { - static_assert(IsGoblinFlavor); + using G1 = typename Flavor::Curve::Group; + using FF = typename Flavor::FF; + static_assert(proof_system::IsGoblinFlavor); const size_t num_ecc_operations = 10; // arbitrary for (size_t i = 0; i < num_ecc_operations; ++i) { - auto point = g1::affine_one * fr::random_element(); - auto scalar = fr::random_element(); + auto point = G1::affine_one * FF::random_element(); + auto scalar = FF::random_element(); circuit_builder.queue_ecc_mul_accum(point, scalar); } } @@ -215,64 +219,32 @@ class RelationCorrectnessTests : public ::testing::Test { */ TEST_F(RelationCorrectnessTests, StandardRelationCorrectness) { - using Flavor = honk::flavor::Standard; + using Flavor = flavor::Standard; using FF = typename Flavor::FF; - using ProverPolynomials = typename Flavor::ProverPolynomials; // Create a composer and a dummy circuit with a few gates - auto circuit_constructor = StandardCircuitBuilder(); + auto builder = proof_system::StandardCircuitBuilder(); - create_some_add_gates(circuit_constructor); + create_some_add_gates(builder); // Create a prover (it will compute proving key and witness) auto composer = StandardComposer(); - auto prover = composer.create_prover(circuit_constructor); - auto circuit_size = prover.key->circuit_size; + auto instance = composer.create_instance(builder); + auto proving_key = instance->proving_key; + auto circuit_size = proving_key->circuit_size; // Generate beta and gamma - fr beta = fr::random_element(); - fr gamma = fr::random_element(); - - // Compute public input delta - const auto public_inputs = circuit_constructor.get_public_inputs(); - auto public_input_delta = - honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); - - proof_system::RelationParameters params{ - .beta = beta, - .gamma = gamma, - .public_input_delta = public_input_delta, - }; + FF beta = FF::random_element(); + FF gamma = FF::random_element(); - // Create an array of spans to the underlying polynomials to more easily - // get the transposition. - // Ex: polynomial_spans[3][i] returns the i-th coefficient of the third polynomial - // in the list below - ProverPolynomials prover_polynomials; - - prover_polynomials.w_l = prover.key->w_l; - prover_polynomials.w_r = prover.key->w_r; - prover_polynomials.w_o = prover.key->w_o; - prover_polynomials.q_m = prover.key->q_m; - prover_polynomials.q_l = prover.key->q_l; - prover_polynomials.q_r = prover.key->q_r; - prover_polynomials.q_o = prover.key->q_o; - prover_polynomials.q_c = prover.key->q_c; - prover_polynomials.sigma_1 = prover.key->sigma_1; - prover_polynomials.sigma_2 = prover.key->sigma_2; - prover_polynomials.sigma_3 = prover.key->sigma_3; - prover_polynomials.id_1 = prover.key->id_1; - prover_polynomials.id_2 = prover.key->id_2; - prover_polynomials.id_3 = prover.key->id_3; - prover_polynomials.lagrange_first = prover.key->lagrange_first; - prover_polynomials.lagrange_last = prover.key->lagrange_last; - - // Compute grand product polynomial - grand_product_library::compute_grand_products(prover.key, prover_polynomials, params); + 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); @@ -291,104 +263,41 @@ TEST_F(RelationCorrectnessTests, StandardRelationCorrectness) // TODO(luke): Add a gate that sets q_arith = 3 to check secondary arithmetic relation TEST_F(RelationCorrectnessTests, UltraRelationCorrectness) { - using Flavor = honk::flavor::Ultra; + using Flavor = flavor::Ultra; using FF = typename Flavor::FF; - using ProverPolynomials = typename Flavor::ProverPolynomials; // Create a composer and then add an assortment of gates designed to ensure that the constraint(s) represented // by each relation are non-trivially exercised. - auto circuit_constructor = UltraCircuitBuilder(); + auto builder = proof_system::UltraCircuitBuilder(); // Create an assortment of representative gates - create_some_add_gates(circuit_constructor); - create_some_lookup_gates(circuit_constructor); - create_some_genperm_sort_gates(circuit_constructor); - create_some_elliptic_curve_addition_gates(circuit_constructor); - create_some_RAM_gates(circuit_constructor); + create_some_add_gates(builder); + create_some_lookup_gates(builder); + create_some_genperm_sort_gates(builder); + create_some_elliptic_curve_addition_gates(builder); + create_some_RAM_gates(builder); // Create a prover (it will compute proving key and witness) auto composer = UltraComposer(); - auto prover = composer.create_prover(circuit_constructor); - auto circuit_size = prover.key->circuit_size; + auto instance = composer.create_instance(builder); + auto proving_key = instance->proving_key; + auto circuit_size = proving_key->circuit_size; // Generate eta, beta and gamma - fr eta = fr::random_element(); - fr beta = fr::random_element(); - fr gamma = fr::random_element(); - - // Compute public input delta - const auto public_inputs = circuit_constructor.get_public_inputs(); - const size_t pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; - auto public_input_delta = honk::compute_public_input_delta( - public_inputs, beta, gamma, prover.key->circuit_size, pub_inputs_offset); - auto lookup_grand_product_delta = - honk::compute_lookup_grand_product_delta(beta, gamma, prover.key->circuit_size); - - proof_system::RelationParameters params{ - .eta = eta, - .beta = beta, - .gamma = gamma, - .public_input_delta = public_input_delta, - .lookup_grand_product_delta = lookup_grand_product_delta, - }; + FF eta = FF::random_element(); + FF beta = FF::random_element(); + FF gamma = FF::random_element(); - // Compute sorted witness-table accumulator - prover.key->sorted_accum = prover_library::compute_sorted_list_accumulator(prover.key, eta); - - // Add RAM/ROM memory records to wire four - prover_library::add_plookup_memory_records_to_wire_4(prover.key, eta); - - ProverPolynomials prover_polynomials; - - prover_polynomials.w_l = prover.key->w_l; - prover_polynomials.w_r = prover.key->w_r; - prover_polynomials.w_o = prover.key->w_o; - prover_polynomials.w_4 = prover.key->w_4; - prover_polynomials.w_l_shift = prover.key->w_l.shifted(); - prover_polynomials.w_r_shift = prover.key->w_r.shifted(); - prover_polynomials.w_o_shift = prover.key->w_o.shifted(); - prover_polynomials.w_4_shift = prover.key->w_4.shifted(); - prover_polynomials.sorted_accum = prover.key->sorted_accum; - prover_polynomials.sorted_accum_shift = prover.key->sorted_accum.shifted(); - prover_polynomials.table_1 = prover.key->table_1; - prover_polynomials.table_2 = prover.key->table_2; - prover_polynomials.table_3 = prover.key->table_3; - prover_polynomials.table_4 = prover.key->table_4; - prover_polynomials.table_1_shift = prover.key->table_1.shifted(); - prover_polynomials.table_2_shift = prover.key->table_2.shifted(); - prover_polynomials.table_3_shift = prover.key->table_3.shifted(); - prover_polynomials.table_4_shift = prover.key->table_4.shifted(); - prover_polynomials.q_m = prover.key->q_m; - prover_polynomials.q_l = prover.key->q_l; - prover_polynomials.q_r = prover.key->q_r; - prover_polynomials.q_o = prover.key->q_o; - prover_polynomials.q_c = prover.key->q_c; - prover_polynomials.q_4 = prover.key->q_4; - prover_polynomials.q_arith = prover.key->q_arith; - prover_polynomials.q_sort = prover.key->q_sort; - prover_polynomials.q_elliptic = prover.key->q_elliptic; - prover_polynomials.q_aux = prover.key->q_aux; - prover_polynomials.q_lookup = prover.key->q_lookup; - prover_polynomials.sigma_1 = prover.key->sigma_1; - prover_polynomials.sigma_2 = prover.key->sigma_2; - prover_polynomials.sigma_3 = prover.key->sigma_3; - prover_polynomials.sigma_4 = prover.key->sigma_4; - prover_polynomials.id_1 = prover.key->id_1; - prover_polynomials.id_2 = prover.key->id_2; - prover_polynomials.id_3 = prover.key->id_3; - prover_polynomials.id_4 = prover.key->id_4; - prover_polynomials.lagrange_first = prover.key->lagrange_first; - prover_polynomials.lagrange_last = prover.key->lagrange_last; - - // Compute grand product polynomials for permutation + lookup - grand_product_library::compute_grand_products(prover.key, prover_polynomials, params); + instance->initialise_prover_polynomials(); + instance->compute_sorted_accumulator_polynomials(eta); + instance->compute_grand_product_polynomials(beta, gamma); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution - ensure_non_zero(prover.key->q_arith); - ensure_non_zero(prover.key->q_sort); - ensure_non_zero(prover.key->q_lookup); - ensure_non_zero(prover.key->q_elliptic); - ensure_non_zero(prover.key->q_aux); + ensure_non_zero(proving_key->q_arith); + ensure_non_zero(proving_key->q_sort); + ensure_non_zero(proving_key->q_lookup); + ensure_non_zero(proving_key->q_elliptic); + ensure_non_zero(proving_key->q_aux); // Construct the round for applying sumcheck relations and results for storing computed results auto relations = std::tuple(proof_system::UltraArithmeticRelation(), @@ -398,6 +307,8 @@ TEST_F(RelationCorrectnessTests, UltraRelationCorrectness) proof_system::EllipticRelation(), proof_system::AuxiliaryRelation()); + 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); @@ -409,13 +320,12 @@ TEST_F(RelationCorrectnessTests, UltraRelationCorrectness) TEST_F(RelationCorrectnessTests, GoblinUltraRelationCorrectness) { - using Flavor = honk::flavor::GoblinUltra; + using Flavor = flavor::GoblinUltra; using FF = typename Flavor::FF; - using ProverPolynomials = typename Flavor::ProverPolynomials; // Create a composer and then add an assortment of gates designed to ensure that the constraint(s) represented // by each relation are non-trivially exercised. - auto builder = UltraCircuitBuilder(); + auto builder = proof_system::UltraCircuitBuilder(); // Create an assortment of representative gates create_some_add_gates(builder); @@ -427,98 +337,25 @@ TEST_F(RelationCorrectnessTests, GoblinUltraRelationCorrectness) // Create a prover (it will compute proving key and witness) auto composer = GoblinUltraComposer(); - auto prover = composer.create_prover(builder); - auto circuit_size = prover.key->circuit_size; + auto instance = composer.create_instance(builder); + auto proving_key = instance->proving_key; + auto circuit_size = proving_key->circuit_size; // Generate eta, beta and gamma - fr eta = fr::random_element(); - fr beta = fr::random_element(); - fr gamma = fr::random_element(); - - // Compute public input delta - const auto public_inputs = builder.get_public_inputs(); + FF eta = FF::random_element(); + FF beta = FF::random_element(); + FF gamma = FF::random_element(); - // If Goblin, must account for the fact that PI are offset in the wire polynomials by the number of ecc op gates - size_t pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; - if constexpr (IsGoblinFlavor) { - pub_inputs_offset += builder.num_ecc_op_gates; - } - auto public_input_delta = honk::compute_public_input_delta( - public_inputs, beta, gamma, prover.key->circuit_size, pub_inputs_offset); - auto lookup_grand_product_delta = - honk::compute_lookup_grand_product_delta(beta, gamma, prover.key->circuit_size); - - proof_system::RelationParameters params{ - .eta = eta, - .beta = beta, - .gamma = gamma, - .public_input_delta = public_input_delta, - .lookup_grand_product_delta = lookup_grand_product_delta, - }; - - // Compute sorted witness-table accumulator - prover.key->sorted_accum = prover_library::compute_sorted_list_accumulator(prover.key, eta); - - // Add RAM/ROM memory records to wire four - prover_library::add_plookup_memory_records_to_wire_4(prover.key, eta); - - ProverPolynomials prover_polynomials; - - prover_polynomials.lagrange_ecc_op = prover.key->lagrange_ecc_op; - prover_polynomials.ecc_op_wire_1 = prover.key->ecc_op_wire_1; - prover_polynomials.ecc_op_wire_2 = prover.key->ecc_op_wire_2; - prover_polynomials.ecc_op_wire_3 = prover.key->ecc_op_wire_3; - prover_polynomials.ecc_op_wire_4 = prover.key->ecc_op_wire_4; - - prover_polynomials.w_l = prover.key->w_l; - prover_polynomials.w_r = prover.key->w_r; - prover_polynomials.w_o = prover.key->w_o; - prover_polynomials.w_4 = prover.key->w_4; - prover_polynomials.w_l_shift = prover.key->w_l.shifted(); - prover_polynomials.w_r_shift = prover.key->w_r.shifted(); - prover_polynomials.w_o_shift = prover.key->w_o.shifted(); - prover_polynomials.w_4_shift = prover.key->w_4.shifted(); - prover_polynomials.sorted_accum = prover.key->sorted_accum; - prover_polynomials.sorted_accum_shift = prover.key->sorted_accum.shifted(); - prover_polynomials.table_1 = prover.key->table_1; - prover_polynomials.table_2 = prover.key->table_2; - prover_polynomials.table_3 = prover.key->table_3; - prover_polynomials.table_4 = prover.key->table_4; - prover_polynomials.table_1_shift = prover.key->table_1.shifted(); - prover_polynomials.table_2_shift = prover.key->table_2.shifted(); - prover_polynomials.table_3_shift = prover.key->table_3.shifted(); - prover_polynomials.table_4_shift = prover.key->table_4.shifted(); - prover_polynomials.q_m = prover.key->q_m; - prover_polynomials.q_l = prover.key->q_l; - prover_polynomials.q_r = prover.key->q_r; - prover_polynomials.q_o = prover.key->q_o; - prover_polynomials.q_c = prover.key->q_c; - prover_polynomials.q_4 = prover.key->q_4; - prover_polynomials.q_arith = prover.key->q_arith; - prover_polynomials.q_sort = prover.key->q_sort; - prover_polynomials.q_elliptic = prover.key->q_elliptic; - prover_polynomials.q_aux = prover.key->q_aux; - prover_polynomials.q_lookup = prover.key->q_lookup; - prover_polynomials.sigma_1 = prover.key->sigma_1; - prover_polynomials.sigma_2 = prover.key->sigma_2; - prover_polynomials.sigma_3 = prover.key->sigma_3; - prover_polynomials.sigma_4 = prover.key->sigma_4; - prover_polynomials.id_1 = prover.key->id_1; - prover_polynomials.id_2 = prover.key->id_2; - prover_polynomials.id_3 = prover.key->id_3; - prover_polynomials.id_4 = prover.key->id_4; - prover_polynomials.lagrange_first = prover.key->lagrange_first; - prover_polynomials.lagrange_last = prover.key->lagrange_last; - - // Compute grand product polynomials for permutation + lookup - grand_product_library::compute_grand_products(prover.key, prover_polynomials, params); + instance->initialise_prover_polynomials(); + instance->compute_sorted_accumulator_polynomials(eta); + instance->compute_grand_product_polynomials(beta, gamma); // Check that selectors are nonzero to ensure corresponding relation has nontrivial contribution - ensure_non_zero(prover.key->q_arith); - ensure_non_zero(prover.key->q_sort); - ensure_non_zero(prover.key->q_lookup); - ensure_non_zero(prover.key->q_elliptic); - ensure_non_zero(prover.key->q_aux); + ensure_non_zero(proving_key->q_arith); + ensure_non_zero(proving_key->q_sort); + ensure_non_zero(proving_key->q_lookup); + ensure_non_zero(proving_key->q_elliptic); + ensure_non_zero(proving_key->q_aux); // Construct the round for applying sumcheck relations and results for storing computed results auto relations = std::tuple(proof_system::UltraArithmeticRelation(), @@ -529,6 +366,9 @@ TEST_F(RelationCorrectnessTests, GoblinUltraRelationCorrectness) proof_system::AuxiliaryRelation(), proof_system::EccOpQueueRelation()); + 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); diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp index fba343da147..37dfbf90771 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/sumcheck.test.cpp @@ -15,7 +15,7 @@ using namespace proof_system::honk; using namespace proof_system::honk::sumcheck; -using Flavor = honk::flavor::Standard; // TODO(Cody): Generalize this test. +using Flavor = proof_system::honk::flavor::Standard; // TODO(Cody): Generalize this test. using FF = typename Flavor::FF; using ProverPolynomials = typename Flavor::ProverPolynomials; const size_t NUM_POLYNOMIALS = Flavor::NUM_ALL_ENTITIES; @@ -406,78 +406,44 @@ TEST_F(SumcheckTests, ProverAndVerifierLonger) */ TEST_F(SumcheckTests, RealCircuitStandard) { - using Flavor = honk::flavor::Standard; - using FF = typename Flavor::FF; - using ProverPolynomials = typename Flavor::ProverPolynomials; - // Create a composer and a dummy circuit with a few gates - auto circuit_constructor = StandardCircuitBuilder(); - fr a = fr::one(); + 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 = circuit_constructor.add_public_variable(a); - fr b = fr::one(); - fr c = a + b; - fr d = a + c; - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); + 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++) { - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, fr::one(), fr::one(), fr::neg_one(), fr::zero() }); - circuit_constructor.create_add_gate( - { d_idx, c_idx, a_idx, fr::one(), fr::neg_one(), fr::neg_one(), fr::zero() }); + 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 prover = composer.create_prover(circuit_constructor); + auto instance = composer.create_instance(builder); // Generate beta and gamma - fr beta = fr::random_element(); - fr gamma = fr::random_element(); - - // Compute public input delta - const auto public_inputs = circuit_constructor.get_public_inputs(); - auto public_input_delta = - honk::compute_public_input_delta(public_inputs, beta, gamma, prover.key->circuit_size); - - proof_system::RelationParameters relation_parameters{ - .beta = beta, - .gamma = gamma, - .public_input_delta = public_input_delta, - }; + FF beta = FF::random_element(); + FF gamma = FF::random_element(); - ProverPolynomials prover_polynomials; - - prover_polynomials.w_l = prover.key->w_l; - prover_polynomials.w_r = prover.key->w_r; - prover_polynomials.w_o = prover.key->w_o; - prover_polynomials.q_m = prover.key->q_m; - prover_polynomials.q_l = prover.key->q_l; - prover_polynomials.q_r = prover.key->q_r; - prover_polynomials.q_o = prover.key->q_o; - prover_polynomials.q_c = prover.key->q_c; - prover_polynomials.sigma_1 = prover.key->sigma_1; - prover_polynomials.sigma_2 = prover.key->sigma_2; - prover_polynomials.sigma_3 = prover.key->sigma_3; - prover_polynomials.id_1 = prover.key->id_1; - prover_polynomials.id_2 = prover.key->id_2; - prover_polynomials.id_3 = prover.key->id_3; - prover_polynomials.lagrange_first = prover.key->lagrange_first; - prover_polynomials.lagrange_last = prover.key->lagrange_last; - - // Compute grand product polynomial - grand_product_library::compute_grand_products(prover.key, prover_polynomials, relation_parameters); + 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(prover.key->circuit_size, prover_transcript); + auto sumcheck_prover = SumcheckProver(circuit_size, prover_transcript); - auto prover_output = sumcheck_prover.prove(prover_polynomials, relation_parameters); + auto prover_output = sumcheck_prover.prove(instance->prover_polynomials, instance->relation_parameters); auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); - auto sumcheck_verifier = SumcheckVerifier(prover.key->circuit_size); + auto sumcheck_verifier = SumcheckVerifier(circuit_size); - std::optional verifier_output = sumcheck_verifier.verify(relation_parameters, verifier_transcript); + std::optional verifier_output = sumcheck_verifier.verify(instance->relation_parameters, verifier_transcript); ASSERT_TRUE(verifier_output.has_value()); } @@ -488,56 +454,55 @@ TEST_F(SumcheckTests, RealCircuitStandard) */ TEST_F(SumcheckTests, RealCircuitUltra) { - using Flavor = honk::flavor::Ultra; + using Flavor = flavor::Ultra; using FF = typename Flavor::FF; - using ProverPolynomials = typename Flavor::ProverPolynomials; // Create a composer and a dummy circuit with a few gates - auto circuit_constructor = UltraCircuitBuilder(); - fr a = fr::one(); + auto builder = proof_system::UltraCircuitBuilder(); + FF a = FF::one(); // Add some basic add gates, with a public input for good measure - uint32_t a_idx = circuit_constructor.add_public_variable(a); - fr b = fr::one(); - fr c = a + b; - fr d = a + c; - uint32_t b_idx = circuit_constructor.add_variable(b); - uint32_t c_idx = circuit_constructor.add_variable(c); - uint32_t d_idx = circuit_constructor.add_variable(d); + 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++) { - circuit_constructor.create_add_gate({ a_idx, b_idx, c_idx, 1, 1, -1, 0 }); - circuit_constructor.create_add_gate({ d_idx, c_idx, a_idx, 1, -1, -1, 0 }); + builder.create_add_gate({ a_idx, b_idx, c_idx, 1, 1, -1, 0 }); + builder.create_add_gate({ d_idx, c_idx, a_idx, 1, -1, -1, 0 }); } // Add a big add gate with use of next row to test q_arith = 2 - fr e = a + b + c + d; - uint32_t e_idx = circuit_constructor.add_variable(e); + FF e = a + b + c + d; + uint32_t e_idx = builder.add_variable(e); - uint32_t zero_idx = circuit_constructor.zero_idx; - circuit_constructor.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); // use next row - circuit_constructor.create_big_add_gate({ zero_idx, zero_idx, zero_idx, e_idx, 0, 0, 0, 0, 0 }, false); + uint32_t zero_idx = builder.zero_idx; + builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); // use next row + builder.create_big_add_gate({ zero_idx, zero_idx, zero_idx, e_idx, 0, 0, 0, 0, 0 }, false); // Add some lookup gates (related to pedersen hashing) - barretenberg::fr pedersen_input_value = fr::random_element(); - const fr input_hi = uint256_t(pedersen_input_value).slice(126, 256); - const fr input_lo = uint256_t(pedersen_input_value).slice(0, 126); - const auto input_hi_index = circuit_constructor.add_variable(input_hi); - const auto input_lo_index = circuit_constructor.add_variable(input_lo); + auto pedersen_input_value = FF::random_element(); + const FF input_hi = uint256_t(pedersen_input_value).slice(126, 256); + const FF input_lo = uint256_t(pedersen_input_value).slice(0, 126); + const auto input_hi_index = builder.add_variable(input_hi); + const auto input_lo_index = builder.add_variable(input_lo); const auto sequence_data_hi = plookup::get_lookup_accumulators(plookup::MultiTableId::PEDERSEN_LEFT_HI, input_hi); const auto sequence_data_lo = plookup::get_lookup_accumulators(plookup::MultiTableId::PEDERSEN_LEFT_LO, input_lo); - circuit_constructor.create_gates_from_plookup_accumulators( + builder.create_gates_from_plookup_accumulators( plookup::MultiTableId::PEDERSEN_LEFT_HI, sequence_data_hi, input_hi_index); - circuit_constructor.create_gates_from_plookup_accumulators( + builder.create_gates_from_plookup_accumulators( plookup::MultiTableId::PEDERSEN_LEFT_LO, sequence_data_lo, input_lo_index); // Add a sort gate (simply checks that consecutive inputs have a difference of < 4) - a_idx = circuit_constructor.add_variable(FF(0)); - b_idx = circuit_constructor.add_variable(FF(1)); - c_idx = circuit_constructor.add_variable(FF(2)); - d_idx = circuit_constructor.add_variable(FF(3)); - circuit_constructor.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); + a_idx = builder.add_variable(FF(0)); + b_idx = builder.add_variable(FF(1)); + c_idx = builder.add_variable(FF(2)); + d_idx = builder.add_variable(FF(3)); + builder.create_sort_constraint({ a_idx, b_idx, c_idx, d_idx }); // Add an elliptic curve addition gate grumpkin::g1::affine_element p1 = crypto::generators::get_generator_data({ 0, 0 }).generator; @@ -549,52 +514,51 @@ TEST_F(SumcheckTests, RealCircuitUltra) grumpkin::g1::affine_element p3(grumpkin::g1::element(p1) - grumpkin::g1::element(p2_endo)); - uint32_t x1 = circuit_constructor.add_variable(p1.x); - uint32_t y1 = circuit_constructor.add_variable(p1.y); - uint32_t x2 = circuit_constructor.add_variable(p2.x); - uint32_t y2 = circuit_constructor.add_variable(p2.y); - uint32_t x3 = circuit_constructor.add_variable(p3.x); - uint32_t y3 = circuit_constructor.add_variable(p3.y); + uint32_t x1 = builder.add_variable(p1.x); + uint32_t y1 = builder.add_variable(p1.y); + uint32_t x2 = builder.add_variable(p2.x); + uint32_t y2 = builder.add_variable(p2.y); + uint32_t x3 = builder.add_variable(p3.x); + uint32_t y3 = builder.add_variable(p3.y); - circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, beta_scalar, -1 }); + builder.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, beta_scalar, -1 }); // Add some RAM gates uint32_t ram_values[8]{ - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), - circuit_constructor.add_variable(fr::random_element()), circuit_constructor.add_variable(fr::random_element()), + builder.add_variable(FF::random_element()), builder.add_variable(FF::random_element()), + builder.add_variable(FF::random_element()), builder.add_variable(FF::random_element()), + builder.add_variable(FF::random_element()), builder.add_variable(FF::random_element()), + builder.add_variable(FF::random_element()), builder.add_variable(FF::random_element()), }; - size_t ram_id = circuit_constructor.create_RAM_array(8); + size_t ram_id = builder.create_RAM_array(8); for (size_t i = 0; i < 8; ++i) { - circuit_constructor.init_RAM_element(ram_id, i, ram_values[i]); + builder.init_RAM_element(ram_id, i, ram_values[i]); } - a_idx = circuit_constructor.read_RAM_array(ram_id, circuit_constructor.add_variable(5)); + a_idx = builder.read_RAM_array(ram_id, builder.add_variable(5)); EXPECT_EQ(a_idx != ram_values[5], true); - b_idx = circuit_constructor.read_RAM_array(ram_id, circuit_constructor.add_variable(4)); - c_idx = circuit_constructor.read_RAM_array(ram_id, circuit_constructor.add_variable(1)); + b_idx = builder.read_RAM_array(ram_id, builder.add_variable(4)); + c_idx = builder.read_RAM_array(ram_id, builder.add_variable(1)); - circuit_constructor.write_RAM_array( - ram_id, circuit_constructor.add_variable(4), circuit_constructor.add_variable(500)); - d_idx = circuit_constructor.read_RAM_array(ram_id, circuit_constructor.add_variable(4)); + builder.write_RAM_array(ram_id, builder.add_variable(4), builder.add_variable(500)); + d_idx = builder.read_RAM_array(ram_id, builder.add_variable(4)); - EXPECT_EQ(circuit_constructor.get_variable(d_idx), 500); + EXPECT_EQ(builder.get_variable(d_idx), 500); // ensure these vars get used in another arithmetic gate - const auto e_value = circuit_constructor.get_variable(a_idx) + circuit_constructor.get_variable(b_idx) + - circuit_constructor.get_variable(c_idx) + circuit_constructor.get_variable(d_idx); - e_idx = circuit_constructor.add_variable(e_value); + const auto e_value = builder.get_variable(a_idx) + builder.get_variable(b_idx) + builder.get_variable(c_idx) + + builder.get_variable(d_idx); + e_idx = builder.add_variable(e_value); - circuit_constructor.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); - circuit_constructor.create_big_add_gate( + builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); + builder.create_big_add_gate( { - circuit_constructor.zero_idx, - circuit_constructor.zero_idx, - circuit_constructor.zero_idx, + builder.zero_idx, + builder.zero_idx, + builder.zero_idx, e_idx, 0, 0, @@ -606,92 +570,29 @@ TEST_F(SumcheckTests, RealCircuitUltra) // Create a prover (it will compute proving key and witness) auto composer = UltraComposer(); - auto prover = composer.create_prover(circuit_constructor); + auto instance = composer.create_instance(builder); // Generate eta, beta and gamma - fr eta = fr::random_element(); - fr beta = fr::random_element(); - fr gamma = fr::random_element(); - - // Compute public input delta - const auto public_inputs = circuit_constructor.get_public_inputs(); - size_t pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; - auto public_input_delta = honk::compute_public_input_delta( - public_inputs, beta, gamma, prover.key->circuit_size, pub_inputs_offset); - auto lookup_grand_product_delta = - honk::compute_lookup_grand_product_delta(beta, gamma, prover.key->circuit_size); + FF eta = FF::random_element(); + FF beta = FF::random_element(); + FF gamma = FF::random_element(); - proof_system::RelationParameters relation_parameters{ - .eta = eta, - .beta = beta, - .gamma = gamma, - .public_input_delta = public_input_delta, - .lookup_grand_product_delta = lookup_grand_product_delta, - }; - - // Compute sorted witness-table accumulator - prover.key->sorted_accum = prover_library::compute_sorted_list_accumulator(prover.key, eta); - - // Add RAM/ROM memory records to wire four - prover_library::add_plookup_memory_records_to_wire_4(prover.key, eta); - - ProverPolynomials prover_polynomials; - - prover_polynomials.w_l = prover.key->w_l; - prover_polynomials.w_r = prover.key->w_r; - prover_polynomials.w_o = prover.key->w_o; - prover_polynomials.w_4 = prover.key->w_4; - prover_polynomials.w_l_shift = prover.key->w_l.shifted(); - prover_polynomials.w_r_shift = prover.key->w_r.shifted(); - prover_polynomials.w_o_shift = prover.key->w_o.shifted(); - prover_polynomials.w_4_shift = prover.key->w_4.shifted(); - prover_polynomials.sorted_accum = prover.key->sorted_accum; - prover_polynomials.sorted_accum_shift = prover.key->sorted_accum.shifted(); - prover_polynomials.table_1 = prover.key->table_1; - prover_polynomials.table_2 = prover.key->table_2; - prover_polynomials.table_3 = prover.key->table_3; - prover_polynomials.table_4 = prover.key->table_4; - prover_polynomials.table_1_shift = prover.key->table_1.shifted(); - prover_polynomials.table_2_shift = prover.key->table_2.shifted(); - prover_polynomials.table_3_shift = prover.key->table_3.shifted(); - prover_polynomials.table_4_shift = prover.key->table_4.shifted(); - prover_polynomials.z_lookup = prover.key->z_lookup; - prover_polynomials.z_lookup_shift = prover.key->z_lookup.shifted(); - prover_polynomials.q_m = prover.key->q_m; - prover_polynomials.q_l = prover.key->q_l; - prover_polynomials.q_r = prover.key->q_r; - prover_polynomials.q_o = prover.key->q_o; - prover_polynomials.q_c = prover.key->q_c; - prover_polynomials.q_4 = prover.key->q_4; - prover_polynomials.q_arith = prover.key->q_arith; - prover_polynomials.q_sort = prover.key->q_sort; - prover_polynomials.q_elliptic = prover.key->q_elliptic; - prover_polynomials.q_aux = prover.key->q_aux; - prover_polynomials.q_lookup = prover.key->q_lookup; - prover_polynomials.sigma_1 = prover.key->sigma_1; - prover_polynomials.sigma_2 = prover.key->sigma_2; - prover_polynomials.sigma_3 = prover.key->sigma_3; - prover_polynomials.sigma_4 = prover.key->sigma_4; - prover_polynomials.id_1 = prover.key->id_1; - prover_polynomials.id_2 = prover.key->id_2; - prover_polynomials.id_3 = prover.key->id_3; - prover_polynomials.id_4 = prover.key->id_4; - prover_polynomials.lagrange_first = prover.key->lagrange_first; - prover_polynomials.lagrange_last = prover.key->lagrange_last; - - grand_product_library::compute_grand_products(prover.key, prover_polynomials, relation_parameters); + instance->initialise_prover_polynomials(); + instance->compute_sorted_accumulator_polynomials(eta); + 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(prover.key->circuit_size, prover_transcript); + auto sumcheck_prover = SumcheckProver(circuit_size, prover_transcript); - auto prover_output = sumcheck_prover.prove(prover_polynomials, relation_parameters); + auto prover_output = sumcheck_prover.prove(instance->prover_polynomials, instance->relation_parameters); auto verifier_transcript = VerifierTranscript::init_empty(prover_transcript); - auto sumcheck_verifier = SumcheckVerifier(prover.key->circuit_size); + auto sumcheck_verifier = SumcheckVerifier(circuit_size); - std::optional verifier_output = sumcheck_verifier.verify(relation_parameters, verifier_transcript); + std::optional verifier_output = sumcheck_verifier.verify(instance->relation_parameters, verifier_transcript); ASSERT_TRUE(verifier_output.has_value()); } diff --git a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp b/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp index ca36c393bde..4b99ce00b56 100644 --- a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.hpp @@ -130,8 +130,9 @@ template class BaseTranscript { public: /** - * @brief After all the prover messages have been sent, finalize the round by hashing all the data, create the field - * elements and reset the state in preparation for the next round. + * @brief After all the prover messages have been sent, finalize the round by hashing all the data and then create + * the number of requested challenges which will be increasing powers of the first challenge. Finally, reset the + * state in preparation for the next round. * * @param labels human-readable names for the challenges for the manifest * @return std::array challenges for this round. @@ -139,10 +140,6 @@ template class BaseTranscript { template std::array get_challenges(const Strings&... labels) { constexpr size_t num_challenges = sizeof...(Strings); - constexpr size_t bytes_per_challenge = HASH_OUTPUT_SIZE / num_challenges; - - // Ensure we have enough entropy from the hash function to construct each challenge. - static_assert(bytes_per_challenge >= MIN_BYTES_PER_CHALLENGE, "requested too many challenges in this round"); // Add challenge labels for current round to the manifest manifest.add_challenge(round_number, labels...); @@ -152,17 +149,16 @@ template class BaseTranscript { // Create challenges from bytes. std::array challenges{}; - for (size_t i = 0; i < num_challenges; ++i) { - // Initialize the buffer for the i-th challenge with 0s. - std::array field_element_buffer{}; - // Copy the i-th chunk of size `bytes_per_challenge` to the start of `field_element_buffer` - // The last bytes will be 0, - std::copy_n(next_challenge_buffer.begin() + i * bytes_per_challenge, - bytes_per_challenge, - field_element_buffer.begin()); - - // Create a FF element from a slice of bytes of next_challenge_buffer. - challenges[i] = from_buffer(field_element_buffer); + + std::array field_element_buffer{}; + std::copy_n(next_challenge_buffer.begin(), HASH_OUTPUT_SIZE, field_element_buffer.begin()); + + challenges[0] = from_buffer(field_element_buffer); + + // TODO(#583): rework the transcript to have a better structure and be able to produce a variable amount of + // challenges that are not powers of each other + for (size_t i = 1; i < num_challenges; i++) { + challenges[i] = challenges[i - 1] * challenges[0]; } // Prepare for next round. diff --git a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp b/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp index 86866fe4a2d..7981a048503 100644 --- a/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/transcript/transcript.test.cpp @@ -11,16 +11,26 @@ using namespace proof_system::honk; template class TranscriptTests : public testing::Test { - public: + 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"); + } + }; + using FF = typename Flavor::FF; - static void SetUpTestSuite() { barretenberg::srs::init_crs_factory("../srs_db/ignition"); } /** * @brief Construct a manifest for a standard Honk proof * - * @details This is where we define the "Manifest" for a Standard 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. + * @details This is where we define the "Manifest" for a Standard 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. * * @note Entries in the manifest consist of a name string and a size (bytes), NOT actual data. * @@ -85,7 +95,7 @@ template class TranscriptTests : public testing::Test { round++; // TODO(Mara): Make testing more flavor agnostic so we can test this with all flavors - if constexpr (IsGrumpkinFlavor) { + if constexpr (proof_system::IsGrumpkinFlavor) { manifest_expected.add_entry(round, "IPA:poly_degree", size_uint64); manifest_expected.add_challenge(round, "IPA:generator_challenge"); @@ -122,17 +132,18 @@ TYPED_TEST(TranscriptTests, ProverManifestConsistency) using Flavor = TypeParam; // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) typename Flavor::FF a = 1; - auto circuit_constructor = typename Flavor::CircuitBuilder(); - circuit_constructor.add_variable(a); - circuit_constructor.add_public_variable(a); + auto builder = typename Flavor::CircuitBuilder(); + builder.add_variable(a); + builder.add_public_variable(a); // Automatically generate a transcript manifest by constructing a proof auto composer = StandardComposer_(); - auto prover = composer.create_prover(circuit_constructor); - plonk::proof proof = prover.construct_proof(); + 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(prover.key->circuit_size); + auto manifest_expected = TestFixture::construct_standard_honk_manifest(instance->proving_key->circuit_size); auto prover_manifest = prover.transcript.get_manifest(); // Note: a manifest can be printed using manifest.print() for (size_t round = 0; round < manifest_expected.size(); ++round) { @@ -150,17 +161,18 @@ 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 circuit_constructor = typename Flavor::CircuitBuilder(); - circuit_constructor.add_variable(a); - circuit_constructor.add_public_variable(a); + 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 prover = composer.create_prover(circuit_constructor); - plonk::proof proof = prover.construct_proof(); + 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(circuit_constructor); + auto verifier = composer.create_verifier(instance); verifier.verify_proof(proof); prover.transcript.print(); verifier.transcript.print(); @@ -277,30 +289,34 @@ TYPED_TEST(TranscriptTests, VerifierMistake) 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. * */ -// TODO(Mara): This is not a typed test and we should have a construct_ultra_honk_manifest as well. -TYPED_TEST(TranscriptTests, UltraVerifierManifestConsistency) +TEST_F(UltraTranscriptTests, UltraVerifierManifestConsistency) { - // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) - auto circuit_constructor = proof_system::UltraCircuitBuilder(); - // fr a = 2; - // circuit_constructor.add_variable(a); - // circuit_constructor.add_public_variable(a); + // Construct a simple circuit of size n = 8 (i.e. the minimum circuit size) + auto builder = proof_system::UltraCircuitBuilder(); - circuit_constructor.add_gates_to_ensure_all_polys_are_non_zero(); + auto a = 2; + builder.add_variable(a); + builder.add_public_variable(a); // Automatically generate a transcript manifest in the prover by constructing a proof auto composer = UltraComposer(); - auto prover = composer.create_prover(circuit_constructor); - plonk::proof proof = prover.construct_proof(); + 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(circuit_constructor); + auto verifier = composer.create_verifier(instance); verifier.verify_proof(proof); prover.transcript.print(); @@ -316,3 +332,45 @@ TYPED_TEST(TranscriptTests, UltraVerifierManifestConsistency) << "Prover/Verifier manifest discrepency in round " << round; } } + +TEST_F(UltraTranscriptTests, FoldingManifestTest) +{ + auto builder_one = proof_system::UltraCircuitBuilder(); + auto a = 2; + auto b = 3; + builder_one.add_variable(a); + builder_one.add_public_variable(a); + builder_one.add_public_variable(b); + + auto builder_two = proof_system::UltraCircuitBuilder(); + a = 3; + b = 4; + builder_two.add_variable(a); + builder_two.add_variable(b); + builder_two.add_public_variable(a); + builder_two.add_public_variable(b); + + auto composer = UltraComposer(); + auto instance_one = composer.create_instance(builder_one); + auto instance_two = composer.create_instance(builder_two); + + std::vector> insts; + insts.emplace_back(instance_one); + insts.emplace_back(instance_two); + auto prover = composer.create_folding_prover(insts); + auto verifier = composer.create_folding_verifier(insts); + + auto prover_res = prover.fold_instances(); + verifier.fold_public_parameters(prover_res.folding_data); + + 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(); + 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; + } +} 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 65c5e318e99..b46390dea2b 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/composer/permutation_lib.hpp @@ -469,31 +469,6 @@ void compute_standard_honk_id_polynomials(auto proving_key) // TODO(Cody): provi } } -/** - * @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 sigma permutation polynomials for standard plonk and put them in the polynomial cache * @@ -554,6 +529,31 @@ 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/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp index dff4ac7ade1..d20a9d161e3 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/ultra_recursive_verifier.hpp @@ -31,7 +31,6 @@ template class UltraRecursiveVerifie std::shared_ptr key; std::map commitments; - std::map pcs_fr_elements; std::shared_ptr pcs_verification_key; Builder* builder; Transcript transcript; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp index 7bfc45452d1..ed46293cf95 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/verifier.test.cpp @@ -112,13 +112,14 @@ template class RecursiveVerifierTest : public testing:: { // Create proof of inner circuit InnerComposer inner_composer; - auto prover = inner_composer.create_prover(inner_circuit); + auto instance = inner_composer.create_instance(inner_circuit); + auto prover = inner_composer.create_prover(instance); auto proof_to_recursively_verify = prover.construct_proof(); - info("Inner circuit size = ", prover.key->circuit_size); + info("Inner circuit size = ", instance->proving_key->circuit_size); // Compute native verification key - const auto native_verification_key = inner_composer.compute_verification_key(inner_circuit); + const auto native_verification_key = instance->compute_verification_key(); // Instantiate the recursive verification key from the native verification key auto verification_key = std::make_shared(&outer_builder, native_verification_key); @@ -128,7 +129,7 @@ template class RecursiveVerifierTest : public testing:: auto pairing_points = verifier.verify_proof(proof_to_recursively_verify); // For testing purposes only, perform native verification and compare the result - auto native_verifier = inner_composer.create_verifier(inner_circuit); + auto native_verifier = inner_composer.create_verifier(instance); auto native_result = native_verifier.verify_proof(proof_to_recursively_verify); // Extract the pairing points from the recursive verifier output and perform the pairing natively. The result @@ -187,8 +188,9 @@ template class RecursiveVerifierTest : public testing:: // Compute native verification key InnerComposer inner_composer; - auto prover = inner_composer.create_prover(inner_circuit); // A prerequisite for computing VK - const auto native_verification_key = inner_composer.compute_verification_key(inner_circuit); + auto instance = inner_composer.create_instance(inner_circuit); + auto prover = inner_composer.create_prover(instance); // A prerequisite for computing VK + const auto native_verification_key = instance->compute_verification_key(); // Instantiate the recursive verification key from the native verification key auto verification_key = std::make_shared(&outer_circuit, native_verification_key);