From 9c9b561f392de5fce11cefe4d72e4f33f2567f41 Mon Sep 17 00:00:00 2001 From: maramihali Date: Fri, 1 Dec 2023 06:06:35 +0000 Subject: [PATCH] chore: Refactor `WitnessEntities` to be able to derive `WitnessCommitments` from it (#3479) This PR removes the sorted polynomials from `WitnessEntities` and moves them as part of the `ProverInstance` since they are not actual witness polynomials that we _commit_ to, just used to compute the sorted accumulator polynomial. This allows us to define a `WitnessCommitments` structure from `WitnessEntities`. The Prover will be responsible for computing the `Instance`'s` WitnessCommitments`. Moreover, the task of computing the `VerificationKey` is moved to the `Composer`, as the Instance should not have the `CommitmentKey`. --- .../src/barretenberg/flavor/goblin_ultra.hpp | 33 ++++---- .../flavor/goblin_ultra_recursive.hpp | 28 +++---- .../cpp/src/barretenberg/flavor/ultra.hpp | 19 +++-- .../barretenberg/flavor/ultra_recursive.hpp | 14 +--- .../honk/verifier/goblin_verifier.test.cpp | 25 +++--- .../recursion/honk/verifier/verifier.test.cpp | 23 +++--- .../sumcheck/instance/prover_instance.cpp | 80 ++----------------- .../sumcheck/instance/prover_instance.hpp | 7 +- .../instance/prover_instance.test.cpp | 16 ++-- .../ultra_honk/ultra_composer.cpp | 68 ++++++++++++++-- .../ultra_honk/ultra_composer.hpp | 17 ++-- .../barretenberg/ultra_honk/ultra_prover.cpp | 64 +++++++++------ .../barretenberg/ultra_honk/ultra_prover.hpp | 2 +- 13 files changed, 192 insertions(+), 204 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp index aba9d98ce95..e67ede73ba1 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra.hpp @@ -42,7 +42,7 @@ class GoblinUltra { // assignment of witnesses. We again choose a neutral name. static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 28; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 18; + static constexpr size_t NUM_WITNESS_ENTITIES = 14; using GrandProductRelations = std::tuple, proof_system::LookupRelation>; @@ -139,28 +139,22 @@ class GoblinUltra { w_r, // column 1 w_o, // column 2 w_4, // column 3 - sorted_1, // column 4 - sorted_2, // column 5 - sorted_3, // column 6 - sorted_4, // column 7 - sorted_accum, // column 8 - z_perm, // column 9 - z_lookup, // column 10 - ecc_op_wire_1, // column 11 - ecc_op_wire_2, // column 12 - ecc_op_wire_3, // column 13 - ecc_op_wire_4, // column 14 - calldata, // column 15 - calldata_read_counts, // column 16 - lookup_inverses // column 17 + sorted_accum, // column 4 + z_perm, // column 5 + z_lookup, // column 6 + ecc_op_wire_1, // column 7 + ecc_op_wire_2, // column 8 + ecc_op_wire_3, // column 9 + ecc_op_wire_4, // column 10 + calldata, // column 11 + calldata_read_counts, // column 12 + lookup_inverses // column 13 ) RefVector get_wires() { return { w_l, w_r, w_o, w_4 }; }; RefVector get_ecc_op_wires() { return { ecc_op_wire_1, ecc_op_wire_2, ecc_op_wire_3, ecc_op_wire_4 }; }; - // The sorted concatenations of table and witness data needed for plookup. - RefVector get_sorted_polynomials() { return { sorted_1, sorted_2, sorted_3, sorted_4 }; }; }; /** @@ -376,6 +370,11 @@ class GoblinUltra { } }; + /** + * @brief A container for the witness commitments. + */ + using WitnessCommitments = WitnessEntities; + /** * @brief A container for commitment labels. * @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It diff --git a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp index f3ce7853066..dd2a5e7ac5f 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/goblin_ultra_recursive.hpp @@ -67,7 +67,7 @@ template class GoblinUltraRecursive_ { // assignment of witnesses. We again choose a neutral name. static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 28; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 18; + static constexpr size_t NUM_WITNESS_ENTITIES = 14; // define the tuple of Relations that comprise the Sumcheck relation using Relations = std::tuple, @@ -153,20 +153,16 @@ template class GoblinUltraRecursive_ { w_r, // column 1 w_o, // column 2 w_4, // column 3 - sorted_1, // column 4 - sorted_2, // column 5 - sorted_3, // column 6 - sorted_4, // column 7 - sorted_accum, // column 8 - z_perm, // column 9 - z_lookup, // column 10 - ecc_op_wire_1, // column 11 - ecc_op_wire_2, // column 12 - ecc_op_wire_3, // column 13 - ecc_op_wire_4, // column 14 - calldata, // column 15 - calldata_read_counts, // column 16 - lookup_inverses // column 17 + sorted_accum, // column 4 + z_perm, // column 5 + z_lookup, // column 6 + ecc_op_wire_1, // column 7 + ecc_op_wire_2, // column 8 + ecc_op_wire_3, // column 9 + ecc_op_wire_4, // column 10 + calldata, // column 11 + calldata_read_counts, // column 12 + lookup_inverses // column 13 ) RefVector get_wires() { return { w_l, w_r, w_o, w_4 }; }; @@ -174,8 +170,6 @@ template class GoblinUltraRecursive_ { { return { ecc_op_wire_1, ecc_op_wire_2, ecc_op_wire_3, ecc_op_wire_4 }; }; - // The sorted concatenations of table and witness data needed for plookup. - RefVector get_sorted_polynomials() { return { sorted_1, sorted_2, sorted_3, sorted_4 }; }; }; /** diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp index 1e987fe09c5..44c65bf9e78 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra.hpp @@ -41,7 +41,7 @@ class Ultra { // assignment of witnesses. We again choose a neutral name. static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 11; + static constexpr size_t NUM_WITNESS_ENTITIES = 7; using GrandProductRelations = std::tuple, proof_system::LookupRelation>; @@ -133,17 +133,11 @@ class Ultra { w_r, // column 1 w_o, // column 2 w_4, // column 3 - sorted_1, // column 4 - sorted_2, // column 5 - sorted_3, // column 6 - sorted_4, // column 7 - sorted_accum, // column 8 - z_perm, // column 9 - z_lookup) // column 10 + sorted_accum, // column 4 + z_perm, // column 5 + z_lookup) // column 6 RefVector get_wires() { return { w_l, w_r, w_o, w_4 }; }; - // The sorted concatenations of table and witness data needed for plookup. - RefVector get_sorted_polynomials() { return { sorted_1, sorted_2, sorted_3, sorted_4 }; }; }; /** @@ -306,6 +300,11 @@ class Ultra { */ using ExtendedEdges = ProverUnivariates; + /** + * @brief A container for the witness commitments. + */ + using WitnessCommitments = WitnessEntities; + /** * @brief A container for commitment labels. * @note It's debatable whether this should inherit from AllEntities. since most entries are not strictly needed. It diff --git a/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp b/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp index c89a2254d3d..b9980e0d071 100644 --- a/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp +++ b/barretenberg/cpp/src/barretenberg/flavor/ultra_recursive.hpp @@ -67,7 +67,7 @@ template class UltraRecursive_ { // assignment of witnesses. We again choose a neutral name. static constexpr size_t NUM_PRECOMPUTED_ENTITIES = 25; // The total number of witness entities not including shifts. - static constexpr size_t NUM_WITNESS_ENTITIES = 11; + static constexpr size_t NUM_WITNESS_ENTITIES = 7; // define the tuple of Relations that comprise the Sumcheck relation using Relations = std::tuple, @@ -145,19 +145,13 @@ template class UltraRecursive_ { w_r, // column 1 w_o, // column 2 w_4, // column 3 - sorted_1, // column 4 - sorted_2, // column 5 - sorted_3, // column 6 - sorted_4, // column 7 - sorted_accum, // column 8 - z_perm, // column 9 - z_lookup // column 10 + sorted_accum, // column 4 + z_perm, // column 5 + z_lookup // column 6 ); RefVector get_wires() { return { w_l, w_r, w_o, w_4 }; }; - // The sorted concatenations of table and witness data needed for plookup. - RefVector get_sorted_polynomials() { return { sorted_1, sorted_2, sorted_3, sorted_4 }; }; }; /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp index 4dbdf3bc178..d1957a6d4ff 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/recursion/honk/verifier/goblin_verifier.test.cpp @@ -135,21 +135,20 @@ template class GoblinRecursiveVerifierTest : public testi InnerComposer inner_composer; 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 OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); + auto verification_key = std::make_shared(&outer_circuit, instance->verification_key); // Spot check some values in the recursive VK to ensure it was constructed correctly - EXPECT_EQ(verification_key->circuit_size, native_verification_key->circuit_size); - EXPECT_EQ(verification_key->log_circuit_size, native_verification_key->log_circuit_size); - EXPECT_EQ(verification_key->num_public_inputs, native_verification_key->num_public_inputs); - EXPECT_EQ(verification_key->q_m.get_value(), native_verification_key->q_m); - EXPECT_EQ(verification_key->q_r.get_value(), native_verification_key->q_r); - EXPECT_EQ(verification_key->sigma_1.get_value(), native_verification_key->sigma_1); - EXPECT_EQ(verification_key->id_3.get_value(), native_verification_key->id_3); - EXPECT_EQ(verification_key->lagrange_ecc_op.get_value(), native_verification_key->lagrange_ecc_op); + EXPECT_EQ(verification_key->circuit_size, instance->verification_key->circuit_size); + EXPECT_EQ(verification_key->log_circuit_size, instance->verification_key->log_circuit_size); + EXPECT_EQ(verification_key->num_public_inputs, instance->verification_key->num_public_inputs); + EXPECT_EQ(verification_key->q_m.get_value(), instance->verification_key->q_m); + EXPECT_EQ(verification_key->q_r.get_value(), instance->verification_key->q_r); + EXPECT_EQ(verification_key->sigma_1.get_value(), instance->verification_key->sigma_1); + EXPECT_EQ(verification_key->id_3.get_value(), instance->verification_key->id_3); + EXPECT_EQ(verification_key->lagrange_ecc_op.get_value(), instance->verification_key->lagrange_ecc_op); } /** @@ -166,11 +165,10 @@ template class GoblinRecursiveVerifierTest : public testi auto instance = inner_composer.create_instance(inner_circuit); auto inner_prover = inner_composer.create_prover(instance); auto inner_proof = inner_prover.construct_proof(); - const auto native_verification_key = instance->compute_verification_key(); // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); + auto verification_key = std::make_shared(&outer_circuit, instance->verification_key); RecursiveVerifier verifier(&outer_circuit, verification_key); auto pairing_points = verifier.verify_proof(inner_proof); @@ -213,7 +211,6 @@ template class GoblinRecursiveVerifierTest : public testi auto instance = inner_composer.create_instance(inner_circuit); auto inner_prover = inner_composer.create_prover(instance); auto inner_proof = inner_prover.construct_proof(); - const auto native_verification_key = instance->compute_verification_key(); // Arbitrarily tamper with the proof to be verified inner_prover.transcript.deserialize_full_transcript(); @@ -223,7 +220,7 @@ template class GoblinRecursiveVerifierTest : public testi // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); + auto verification_key = std::make_shared(&outer_circuit, instance->verification_key); RecursiveVerifier verifier(&outer_circuit, verification_key); verifier.verify_proof(inner_proof); 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 29c5b9bd639..0852c45cc70 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 @@ -120,19 +120,18 @@ template class RecursiveVerifierTest : public testing::Te InnerComposer inner_composer; 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); + auto verification_key = std::make_shared(&outer_circuit, instance->verification_key); // Spot check some values in the recursive VK to ensure it was constructed correctly - EXPECT_EQ(verification_key->circuit_size, native_verification_key->circuit_size); - EXPECT_EQ(verification_key->log_circuit_size, native_verification_key->log_circuit_size); - EXPECT_EQ(verification_key->num_public_inputs, native_verification_key->num_public_inputs); - EXPECT_EQ(verification_key->q_m.get_value(), native_verification_key->q_m); - EXPECT_EQ(verification_key->q_r.get_value(), native_verification_key->q_r); - EXPECT_EQ(verification_key->sigma_1.get_value(), native_verification_key->sigma_1); - EXPECT_EQ(verification_key->id_3.get_value(), native_verification_key->id_3); + EXPECT_EQ(verification_key->circuit_size, instance->verification_key->circuit_size); + EXPECT_EQ(verification_key->log_circuit_size, instance->verification_key->log_circuit_size); + EXPECT_EQ(verification_key->num_public_inputs, instance->verification_key->num_public_inputs); + EXPECT_EQ(verification_key->q_m.get_value(), instance->verification_key->q_m); + EXPECT_EQ(verification_key->q_r.get_value(), instance->verification_key->q_r); + EXPECT_EQ(verification_key->sigma_1.get_value(), instance->verification_key->sigma_1); + EXPECT_EQ(verification_key->id_3.get_value(), instance->verification_key->id_3); } /** @@ -150,11 +149,10 @@ template class RecursiveVerifierTest : public testing::Te auto instance = inner_composer.create_instance(inner_circuit); auto inner_prover = inner_composer.create_prover(instance); auto inner_proof = inner_prover.construct_proof(); - const auto native_verification_key = instance->compute_verification_key(); // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); + auto verification_key = std::make_shared(&outer_circuit, instance->verification_key); RecursiveVerifier verifier(&outer_circuit, verification_key); auto pairing_points = verifier.verify_proof(inner_proof); @@ -198,7 +196,6 @@ template class RecursiveVerifierTest : public testing::Te auto instance = inner_composer.create_instance(inner_circuit); auto inner_prover = inner_composer.create_prover(instance); auto inner_proof = inner_prover.construct_proof(); - const auto native_verification_key = instance->compute_verification_key(); // Arbitrarily tamper with the proof to be verified inner_prover.transcript.deserialize_full_transcript(); @@ -208,7 +205,7 @@ template class RecursiveVerifierTest : public testing::Te // Create a recursive verification circuit for the proof of the inner circuit OuterBuilder outer_circuit; - auto verification_key = std::make_shared(&outer_circuit, native_verification_key); + auto verification_key = std::make_shared(&outer_circuit, instance->verification_key); RecursiveVerifier verifier(&outer_circuit, verification_key); verifier.verify_proof(inner_proof); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp index 34f2842eede..41924b71875 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp @@ -66,11 +66,10 @@ template void ProverInstance_::compute_witness(Circuit& c construct_databus_polynomials(circuit); } - // 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); + // Initialise the sorted concatenated list polynomials for the lookup argument + for (auto& s_i : sorted_polynomials) { + s_i = Polynomial(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 @@ -116,21 +115,14 @@ template void ProverInstance_::compute_witness(Circuit& c 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; + sorted_polynomials[0][s_index] = components[0]; + sorted_polynomials[1][s_index] = components[1]; + sorted_polynomials[2][s_index] = components[2]; + sorted_polynomials[3][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 @@ -392,8 +384,6 @@ template void ProverInstance_::compute_sorted_list_accumu 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]; @@ -481,60 +471,6 @@ template void ProverInstance_::compute_grand_product_poly 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); - - 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 these polynomials - // due to their simple structure. - if constexpr (IsGoblinFlavor) { - verification_key->lagrange_ecc_op = commitment_key->commit(proving_key->lagrange_ecc_op); - verification_key->q_busread = commitment_key->commit(proving_key->q_busread); - verification_key->databus_id = commitment_key->commit(proving_key->databus_id); - } - - return verification_key; -} - template class ProverInstance_; template class ProverInstance_; diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp index c72e940a206..5f12dc0c1dd 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp @@ -27,13 +27,16 @@ template class ProverInstance_ { using FoldingParameters = typename Flavor::FoldingParameters; using ProverPolynomials = typename Flavor::ProverPolynomials; using Polynomial = typename Flavor::Polynomial; + using WitnessCommitments = typename Flavor::WitnessCommitments; public: std::shared_ptr proving_key; std::shared_ptr verification_key; - std::shared_ptr commitment_key; ProverPolynomials prover_polynomials; + WitnessCommitments witness_commitments; + + std::array sorted_polynomials; // The number of public inputs has to be the same for all instances because they are // folded element by element. @@ -64,8 +67,6 @@ template class ProverInstance_ { ProverInstance_() = default; ~ProverInstance_() = default; - std::shared_ptr compute_verification_key(); - void initialize_prover_polynomials(); void compute_sorted_accumulator_polynomials(FF); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp index a4c2884904e..6fb7eeab3ed 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp @@ -60,14 +60,7 @@ template class InstanceTests : public testing::Test { // 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); - } + auto sorted_list_polynomials = instance.sorted_polynomials; // Method 1: computed sorted list accumulator polynomial using prover library method instance.compute_sorted_list_accumulator(eta); @@ -78,10 +71,11 @@ template class InstanceTests : public testing::Test { 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] }; + Polynomial sorted_list_accumulator_expected{ sorted_list_polynomials[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; + sorted_list_accumulator_expected[i] += sorted_list_polynomials[1][i] * eta + + sorted_list_polynomials[2][i] * eta_sqr + + sorted_list_polynomials[3][i] * eta_cube; } EXPECT_EQ(sorted_list_accumulator, sorted_list_accumulator_expected); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.cpp index ff8cf11b869..716c83d09a4 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.cpp @@ -6,20 +6,78 @@ namespace proof_system::honk { +/** + * Compute verification key consisting of selector precommitments. + * + * @return Pointer to the resulting verification key of the Instance. + * */ +template +void UltraComposer_::compute_verification_key(std::shared_ptr> instance) +{ + if (instance->verification_key) { + return; + } + + auto& proving_key = instance->proving_key; + + auto 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); + + 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 these polynomials + // due to their simple structure. + if constexpr (IsGoblinFlavor) { + verification_key->lagrange_ecc_op = commitment_key->commit(proving_key->lagrange_ecc_op); + verification_key->q_busread = commitment_key->commit(proving_key->q_busread); + verification_key->databus_id = commitment_key->commit(proving_key->databus_id); + } + + instance->verification_key = std::move(verification_key); +} + template std::shared_ptr> UltraComposer_::create_instance(CircuitBuilder& circuit) { 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); + commitment_key = compute_commitment_key(instance->proving_key->circuit_size); + + compute_verification_key(instance); return instance; } template UltraProver_ UltraComposer_::create_prover(std::shared_ptr instance) { - UltraProver_ output_state(instance); + UltraProver_ output_state(instance, commitment_key); return output_state; } @@ -27,9 +85,9 @@ UltraProver_ UltraComposer_::create_prover(std::shared_ptr UltraVerifier_ UltraComposer_::create_verifier(std::shared_ptr instance) { - 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_); + UltraVerifier_ output_state(instance->verification_key); + auto pcs_verification_key = + std::make_unique(instance->verification_key->circuit_size, crs_factory_); output_state.pcs_verification_key = std::move(pcs_verification_key); return output_state; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp index 3cd04b03ff1..33840e32bc7 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_composer.hpp @@ -29,8 +29,6 @@ template class UltraComposer_ { static constexpr size_t num_zero_rows = Flavor::has_zero_row ? 1 : 0; static constexpr std::string_view NAME_STRING = "UltraHonk"; static constexpr size_t NUM_WIRES = CircuitBuilder::NUM_WIRES; - std::shared_ptr proving_key; - std::shared_ptr verification_key; // The crs_factory holds the path to the srs and exposes methods to extract the srs elements std::shared_ptr> crs_factory_; @@ -43,11 +41,6 @@ template class UltraComposer_ { : crs_factory_(std::move(crs_factory)) {} - UltraComposer_(std::shared_ptr p_key, std::shared_ptr v_key) - : proving_key(std::move(p_key)) - , verification_key(std::move(v_key)) - {} - UltraComposer_(UltraComposer_&& other) noexcept = default; UltraComposer_(UltraComposer_ const& other) noexcept = default; UltraComposer_& operator=(UltraComposer_&& other) noexcept = default; @@ -104,13 +97,21 @@ template class UltraComposer_ { { std::vector> vks; for (const auto& inst : instances) { - vks.emplace_back(inst->compute_verification_key()); + vks.emplace_back(inst->verification_key); } VerifierInstances insts(vks); ProtoGalaxyVerifier_ output_state(insts); return output_state; }; + + private: + /** + * @brief Compute the verification key of an Instance, produced from a finalised circuit. + * + * @param inst + */ + void compute_verification_key(std::shared_ptr); }; extern template class UltraComposer_; extern template class UltraComposer_; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp index 40ef84501b6..6c316094ceb 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.cpp @@ -12,9 +12,9 @@ namespace proof_system::honk { * @tparam a type of UltraFlavor * */ template -UltraProver_::UltraProver_(std::shared_ptr inst) +UltraProver_::UltraProver_(std::shared_ptr inst, std::shared_ptr commitment_key) : instance(std::move(inst)) - , commitment_key(instance->commitment_key) + , commitment_key(commitment_key) { instance->initialize_prover_polynomials(); } @@ -40,31 +40,46 @@ template void UltraProver_::execute_preamble_round( } /** - * @brief Compute commitments to the first three wire polynomials (and ECC op wires if using Goblin). - * + * @brief Commit to the wire polynomials (part of the witness), with the exception of the fourth wire, which is + * only commited to after adding memory records. In the Goblin Flavor, we also commit to the ECC OP wires and the + * DataBus columns. */ template void UltraProver_::execute_wire_commitments_round() { + auto& witness_commitments = instance->witness_commitments; + auto& proving_key = instance->proving_key; + // 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(); + // We only commit to the fourth wire polynomial after adding memory recordss + witness_commitments.w_l = commitment_key->commit(proving_key->w_l); + witness_commitments.w_r = commitment_key->commit(proving_key->w_r); + witness_commitments.w_o = commitment_key->commit(proving_key->w_o); + + auto wire_comms = witness_commitments.get_wires(); auto labels = commitment_labels.get_wires(); for (size_t idx = 0; idx < 3; ++idx) { - transcript.send_to_verifier(labels[idx], commitment_key->commit(wire_polys[idx])); + transcript.send_to_verifier(labels[idx], wire_comms[idx]); } if constexpr (IsGoblinFlavor) { // Commit to Goblin ECC op wires - auto op_wire_polys = instance->proving_key->get_ecc_op_wires(); + witness_commitments.ecc_op_wire_1 = commitment_key->commit(proving_key->ecc_op_wire_1); + witness_commitments.ecc_op_wire_2 = commitment_key->commit(proving_key->ecc_op_wire_2); + witness_commitments.ecc_op_wire_3 = commitment_key->commit(proving_key->ecc_op_wire_3); + witness_commitments.ecc_op_wire_4 = commitment_key->commit(proving_key->ecc_op_wire_4); + + auto op_wire_comms = instance->witness_commitments.get_ecc_op_wires(); auto labels = commitment_labels.get_ecc_op_wires(); for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - transcript.send_to_verifier(labels[idx], commitment_key->commit(op_wire_polys[idx])); + transcript.send_to_verifier(labels[idx], op_wire_comms[idx]); } + // Commit to DataBus columns - transcript.send_to_verifier(commitment_labels.calldata, - commitment_key->commit(instance->proving_key->calldata)); + witness_commitments.calldata = commitment_key->commit(proving_key->calldata); + witness_commitments.calldata_read_counts = commitment_key->commit(proving_key->calldata_read_counts); + transcript.send_to_verifier(commitment_labels.calldata, instance->witness_commitments.calldata); transcript.send_to_verifier(commitment_labels.calldata_read_counts, - commitment_key->commit(instance->proving_key->calldata_read_counts)); + instance->witness_commitments.calldata_read_counts); } } @@ -78,12 +93,14 @@ template void UltraProver_::execute_sorted_list_acc instance->compute_sorted_accumulator_polynomials(eta); + auto& witness_commitments = instance->witness_commitments; // Commit to the sorted withness-table accumulator and the finalized (i.e. with memory records) fourth wire // polynomial - auto sorted_accum_commitment = commitment_key->commit(instance->proving_key->sorted_accum); - auto w_4_commitment = commitment_key->commit(instance->proving_key->w_4); - transcript.send_to_verifier(commitment_labels.sorted_accum, sorted_accum_commitment); - transcript.send_to_verifier(commitment_labels.w_4, w_4_commitment); + witness_commitments.sorted_accum = commitment_key->commit(instance->prover_polynomials.sorted_accum); + witness_commitments.w_4 = commitment_key->commit(instance->prover_polynomials.w_4); + + transcript.send_to_verifier(commitment_labels.sorted_accum, instance->witness_commitments.sorted_accum); + transcript.send_to_verifier(commitment_labels.w_4, instance->witness_commitments.w_4); } /** @@ -99,9 +116,9 @@ template void UltraProver_::execute_log_derivative_ if constexpr (IsGoblinFlavor) { instance->compute_logderivative_inverse(beta, gamma); - - auto lookup_inverses_commitment = commitment_key->commit(instance->proving_key->lookup_inverses); - transcript.send_to_verifier(commitment_labels.lookup_inverses, lookup_inverses_commitment); + instance->witness_commitments.lookup_inverses = + commitment_key->commit(instance->prover_polynomials.lookup_inverses); + transcript.send_to_verifier(commitment_labels.lookup_inverses, instance->witness_commitments.lookup_inverses); } } @@ -114,10 +131,11 @@ template void UltraProver_::execute_grand_product_c instance->compute_grand_product_polynomials(relation_parameters.beta, relation_parameters.gamma); - auto z_perm_commitment = commitment_key->commit(instance->proving_key->z_perm); - auto z_lookup_commitment = commitment_key->commit(instance->proving_key->z_lookup); - transcript.send_to_verifier(commitment_labels.z_perm, z_perm_commitment); - transcript.send_to_verifier(commitment_labels.z_lookup, z_lookup_commitment); + auto& witness_commitments = instance->witness_commitments; + witness_commitments.z_perm = commitment_key->commit(instance->prover_polynomials.z_perm); + witness_commitments.z_lookup = commitment_key->commit(instance->prover_polynomials.z_lookup); + transcript.send_to_verifier(commitment_labels.z_perm, instance->witness_commitments.z_perm); + transcript.send_to_verifier(commitment_labels.z_lookup, instance->witness_commitments.z_lookup); } /** diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp index fe50c8e0c80..9d660067229 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_prover.hpp @@ -23,7 +23,7 @@ template class UltraProver_ { using Transcript = typename Flavor::Transcript; public: - explicit UltraProver_(std::shared_ptr); + explicit UltraProver_(std::shared_ptr, std::shared_ptr); BBERG_PROFILE void execute_preamble_round(); BBERG_PROFILE void execute_wire_commitments_round(); BBERG_PROFILE void execute_sorted_list_accumulator_round();