From cbe3d938d8d81a84b9d7f6b776847726a5de34c3 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 17 Feb 2025 18:26:37 +0000 Subject: [PATCH 01/33] add ecc tables to op queue, update but dont use --- .../op_queue/ecc_op_queue.hpp | 54 +++++++++---------- .../op_queue/ecc_ops_table.hpp | 16 +++++- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index 33b462a68602..34f48f5ac72d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -3,24 +3,10 @@ #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/eccvm/eccvm_builder_types.hpp" #include "barretenberg/stdlib/primitives/bigfield/constants.hpp" +#include "barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp" #include "barretenberg/stdlib_circuit_builders/op_queue/eccvm_row_tracker.hpp" namespace bb { -enum EccOpCode { NULL_OP, ADD_ACCUM, MUL_ACCUM, EQUALITY }; - -struct UltraOp { - using Fr = curve::BN254::ScalarField; - EccOpCode op_code = NULL_OP; - Fr op; - Fr x_lo; - Fr x_hi; - Fr y_lo; - Fr y_hi; - Fr z_1; - Fr z_2; - bool return_is_infinity; -}; - /** * @brief Used to construct execution trace representations of elliptic curve operations. * @@ -44,6 +30,9 @@ class ECCOpQueue { std::vector> raw_ops; std::array, 4> ultra_ops; // ops encoded in the width-4 Ultra format + RawEccOpsTable raw_ops_table; + UltraEccOpsTable ultra_ops_table; + size_t current_ultra_ops_size = 0; // M_i size_t previous_ultra_ops_size = 0; // M_{i-1} @@ -55,6 +44,14 @@ class ECCOpQueue { public: using ECCVMOperation = bb::eccvm::VMOperation; + ECCOpQueue() { initialize_new_subtable(); } + + void initialize_new_subtable() + { + raw_ops_table.create_new_subtable(); + ultra_ops_table.create_new_subtable(); + } + const std::vector& get_raw_ops() { return raw_ops; } /** @@ -106,12 +103,7 @@ class ECCOpQueue { * @warning This is for testing purposes only. Currently no valid use case. * */ - void empty_row_for_testing() - { - raw_ops.emplace_back(ECCVMOperation{ .base_point = point_at_infinity }); - - eccvm_row_tracker.update_cached_msms(raw_ops.back()); - } + void empty_row_for_testing() { append_raw_op(ECCVMOperation{ .base_point = point_at_infinity }); } Point get_accumulator() { return accumulator; } @@ -175,8 +167,7 @@ class ECCOpQueue { accumulator = accumulator + to_add; // Store the raw operation - raw_ops.emplace_back(ECCVMOperation{ .add = true, .base_point = to_add }); - eccvm_row_tracker.update_cached_msms(raw_ops.back()); + append_raw_op(ECCVMOperation{ .add = true, .base_point = to_add }); // Construct and store the operation in the ultra op format return construct_and_populate_ultra_ops(ADD_ACCUM, to_add); @@ -196,14 +187,13 @@ class ECCOpQueue { UltraOp ultra_op = construct_and_populate_ultra_ops(MUL_ACCUM, to_mul, scalar); // Store the raw operation - raw_ops.emplace_back(ECCVMOperation{ + append_raw_op(ECCVMOperation{ .mul = true, .base_point = to_mul, .z1 = ultra_op.z_1, .z2 = ultra_op.z_2, .mul_scalar_full = scalar, }); - eccvm_row_tracker.update_cached_msms(raw_ops.back()); return ultra_op; } @@ -215,8 +205,7 @@ class ECCOpQueue { UltraOp no_op() { // Store raw operation - raw_ops.emplace_back(ECCVMOperation{}); - eccvm_row_tracker.update_cached_msms(raw_ops.back()); + append_raw_op(ECCVMOperation{}); // Construct and store the operation in the ultra op format return construct_and_populate_ultra_ops(NULL_OP, accumulator); @@ -233,14 +222,19 @@ class ECCOpQueue { accumulator.self_set_infinity(); // Store raw operation - raw_ops.emplace_back(ECCVMOperation{ .eq = true, .reset = true, .base_point = expected }); - eccvm_row_tracker.update_cached_msms(raw_ops.back()); + append_raw_op(ECCVMOperation{ .eq = true, .reset = true, .base_point = expected }); // Construct and store the operation in the ultra op format return construct_and_populate_ultra_ops(EQUALITY, expected); } private: + void append_raw_op(const ECCVMOperation& op) + { + raw_ops.emplace_back(op); + eccvm_row_tracker.update_cached_msms(raw_ops.back()); + raw_ops_table.push(op); + } /** * @brief Given an ecc operation and its inputs, decompose into ultra format and populate ultra_ops * @@ -288,6 +282,8 @@ class ECCOpQueue { append_to_ultra_ops(ultra_op); + ultra_ops_table.push(ultra_op); + return ultra_op; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index 890e117a478a..1eca6d4eae7a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -2,10 +2,24 @@ #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/eccvm/eccvm_builder_types.hpp" -#include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp" #include namespace bb { +enum EccOpCode { NULL_OP, ADD_ACCUM, MUL_ACCUM, EQUALITY }; + +struct UltraOp { + using Fr = curve::BN254::ScalarField; + EccOpCode op_code = NULL_OP; + Fr op; + Fr x_lo; + Fr x_hi; + Fr y_lo; + Fr y_hi; + Fr z_1; + Fr z_2; + bool return_is_infinity; +}; + /** * @brief A table of ECC operations * @details The table is constructed via concatenation of subtables of ECC operations. The table concatentation protocol From 0c41158f3c94058bcc0d106389f7e2dbb3145a7b Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 17 Feb 2025 20:35:01 +0000 Subject: [PATCH 02/33] test of basic poly construction functionality based on ecc tables --- .../op_queue/ecc_op_queue.hpp | 46 +++++++ .../op_queue/ecc_ops_table.hpp | 52 ++++++- .../ultra_honk/mega_honk.test.cpp | 73 ++++++++++ .../ultra_honk/merge_prover_new.cpp | 130 ++++++++++++++++++ .../ultra_honk/merge_prover_new.hpp | 41 ++++++ .../ultra_honk/merge_verifier_new.cpp | 89 ++++++++++++ .../ultra_honk/merge_verifier_new.hpp | 36 +++++ 7 files changed, 465 insertions(+), 2 deletions(-) create mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp create mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.hpp create mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp create mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.hpp diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index 34f48f5ac72d..1526ccc28887 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -2,6 +2,7 @@ #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/eccvm/eccvm_builder_types.hpp" +#include "barretenberg/polynomials/polynomial.hpp" #include "barretenberg/stdlib/primitives/bigfield/constants.hpp" #include "barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp" #include "barretenberg/stdlib_circuit_builders/op_queue/eccvm_row_tracker.hpp" @@ -52,6 +53,50 @@ class ECCOpQueue { ultra_ops_table.create_new_subtable(); } + std::array, 4> get_ultra_ops_table_columns() const + { + const size_t table_size = ultra_ops_table.ultra_table_size(); + std::array, 4> column_polynomials; + std::array, 4> column_spans; + for (auto [column_span, column] : zip_view(column_spans, column_polynomials)) { + column = Polynomial(table_size); + column_span = column.coeffs(); + } + ultra_ops_table.populate_table_columns(column_spans); + return column_polynomials; + } + + std::array, 4> get_previous_ultra_ops_table_columns() const + { + const size_t table_size = ultra_ops_table.ultra_table_size(); + const size_t current_subtable_size = ultra_ops_table.current_ultra_subtable_size(); + const size_t previous_table_size = table_size - current_subtable_size; + std::array, 4> column_polynomials; + std::array, 4> column_spans; + for (auto [column_span, column] : zip_view(column_spans, column_polynomials)) { + column = Polynomial(previous_table_size, table_size); + column_span = column.coeffs(); + } + ultra_ops_table.populate_previous_table_columns(column_spans); + return column_polynomials; + } + + std::array, 4> get_current_subtable_columns() const + { + const size_t current_subtable_size = ultra_ops_table.current_ultra_subtable_size(); + std::array, 4> column_polynomials; + std::array, 4> column_spans; + for (auto [column_span, column] : zip_view(column_spans, column_polynomials)) { + column = Polynomial(current_subtable_size); + column_span = column.coeffs(); + } + ultra_ops_table.populate_current_subtable_columns(column_spans); + return column_polynomials; + } + + size_t get_ultra_ops_table_size() const { return ultra_ops_table.ultra_table_size(); } + size_t get_current_ultra_ops_subtable_size() const { return ultra_ops_table.current_ultra_subtable_size(); } + const std::vector& get_raw_ops() { return raw_ops; } /** @@ -117,6 +162,7 @@ class ECCOpQueue { { previous_ultra_ops_size = current_ultra_ops_size; current_ultra_ops_size = ultra_ops[0].size(); + initialize_new_subtable(); } [[nodiscard]] size_t get_previous_size() const { return previous_ultra_ops_size; } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index 1eca6d4eae7a..0ec52d748063 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -85,15 +85,20 @@ using RawEccOpsTable = EccOpsTable>; * polynomials in the proving system. */ class UltraEccOpsTable { + static constexpr size_t TABLE_WIDTH = 4; + static constexpr size_t NUM_ROWS_PER_OP = 2; + using Curve = curve::BN254; using Fr = Curve::ScalarField; using UltraOpsTable = EccOpsTable; + using TableView = std::array, TABLE_WIDTH>; UltraOpsTable table; - static constexpr size_t TABLE_WIDTH = 4; public: size_t size() const { return table.size(); } + size_t ultra_table_size() const { return table.size() * NUM_ROWS_PER_OP; } + size_t current_ultra_subtable_size() const { return table.get()[0].size() * NUM_ROWS_PER_OP; } void create_new_subtable(size_t size_hint = 0) { table.create_new_subtable(size_hint); } void push(const UltraOp& op) { table.push(op); } @@ -102,7 +107,7 @@ class UltraEccOpsTable { * @todo multithreaded this functionality * @param target_columns */ - void populate_column_data(std::array, TABLE_WIDTH>& target_columns) + void populate_column_data(std::array, TABLE_WIDTH>& target_columns) const { size_t i = 0; for (const auto& subtable : table.get()) { @@ -120,6 +125,49 @@ class UltraEccOpsTable { } } } + + void populate_column_data_from_subtables(std::array, TABLE_WIDTH>& target_columns, + const size_t start_idx, + const size_t end_idx) const + { + size_t i = 0; + for (size_t j = start_idx; j < end_idx; ++j) { + const auto& subtable = table.get()[j]; + for (const auto& op : subtable) { + target_columns[0][i] = op.op; + target_columns[1][i] = op.x_lo; + target_columns[2][i] = op.x_hi; + target_columns[3][i] = op.y_lo; + i++; + target_columns[0][i] = 0; // only the first 'op' field is utilized + target_columns[1][i] = op.y_hi; + target_columns[2][i] = op.z_1; + target_columns[3][i] = op.z_2; + i++; + } + } + } + + void populate_table_columns(TableView& target_columns) const + { + const size_t start_idx = 0; + const size_t end_idx = table.get().size(); + populate_column_data_from_subtables(target_columns, start_idx, end_idx); + } + + void populate_previous_table_columns(TableView& target_columns) const + { + const size_t start_idx = 1; + const size_t end_idx = table.get().size(); + populate_column_data_from_subtables(target_columns, start_idx, end_idx); + } + + void populate_current_subtable_columns(TableView& target_columns) const + { + const size_t start_idx = 0; + const size_t end_idx = 1; + populate_column_data_from_subtables(target_columns, start_idx, end_idx); + } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index ff8f002abc32..17d93d680a31 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -9,7 +9,9 @@ #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" #include "barretenberg/ultra_honk/merge_prover.hpp" +#include "barretenberg/ultra_honk/merge_prover_new.hpp" #include "barretenberg/ultra_honk/merge_verifier.hpp" +#include "barretenberg/ultra_honk/merge_verifier_new.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -29,6 +31,8 @@ template class MegaHonkTests : public ::testing::Test { using CommitmentKey = bb::CommitmentKey; using MergeProver = MergeProver_; using MergeVerifier = MergeVerifier_; + using MergeProverNew = MergeProverNew_; + using MergeVerifierNew = MergeVerifierNew_; using Prover = UltraProver_; using Verifier = UltraVerifier_; using VerificationKey = typename Flavor::VerificationKey; @@ -85,6 +89,20 @@ template class MegaHonkTests : public ::testing::Test { return verified; } + + /** + * @brief Construct and verify a Goblin ECC op queue merge proof + * + */ + bool construct_and_verify_merge_proof_new(auto& op_queue) + { + MergeProverNew merge_prover{ op_queue }; + MergeVerifierNew merge_verifier; + auto merge_proof = merge_prover.construct_proof(); + bool verified = merge_verifier.verify_proof(merge_proof); + + return verified; + } }; TYPED_TEST_SUITE(MegaHonkTests, FlavorTypes); @@ -253,6 +271,61 @@ TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly) } } +TYPED_TEST(MegaHonkTests, NewMergePolyconstruction) +{ + using Flavor = TypeParam; + using Fr = typename Flavor::Curve::ScalarField; + // Instantiate EccOpQueue. This will be shared across all circuits in the series + auto op_queue = std::make_shared(); + + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + + auto builder = typename Flavor::CircuitBuilder{ op_queue }; + GoblinMockCircuits::construct_simple_circuit(builder); + + const size_t expected_table_size = op_queue->get_ultra_ops_table_size(); + // op_queue->set_size_data(); + + // EXPECT_EQ(op_queue->get_current_size(), expected_table_size); + + std::array, 4> table_polynomials = op_queue->get_ultra_ops_table_columns(); + std::array, 4> previous_table_polynomials = op_queue->get_previous_ultra_ops_table_columns(); + std::array, 4> subtable_polynomials = op_queue->get_current_subtable_columns(); + + const size_t current_subtable_size = op_queue->get_current_ultra_ops_subtable_size(); + std::array, 4> reconstructed_table_polynomials; + for (size_t i = 0; i < 4; ++i) { + reconstructed_table_polynomials[i] = Polynomial(expected_table_size); + reconstructed_table_polynomials[i] += subtable_polynomials[i]; + reconstructed_table_polynomials[i] += previous_table_polynomials[i].right_shifted(current_subtable_size); + } + + for (auto [reconstructed, table] : zip_view(reconstructed_table_polynomials, table_polynomials)) { + EXPECT_EQ(reconstructed, table); + } + + Fr eval_challenge = Fr::random_element(); + + std::array table_evals; + std::array shifted_previous_table_evals; + std::array subtable_evals; + for (auto [eval, poly] : zip_view(table_evals, table_polynomials)) { + eval = poly.evaluate(eval_challenge); + } + for (auto [eval, poly] : zip_view(shifted_previous_table_evals, previous_table_polynomials)) { + eval = poly.evaluate(eval_challenge); + eval *= eval_challenge.pow(current_subtable_size); + } + for (auto [eval, poly] : zip_view(subtable_evals, subtable_polynomials)) { + eval = poly.evaluate(eval_challenge); + } + + for (auto [table_eval, shifted_previous_table_eval, subtable_eval] : + zip_view(table_evals, shifted_previous_table_evals, subtable_evals)) { + EXPECT_EQ(table_eval, subtable_eval + shifted_previous_table_eval); + } +} + /** * @brief Test Honk proof construction/verification for multiple circuits with ECC op gates, public inputs, and * basic arithmetic gates diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp new file mode 100644 index 000000000000..a12893e85aed --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp @@ -0,0 +1,130 @@ +#include "merge_prover_new.hpp" +#include "barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp" + +namespace bb { + +/** + * @brief Create MergeProver + * @details We require an SRS at least as large as the current op queue size in order to commit to the shifted + * per-circuit contribution t_i^{shift} + * + */ +template +MergeProverNew_::MergeProverNew_(const std::shared_ptr& op_queue, + std::shared_ptr commitment_key) + : op_queue(op_queue) +{ + // Update internal size data in the op queue that allows for extraction of e.g. previous aggregate transcript + op_queue->set_size_data(); + pcs_commitment_key = + commitment_key ? commitment_key : std::make_shared(op_queue->get_current_size()); +} + +/** + * @brief Prove proper construction of the aggregate Goblin ECC op queue polynomials T_i^(j), j = 1,2,3,4. + * @details Let T_i^(j) be the jth column of the aggregate op queue after incorporating the contribution from the + * present circuit. T_{i-1}^(j) corresponds to the aggregate op queue at the previous stage and $t_i^(j)$ represents + * the contribution from the present circuit only. For each j, we have the relationship T_i = T_{i-1} + right_shift(t_i, + * M_{i-1}), where the shift magnitude M_{i-1} is the honest length of T_{i-1}. This protocol demonstrates, assuming the + * length of T_{i-1} is at most M_{i-1}, that the aggregate op queue has been constructed correctly via a simple + * Schwartz-Zippel check. Evaluations are proven via batched KZG. + * + * TODO(#746): Prove connection between t_i^{shift}, committed to herein, and t_i, used in the main protocol. See issue + * for details (https://github.com/AztecProtocol/barretenberg/issues/746). + * + * @return honk::proof + */ +template HonkProof MergeProverNew_::construct_proof() +{ + transcript = std::make_shared(); + + size_t N = op_queue->get_current_size(); + + // Extract T_i, T_{i-1} + auto T_current = op_queue->get_aggregate_transcript(); + auto T_prev = op_queue->get_previous_aggregate_transcript(); + // TODO(#723): Cannot currently support an empty T_{i-1}. Need to be able to properly handle zero commitment. + ASSERT(T_prev[0].size() > 0); + ASSERT(T_current[0].size() > T_prev[0].size()); // Must have some new ops to accumulate otherwise C_t_shift = 0 + + // Construct t_i^{shift} as T_i - T_{i-1} + std::array t_shift; + for (size_t i = 0; i < NUM_WIRES; ++i) { + t_shift[i] = Polynomial(T_current[i]); + t_shift[i] -= { 0, T_prev[i] }; + } + + // Compute/get commitments [t_i^{shift}], [T_{i-1}], and [T_i] and add to transcript + std::array C_T_current; + for (size_t idx = 0; idx < t_shift.size(); ++idx) { + // Get previous transcript commitment [T_{i-1}] from op queue + const auto& C_T_prev = op_queue->get_ultra_ops_commitments()[idx]; + // Compute commitment [t_i^{shift}] directly + auto C_t_shift = pcs_commitment_key->commit(t_shift[idx]); + // Compute updated aggregate transcript commitment as [T_i] = [T_{i-1}] + [t_i^{shift}] + C_T_current[idx] = C_T_prev + C_t_shift; + + std::string suffix = std::to_string(idx + 1); + transcript->send_to_verifier("T_PREV_" + suffix, C_T_prev); + transcript->send_to_verifier("t_SHIFT_" + suffix, C_t_shift); + transcript->send_to_verifier("T_CURRENT_" + suffix, C_T_current[idx]); + } + + // Store the commitments [T_{i}] (to be used later in subsequent iterations as [T_{i-1}]). + op_queue->set_commitment_data(C_T_current); + + // Compute evaluations T_i(\kappa), T_{i-1}(\kappa), t_i^{shift}(\kappa), add to transcript. For each polynomial + // we add a univariate opening claim {p(X), (\kappa, p(\kappa))} to the set of claims to be checked via batched KZG. + FF kappa = transcript->template get_challenge("kappa"); + + // Add univariate opening claims for each polynomial. + std::vector opening_claims; + // Compute evaluation T_{i-1}(\kappa) + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + auto polynomial = Polynomial(T_prev[idx]); + auto evaluation = polynomial.evaluate(kappa); + transcript->send_to_verifier("T_prev_eval_" + std::to_string(idx + 1), evaluation); + opening_claims.emplace_back(OpeningClaim{ polynomial, { kappa, evaluation } }); + } + // Compute evaluation t_i^{shift}(\kappa) + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + auto evaluation = t_shift[idx].evaluate(kappa); + transcript->send_to_verifier("t_shift_eval_" + std::to_string(idx + 1), evaluation); + opening_claims.emplace_back(OpeningClaim{ t_shift[idx], { kappa, evaluation } }); + } + // Compute evaluation T_i(\kappa) + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + auto polynomial = Polynomial(T_current[idx]); + auto evaluation = polynomial.evaluate(kappa); + transcript->send_to_verifier("T_current_eval_" + std::to_string(idx + 1), evaluation); + opening_claims.emplace_back(OpeningClaim{ polynomial, { kappa, evaluation } }); + } + + FF alpha = transcript->template get_challenge("alpha"); + + // Construct batched polynomial to opened via KZG + auto batched_polynomial = Polynomial(N); + auto batched_eval = FF(0); + auto alpha_pow = FF(1); + for (auto& claim : opening_claims) { + batched_polynomial.add_scaled(claim.polynomial, alpha_pow); + batched_eval += alpha_pow * claim.opening_pair.evaluation; + alpha_pow *= alpha; + } + + // Construct and commit to KZG quotient polynomial q = (f - v) / (X - kappa) + auto quotient = batched_polynomial; + quotient.at(0) -= batched_eval; + quotient.factor_roots(kappa); + + auto quotient_commitment = pcs_commitment_key->commit(quotient); + transcript->send_to_verifier("KZG:W", quotient_commitment); + + return transcript->proof_data; +} + +template class MergeProverNew_; +template class MergeProverNew_; +template class MergeProverNew_; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.hpp new file mode 100644 index 000000000000..3467f908c451 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include "barretenberg/commitment_schemes/claim.hpp" +#include "barretenberg/honk/proof_system/types/proof.hpp" +#include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" +#include "barretenberg/transcript/transcript.hpp" + +namespace bb { + +/** + * @brief Prover class for the Goblin ECC op queue transcript merge protocol + * + */ +template class MergeProverNew_ { + using FF = typename Flavor::FF; + using Polynomial = typename Flavor::Polynomial; + using CommitmentKey = typename Flavor::CommitmentKey; + using Commitment = typename Flavor::Commitment; + using PCS = typename Flavor::PCS; + using Curve = typename Flavor::Curve; + using OpeningClaim = ProverOpeningClaim; + using OpeningPair = bb::OpeningPair; + using Transcript = NativeTranscript; + + public: + std::shared_ptr transcript; + + explicit MergeProverNew_(const std::shared_ptr& op_queue, + std::shared_ptr commitment_key = nullptr); + + BB_PROFILE HonkProof construct_proof(); + + private: + std::shared_ptr op_queue; + std::shared_ptr pcs_commitment_key; + static constexpr size_t NUM_WIRES = MegaFlavor::NUM_WIRES; +}; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp new file mode 100644 index 000000000000..c425a16afd68 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp @@ -0,0 +1,89 @@ +#include "merge_verifier_new.hpp" +#include "barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" + +namespace bb { + +template +MergeVerifierNew_::MergeVerifierNew_() + : transcript(std::make_shared()) + , pcs_verification_key(std::make_unique()){}; + +/** + * @brief Verify proper construction of the aggregate Goblin ECC op queue polynomials T_i^(j), j = 1,2,3,4. + * @details Let T_i^(j) be the jth column of the aggregate op queue after incorporating the contribution from the + * present circuit. T_{i-1}^(j) corresponds to the aggregate op queue at the previous stage and $t_i^(j)$ represents + * the contribution from the present circuit only. For each j, we have the relationship T_i = T_{i-1} + right_shift(t_i, + * M_{i-1}), where the shift magnitude M_{i-1} is the honest length of T_{i-1}. This protocol verfies, assuming the + * length of T_{i-1} is at most M_{i-1}, that the aggregate op queue has been constructed correctly via a simple + * Schwartz-Zippel check. Evaluations are checked via batched KZG. + * + * @tparam Flavor + * @return bool + */ +template bool MergeVerifierNew_::verify_proof(const HonkProof& proof) +{ + transcript = std::make_shared(proof); + + // Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i] + std::array C_T_prev; + std::array C_t_shift; + std::array C_T_current; + for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { + C_T_prev[idx] = transcript->template receive_from_prover("T_PREV_" + std::to_string(idx + 1)); + C_t_shift[idx] = transcript->template receive_from_prover("t_SHIFT_" + std::to_string(idx + 1)); + C_T_current[idx] = transcript->template receive_from_prover("T_CURRENT_" + std::to_string(idx + 1)); + } + + FF kappa = transcript->template get_challenge("kappa"); + + // Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]} + std::array T_prev_evals; + std::array t_shift_evals; + std::array T_current_evals; + std::vector opening_claims; + for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { + T_prev_evals[idx] = transcript->template receive_from_prover("T_prev_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, C_T_prev[idx] }); + } + for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { + t_shift_evals[idx] = transcript->template receive_from_prover("t_shift_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, t_shift_evals[idx] }, C_t_shift[idx] }); + } + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + T_current_evals[idx] = + transcript->template receive_from_prover("T_current_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, C_T_current[idx] }); + } + + // Check the identity T_i(\kappa) = T_{i-1}(\kappa) + t_i^{shift}(\kappa). If it fails, return false + bool identity_checked = true; + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + identity_checked = identity_checked && (T_current_evals[idx] == T_prev_evals[idx] + t_shift_evals[idx]); + } + + FF alpha = transcript->template get_challenge("alpha"); + + // Construct batched commitment and evaluation from constituents + auto batched_commitment = opening_claims[0].commitment; + auto batched_eval = opening_claims[0].opening_pair.evaluation; + auto alpha_pow = alpha; + for (size_t idx = 1; idx < opening_claims.size(); ++idx) { + auto& claim = opening_claims[idx]; + batched_commitment = batched_commitment + (claim.commitment * alpha_pow); + batched_eval += alpha_pow * claim.opening_pair.evaluation; + alpha_pow *= alpha; + } + + OpeningClaim batched_claim = { { kappa, batched_eval }, batched_commitment }; + + auto pairing_points = PCS::reduce_verify(batched_claim, transcript); + auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); + return identity_checked && verified; +} + +template class MergeVerifierNew_; +template class MergeVerifierNew_; +template class MergeVerifierNew_; + +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.hpp new file mode 100644 index 000000000000..4095bfe6d859 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.hpp @@ -0,0 +1,36 @@ +#pragma once + +#include "barretenberg/commitment_schemes/claim.hpp" +#include "barretenberg/honk/proof_system/types/proof.hpp" +#include "barretenberg/srs/global_crs.hpp" +#include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" +#include "barretenberg/transcript/transcript.hpp" + +namespace bb { + +/** + * @brief Verifier class for the Goblin ECC op queue transcript merge protocol + * + */ +template class MergeVerifierNew_ { + using Curve = typename Flavor::Curve; + using FF = typename Curve::ScalarField; + using Commitment = typename Curve::AffineElement; + using PCS = bb::KZG; + using OpeningClaim = bb::OpeningClaim; + using VerifierCommitmentKey = bb::VerifierCommitmentKey; + using Transcript = NativeTranscript; + + public: + std::shared_ptr transcript; + + explicit MergeVerifierNew_(); + bool verify_proof(const HonkProof& proof); + + private: + std::shared_ptr pcs_verification_key; + static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES; +}; + +} // namespace bb From b1d53af6e0d11a35e0e06b05d7eb614b8e25c7d0 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 17 Feb 2025 22:52:39 +0000 Subject: [PATCH 03/33] new prover and verifier, all consistent but doesnt verify --- .../src/barretenberg/goblin/mock_circuits.hpp | 1 + .../op_queue/ecc_op_queue.hpp | 2 +- .../ultra_honk/mega_honk.test.cpp | 18 +++ .../ultra_honk/merge_prover_new.cpp | 107 +++++++++--------- .../ultra_honk/merge_verifier_new.cpp | 67 +++++++---- 5 files changed, 115 insertions(+), 80 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index b63aaa9091dc..75f151c3262b 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -149,6 +149,7 @@ class GoblinMockCircuits { MockCircuits::construct_goblin_ecc_op_circuit(builder); op_queue->set_size_data(); + op_queue->initialize_new_subtable(); // WORKTODO: where to do this!? // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) #ifndef __wasm__ diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index 1526ccc28887..bdbb8d1ef917 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -162,7 +162,7 @@ class ECCOpQueue { { previous_ultra_ops_size = current_ultra_ops_size; current_ultra_ops_size = ultra_ops[0].size(); - initialize_new_subtable(); + // initialize_new_subtable(); } [[nodiscard]] size_t get_previous_size() const { return previous_ultra_ops_size; } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 17d93d680a31..78a9c19df9e1 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -271,6 +271,24 @@ TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly) } } +TYPED_TEST(MegaHonkTests, NewMultipleCircuitsMergeOnly) +{ + using Flavor = TypeParam; + // Instantiate EccOpQueue. This will be shared across all circuits in the series + auto op_queue = std::make_shared(); + + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + + // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. + auto builder = typename Flavor::CircuitBuilder{ op_queue }; + + GoblinMockCircuits::construct_simple_circuit(builder); + + // Construct and verify Goblin ECC op queue Merge proof + auto merge_verified = this->construct_and_verify_merge_proof_new(op_queue); + EXPECT_TRUE(merge_verified); +} + TYPED_TEST(MegaHonkTests, NewMergePolyconstruction) { using Flavor = TypeParam; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp index a12893e85aed..b75db3081efc 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp @@ -6,7 +6,7 @@ namespace bb { /** * @brief Create MergeProver * @details We require an SRS at least as large as the current op queue size in order to commit to the shifted - * per-circuit contribution t_i^{shift} + * per-circuit contribution t^{shift} * */ template @@ -21,15 +21,15 @@ MergeProverNew_::MergeProverNew_(const std::shared_ptr& op_q } /** - * @brief Prove proper construction of the aggregate Goblin ECC op queue polynomials T_i^(j), j = 1,2,3,4. - * @details Let T_i^(j) be the jth column of the aggregate op queue after incorporating the contribution from the - * present circuit. T_{i-1}^(j) corresponds to the aggregate op queue at the previous stage and $t_i^(j)$ represents - * the contribution from the present circuit only. For each j, we have the relationship T_i = T_{i-1} + right_shift(t_i, - * M_{i-1}), where the shift magnitude M_{i-1} is the honest length of T_{i-1}. This protocol demonstrates, assuming the - * length of T_{i-1} is at most M_{i-1}, that the aggregate op queue has been constructed correctly via a simple + * @brief Prove proper construction of the aggregate Goblin ECC op queue polynomials T^(j), j = 1,2,3,4. + * @details Let T^(j) be the jth column of the aggregate op queue after incorporating the contribution from the + * present circuit. T_prev^(j) corresponds to the aggregate op queue at the previous stage and $t^(j)$ represents + * the contribution from the present circuit only. For each j, we have the relationship T = T_prev + right_shift(t, + * M_{i-1}), where the shift magnitude M_{i-1} is the honest length of T_prev. This protocol demonstrates, assuming the + * length of T_prev is at most M_{i-1}, that the aggregate op queue has been constructed correctly via a simple * Schwartz-Zippel check. Evaluations are proven via batched KZG. * - * TODO(#746): Prove connection between t_i^{shift}, committed to herein, and t_i, used in the main protocol. See issue + * TODO(#746): Prove connection between t^{shift}, committed to herein, and t, used in the main protocol. See issue * for details (https://github.com/AztecProtocol/barretenberg/issues/746). * * @return honk::proof @@ -38,80 +38,79 @@ template HonkProof MergeProverNew_::construct_proof() { transcript = std::make_shared(); - size_t N = op_queue->get_current_size(); + // Extract T, T_prev, t + std::array T_current = op_queue->get_ultra_ops_table_columns(); + std::array T_prev = op_queue->get_previous_ultra_ops_table_columns(); + std::array t_current = op_queue->get_current_subtable_columns(); - // Extract T_i, T_{i-1} - auto T_current = op_queue->get_aggregate_transcript(); - auto T_prev = op_queue->get_previous_aggregate_transcript(); - // TODO(#723): Cannot currently support an empty T_{i-1}. Need to be able to properly handle zero commitment. + // TODO(#723): Cannot currently support an empty T_prev. Need to be able to properly handle zero commitment. ASSERT(T_prev[0].size() > 0); ASSERT(T_current[0].size() > T_prev[0].size()); // Must have some new ops to accumulate otherwise C_t_shift = 0 - // Construct t_i^{shift} as T_i - T_{i-1} - std::array t_shift; - for (size_t i = 0; i < NUM_WIRES; ++i) { - t_shift[i] = Polynomial(T_current[i]); - t_shift[i] -= { 0, T_prev[i] }; - } + const size_t current_table_size = T_current[0].size(); + const size_t current_subtable_size = t_current[0].size(); + + transcript->send_to_verifier("subtable_size", current_subtable_size); + info("subtable_size: ", current_subtable_size); + + // Compute/get commitments [t^{shift}], [T_prev], and [T] and add to transcript + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + // Compute commitments + Commitment C_t_current = pcs_commitment_key->commit(t_current[idx]); + Commitment C_T_prev = pcs_commitment_key->commit(T_prev[idx]); + Commitment C_T_current = pcs_commitment_key->commit(T_current[idx]); - // Compute/get commitments [t_i^{shift}], [T_{i-1}], and [T_i] and add to transcript - std::array C_T_current; - for (size_t idx = 0; idx < t_shift.size(); ++idx) { - // Get previous transcript commitment [T_{i-1}] from op queue - const auto& C_T_prev = op_queue->get_ultra_ops_commitments()[idx]; - // Compute commitment [t_i^{shift}] directly - auto C_t_shift = pcs_commitment_key->commit(t_shift[idx]); - // Compute updated aggregate transcript commitment as [T_i] = [T_{i-1}] + [t_i^{shift}] - C_T_current[idx] = C_T_prev + C_t_shift; - - std::string suffix = std::to_string(idx + 1); + std::string suffix = std::to_string(idx); + transcript->send_to_verifier("t_CURRENT_" + suffix, C_t_current); transcript->send_to_verifier("T_PREV_" + suffix, C_T_prev); - transcript->send_to_verifier("t_SHIFT_" + suffix, C_t_shift); - transcript->send_to_verifier("T_CURRENT_" + suffix, C_T_current[idx]); + transcript->send_to_verifier("T_CURRENT_" + suffix, C_T_current); } - // Store the commitments [T_{i}] (to be used later in subsequent iterations as [T_{i-1}]). - op_queue->set_commitment_data(C_T_current); - - // Compute evaluations T_i(\kappa), T_{i-1}(\kappa), t_i^{shift}(\kappa), add to transcript. For each polynomial - // we add a univariate opening claim {p(X), (\kappa, p(\kappa))} to the set of claims to be checked via batched KZG. + // Compute evaluations T(\kappa), T_prev_shift(\kappa), t(\kappa), add to transcript. For each polynomial we add a + // univariate opening claim {p(X), (\kappa, p(\kappa))} to the set of claims to be checked via batched KZG. FF kappa = transcript->template get_challenge("kappa"); + info("kappa: ", kappa); // Add univariate opening claims for each polynomial. std::vector opening_claims; - // Compute evaluation T_{i-1}(\kappa) + // Compute evaluation t(\kappa) for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - auto polynomial = Polynomial(T_prev[idx]); - auto evaluation = polynomial.evaluate(kappa); - transcript->send_to_verifier("T_prev_eval_" + std::to_string(idx + 1), evaluation); - opening_claims.emplace_back(OpeningClaim{ polynomial, { kappa, evaluation } }); + FF evaluation = t_current[idx].evaluate(kappa); + transcript->send_to_verifier("t_eval_" + std::to_string(idx), evaluation); + opening_claims.emplace_back(OpeningClaim{ std::move(t_current[idx]), { kappa, evaluation } }); } - // Compute evaluation t_i^{shift}(\kappa) + // Compute evaluation T_prev(\kappa) for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - auto evaluation = t_shift[idx].evaluate(kappa); - transcript->send_to_verifier("t_shift_eval_" + std::to_string(idx + 1), evaluation); - opening_claims.emplace_back(OpeningClaim{ t_shift[idx], { kappa, evaluation } }); + FF evaluation = T_prev[idx].evaluate(kappa); + evaluation *= kappa.pow(current_subtable_size); // \kappa^{m_i}*T_prev(\kappa) + transcript->send_to_verifier("T_prev_shift_eval_" + std::to_string(idx), evaluation); + opening_claims.emplace_back( + OpeningClaim{ T_prev[idx].right_shifted(current_subtable_size), { kappa, evaluation } }); } - // Compute evaluation T_i(\kappa) + // Compute evaluation T(\kappa) for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - auto polynomial = Polynomial(T_current[idx]); - auto evaluation = polynomial.evaluate(kappa); - transcript->send_to_verifier("T_current_eval_" + std::to_string(idx + 1), evaluation); - opening_claims.emplace_back(OpeningClaim{ polynomial, { kappa, evaluation } }); + FF evaluation = T_current[idx].evaluate(kappa); + transcript->send_to_verifier("T_eval_" + std::to_string(idx), evaluation); + opening_claims.emplace_back(OpeningClaim{ std::move(T_current[idx]), { kappa, evaluation } }); } FF alpha = transcript->template get_challenge("alpha"); + info("alpha: ", alpha); // Construct batched polynomial to opened via KZG - auto batched_polynomial = Polynomial(N); - auto batched_eval = FF(0); - auto alpha_pow = FF(1); + Polynomial batched_polynomial(current_table_size); + FF batched_eval(0); + FF alpha_pow(1); for (auto& claim : opening_claims) { batched_polynomial.add_scaled(claim.polynomial, alpha_pow); batched_eval += alpha_pow * claim.opening_pair.evaluation; alpha_pow *= alpha; } + info("Prover: batched_eval: ", batched_eval); + info("reconstructed batched_eval: ", batched_polynomial.evaluate(kappa)); + info("batched_commitment: ", pcs_commitment_key->commit(batched_polynomial)); + // Construct and commit to KZG quotient polynomial q = (f - v) / (X - kappa) auto quotient = batched_polynomial; quotient.at(0) -= batched_eval; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp index c425a16afd68..2c9154d50a73 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp @@ -25,58 +25,75 @@ template bool MergeVerifierNew_::verify_proof(const Ho { transcript = std::make_shared(proof); + uint32_t subtable_size = transcript->template receive_from_prover("subtable_size"); + info("subtable_size: ", subtable_size); + // Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i] - std::array C_T_prev; - std::array C_t_shift; - std::array C_T_current; + std::array t_commitments; + std::array T_prev_commitments; + std::array T_commitments; for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - C_T_prev[idx] = transcript->template receive_from_prover("T_PREV_" + std::to_string(idx + 1)); - C_t_shift[idx] = transcript->template receive_from_prover("t_SHIFT_" + std::to_string(idx + 1)); - C_T_current[idx] = transcript->template receive_from_prover("T_CURRENT_" + std::to_string(idx + 1)); + std::string suffix = std::to_string(idx); + t_commitments[idx] = transcript->template receive_from_prover("t_CURRENT_" + suffix); + T_prev_commitments[idx] = transcript->template receive_from_prover("T_PREV_" + suffix); + T_commitments[idx] = transcript->template receive_from_prover("T_CURRENT_" + suffix); } FF kappa = transcript->template get_challenge("kappa"); + info("kappa: ", kappa); // Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]} - std::array T_prev_evals; - std::array t_shift_evals; - std::array T_current_evals; - std::vector opening_claims; + std::array t_evals; + std::array T_prev_shift_evals; + std::array T_evals; for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - T_prev_evals[idx] = transcript->template receive_from_prover("T_prev_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, C_T_prev[idx] }); + t_evals[idx] = transcript->template receive_from_prover("t_eval_" + std::to_string(idx)); } for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - t_shift_evals[idx] = transcript->template receive_from_prover("t_shift_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, t_shift_evals[idx] }, C_t_shift[idx] }); + T_prev_shift_evals[idx] = + transcript->template receive_from_prover("T_prev_shift_eval_" + std::to_string(idx)); } for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - T_current_evals[idx] = - transcript->template receive_from_prover("T_current_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, C_T_current[idx] }); + T_evals[idx] = transcript->template receive_from_prover("T_eval_" + std::to_string(idx)); } - // Check the identity T_i(\kappa) = T_{i-1}(\kappa) + t_i^{shift}(\kappa). If it fails, return false + // Check the identity T(\kappa) = t(\kappa) + T_prev_shift(\kappa). If it fails, return false bool identity_checked = true; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - identity_checked = identity_checked && (T_current_evals[idx] == T_prev_evals[idx] + t_shift_evals[idx]); + bool current_check = T_evals[idx] == t_evals[idx] + T_prev_shift_evals[idx]; + info("current_check: ", current_check); + identity_checked = identity_checked && current_check; } FF alpha = transcript->template get_challenge("alpha"); + info("alpha: ", alpha); // Construct batched commitment and evaluation from constituents - auto batched_commitment = opening_claims[0].commitment; - auto batched_eval = opening_claims[0].opening_pair.evaluation; + Commitment batched_commitment = t_commitments[0]; + FF batched_eval = t_evals[0]; auto alpha_pow = alpha; - for (size_t idx = 1; idx < opening_claims.size(); ++idx) { - auto& claim = opening_claims[idx]; - batched_commitment = batched_commitment + (claim.commitment * alpha_pow); - batched_eval += alpha_pow * claim.opening_pair.evaluation; + for (size_t idx = 1; idx < NUM_WIRES; ++idx) { + batched_commitment = batched_commitment + (t_commitments[idx] * alpha_pow); + batched_eval += alpha_pow * t_evals[idx]; + alpha_pow *= alpha; + } + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + FF commitment_scalar = alpha_pow * kappa.pow(subtable_size); + batched_commitment = batched_commitment + (T_prev_commitments[idx] * commitment_scalar); + batched_eval += alpha_pow * T_prev_shift_evals[idx]; + alpha_pow *= alpha; + } + for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + batched_commitment = batched_commitment + (T_commitments[idx] * alpha_pow); + batched_eval += alpha_pow * T_evals[idx]; alpha_pow *= alpha; } OpeningClaim batched_claim = { { kappa, batched_eval }, batched_commitment }; + info("Verifier: batched_eval: ", batched_eval); + info("batched_commitment: ", batched_commitment); + auto pairing_points = PCS::reduce_verify(batched_claim, transcript); auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); return identity_checked && verified; From 8eaeb4a85d875bf2e46b8d76741ea587ebea8859 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 18 Feb 2025 17:29:34 +0000 Subject: [PATCH 04/33] possibly unuseful kzg test.. --- .../commitment_schemes/kzg/kzg.test.cpp | 30 ++++++++++++++++++- .../ultra_honk/merge_prover_new.cpp | 5 ++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 5bac7124bcd4..f62926e12cc4 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -59,6 +59,34 @@ TEST_F(KZGTest, single) EXPECT_EQ(vk->pairing_check(pairing_points[0], pairing_points[1]), true); } +TEST_F(KZGTest, OpenShiftViaUnshiftedCommitment) +{ + // Construct a polynomial that is right shiftable by shift_magnitude + const size_t shift_magnitude = 4; + // const size_t shift_magnitude = 0; + auto witness = bb::Polynomial::random(n - shift_magnitude, n, 0); + bb::Polynomial witness_shifted(n); + witness_shifted += witness.right_shifted(shift_magnitude); + + // Commit to the unshifted polynomial + const Commitment commitment = ck->commit(witness); + + // Compute the shifted evaluation + const Fr challenge = Fr::random_element(); + const Fr unshifted_evaluation = witness.evaluate(challenge); + const Fr shifted_evaluation = unshifted_evaluation * challenge.pow(shift_magnitude); + + auto prover_transcript = NativeTranscript::prover_init_empty(); + PCS::compute_opening_proof(ck, { witness, { challenge, unshifted_evaluation } }, prover_transcript); + + Fr unshifted_eval_reconstructed = shifted_evaluation * (challenge.pow(shift_magnitude)).invert(); + auto opening_claim = OpeningClaim{ { challenge, unshifted_eval_reconstructed }, commitment }; + auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); + const auto pairing_points = PCS::reduce_verify(opening_claim, verifier_transcript); + + EXPECT_EQ(vk->pairing_check(pairing_points[0], pairing_points[1]), true); +} + /** * @brief Test opening proof of a polynomial given by its evaluations at \f$ i = 0, \ldots, n \f$. Should only be used * for small values of \f$ n \f$. @@ -330,4 +358,4 @@ TEST_F(KZGTest, ShpleminiKzgShiftsRemoval) } // namespace bb std::shared_ptr bb::KZGTest::ck = nullptr; -std::shared_ptr bb::KZGTest::vk = nullptr; \ No newline at end of file +std::shared_ptr bb::KZGTest::vk = nullptr; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp index b75db3081efc..0c61654b2d3b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp @@ -71,6 +71,11 @@ template HonkProof MergeProverNew_::construct_proof() FF kappa = transcript->template get_challenge("kappa"); info("kappa: ", kappa); + // WORKTODO: what I actually need to do is send claims for both [T_prev_shift] and [T_prev] then check that + // T_prev_shift(\gamma) = \gamma^{m_i}T_prev(\gamma). Otherwise I think I need Shplonk to open the shift from the + // unshifted. Interestingly the verifier can compute [T_prev_shift] as [T] - [t]. Is that useful at all? Probably + // not, unless this somehow makes the batch opening contain fewer commitments. + // Add univariate opening claims for each polynomial. std::vector opening_claims; // Compute evaluation t(\kappa) From 1445fa5e3e90393b46db13b81513b44f7730ac1d Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 18 Feb 2025 17:46:55 +0000 Subject: [PATCH 05/33] open unsihfted; prove shift via identity on evals; test passes --- .../barretenberg/ultra_honk/merge_prover_new.cpp | 11 ++--------- .../barretenberg/ultra_honk/merge_verifier_new.cpp | 14 ++++++-------- 2 files changed, 8 insertions(+), 17 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp index 0c61654b2d3b..814cd656e736 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp @@ -71,11 +71,6 @@ template HonkProof MergeProverNew_::construct_proof() FF kappa = transcript->template get_challenge("kappa"); info("kappa: ", kappa); - // WORKTODO: what I actually need to do is send claims for both [T_prev_shift] and [T_prev] then check that - // T_prev_shift(\gamma) = \gamma^{m_i}T_prev(\gamma). Otherwise I think I need Shplonk to open the shift from the - // unshifted. Interestingly the verifier can compute [T_prev_shift] as [T] - [t]. Is that useful at all? Probably - // not, unless this somehow makes the batch opening contain fewer commitments. - // Add univariate opening claims for each polynomial. std::vector opening_claims; // Compute evaluation t(\kappa) @@ -87,10 +82,8 @@ template HonkProof MergeProverNew_::construct_proof() // Compute evaluation T_prev(\kappa) for (size_t idx = 0; idx < NUM_WIRES; ++idx) { FF evaluation = T_prev[idx].evaluate(kappa); - evaluation *= kappa.pow(current_subtable_size); // \kappa^{m_i}*T_prev(\kappa) - transcript->send_to_verifier("T_prev_shift_eval_" + std::to_string(idx), evaluation); - opening_claims.emplace_back( - OpeningClaim{ T_prev[idx].right_shifted(current_subtable_size), { kappa, evaluation } }); + transcript->send_to_verifier("T_prev_eval_" + std::to_string(idx), evaluation); + opening_claims.emplace_back(OpeningClaim{ T_prev[idx], { kappa, evaluation } }); } // Compute evaluation T(\kappa) for (size_t idx = 0; idx < NUM_WIRES; ++idx) { diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp index 2c9154d50a73..e1892c6082d3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp @@ -44,23 +44,22 @@ template bool MergeVerifierNew_::verify_proof(const Ho // Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]} std::array t_evals; - std::array T_prev_shift_evals; + std::array T_prev_evals; std::array T_evals; for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { t_evals[idx] = transcript->template receive_from_prover("t_eval_" + std::to_string(idx)); } for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - T_prev_shift_evals[idx] = - transcript->template receive_from_prover("T_prev_shift_eval_" + std::to_string(idx)); + T_prev_evals[idx] = transcript->template receive_from_prover("T_prev_eval_" + std::to_string(idx)); } for (size_t idx = 0; idx < NUM_WIRES; ++idx) { T_evals[idx] = transcript->template receive_from_prover("T_eval_" + std::to_string(idx)); } - // Check the identity T(\kappa) = t(\kappa) + T_prev_shift(\kappa). If it fails, return false + // Check the identity T(\kappa) = t(\kappa) + \kappa^m*T_prev_(\kappa). If it fails, return false bool identity_checked = true; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - bool current_check = T_evals[idx] == t_evals[idx] + T_prev_shift_evals[idx]; + bool current_check = T_evals[idx] == t_evals[idx] + T_prev_evals[idx] * kappa.pow(subtable_size); info("current_check: ", current_check); identity_checked = identity_checked && current_check; } @@ -78,9 +77,8 @@ template bool MergeVerifierNew_::verify_proof(const Ho alpha_pow *= alpha; } for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - FF commitment_scalar = alpha_pow * kappa.pow(subtable_size); - batched_commitment = batched_commitment + (T_prev_commitments[idx] * commitment_scalar); - batched_eval += alpha_pow * T_prev_shift_evals[idx]; + batched_commitment = batched_commitment + (T_prev_commitments[idx] * alpha_pow); + batched_eval += alpha_pow * T_prev_evals[idx]; alpha_pow *= alpha; } for (size_t idx = 0; idx < NUM_WIRES; ++idx) { From 428a3d40415b6462aa511301d97c2964fcab1850 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 18 Feb 2025 18:07:51 +0000 Subject: [PATCH 06/33] update rec merge verifier; test passes --- .../merge_recursive_verifier.cpp | 29 ++++++++++--------- .../goblin_verifier/merge_verifier.test.cpp | 10 +++---- .../ultra_honk/merge_verifier_new.cpp | 5 ++-- 3 files changed, 24 insertions(+), 20 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp index 6f3ea52555cf..f374a2ba9733 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp @@ -22,40 +22,43 @@ std::array::Element, 2> MergeRecursiveVerifier_ stdlib_proof = bb::convert_native_proof_to_stdlib(builder, proof); transcript = std::make_shared(stdlib_proof); - // Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i] + FF subtable_size = transcript->template receive_from_prover("subtable_size"); + + // Receive commitments [t], [T_prev], and [T] + std::array C_t; std::array C_T_prev; - std::array C_t_shift; - std::array C_T_current; + std::array C_T; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { + C_t[idx] = transcript->template receive_from_prover("t_CURRENT_" + std::to_string(idx + 1)); C_T_prev[idx] = transcript->template receive_from_prover("T_PREV_" + std::to_string(idx + 1)); - C_t_shift[idx] = transcript->template receive_from_prover("t_SHIFT_" + std::to_string(idx + 1)); - C_T_current[idx] = transcript->template receive_from_prover("T_CURRENT_" + std::to_string(idx + 1)); + C_T[idx] = transcript->template receive_from_prover("T_CURRENT_" + std::to_string(idx + 1)); } FF kappa = transcript->template get_challenge("kappa"); // Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]} + std::array t_evals; std::array T_prev_evals; - std::array t_shift_evals; std::array T_current_evals; std::vector opening_claims; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - T_prev_evals[idx] = transcript->template receive_from_prover("T_prev_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, C_T_prev[idx] }); + t_evals[idx] = transcript->template receive_from_prover("t_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, t_evals[idx] }, C_t[idx] }); } for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - t_shift_evals[idx] = transcript->template receive_from_prover("t_shift_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, t_shift_evals[idx] }, C_t_shift[idx] }); + T_prev_evals[idx] = transcript->template receive_from_prover("T_prev_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, C_T_prev[idx] }); } for (size_t idx = 0; idx < NUM_WIRES; ++idx) { T_current_evals[idx] = transcript->template receive_from_prover("T_current_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, C_T_current[idx] }); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, C_T[idx] }); } - // Check the identity T_i(\kappa) = T_{i-1}(\kappa) + t_i^{shift}(\kappa) + // Check the identity T(\kappa) = t(\kappa) + \kappa^m * T_prev(\kappa) for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - T_current_evals[idx].assert_equal(T_prev_evals[idx] + t_shift_evals[idx]); + FF T_prev_shifted_eval_reconstructed = T_prev_evals[idx] * kappa.pow(subtable_size); + T_current_evals[idx].assert_equal(t_evals[idx] + T_prev_shifted_eval_reconstructed); } FF alpha = transcript->template get_challenge("alpha"); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_verifier.test.cpp index a7887a9c96e0..4a8d34d90414 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_verifier.test.cpp @@ -1,10 +1,10 @@ -#include "barretenberg/ultra_honk/merge_verifier.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/common/test.hpp" #include "barretenberg/goblin/mock_circuits.hpp" #include "barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" -#include "barretenberg/ultra_honk/merge_prover.hpp" +#include "barretenberg/ultra_honk/merge_prover_new.hpp" +#include "barretenberg/ultra_honk/merge_verifier_new.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -31,8 +31,8 @@ template class RecursiveMergeVerifierTest : public test using Commitment = InnerFlavor::Commitment; using FF = InnerFlavor::FF; using VerifierCommitmentKey = bb::VerifierCommitmentKey; - using MergeProver = MergeProver_; - using MergeVerifier = MergeVerifier_; + using MergeProver = MergeProverNew_; + using MergeVerifier = MergeVerifierNew_; public: static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } @@ -99,4 +99,4 @@ TYPED_TEST(RecursiveMergeVerifierTest, SingleRecursiveVerification) TestFixture::test_recursive_merge_verification(); }; -} // namespace bb::stdlib::recursion::goblin \ No newline at end of file +} // namespace bb::stdlib::recursion::goblin diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp index e1892c6082d3..4712a69fe13b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp @@ -56,10 +56,11 @@ template bool MergeVerifierNew_::verify_proof(const Ho T_evals[idx] = transcript->template receive_from_prover("T_eval_" + std::to_string(idx)); } - // Check the identity T(\kappa) = t(\kappa) + \kappa^m*T_prev_(\kappa). If it fails, return false + // Check the identity T(\kappa) = t(\kappa) + \kappa^m * T_prev_(\kappa). If it fails, return false bool identity_checked = true; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - bool current_check = T_evals[idx] == t_evals[idx] + T_prev_evals[idx] * kappa.pow(subtable_size); + FF T_prev_shifted_eval_reconstructed = T_prev_evals[idx] * kappa.pow(subtable_size); + bool current_check = T_evals[idx] == t_evals[idx] + T_prev_shifted_eval_reconstructed; info("current_check: ", current_check); identity_checked = identity_checked && current_check; } From 6dccae5d16fbe1b73a7d1d4a681925eae16beaf4 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 18 Feb 2025 18:34:10 +0000 Subject: [PATCH 07/33] add an inefficient copy based reconstruction method for ecc op table --- .../op_queue/ecc_ops_table.hpp | 15 ++++++++++++++- .../op_queue/ecc_ops_table.test.cpp | 5 ++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index 0ec52d748063..e538ba2cc7fd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -49,7 +49,7 @@ template class EccOpsTable { void create_new_subtable(size_t size_hint = 0) { - std::vector new_subtable; + Subtable new_subtable; new_subtable.reserve(size_hint); table.insert(table.begin(), std::move(new_subtable)); } @@ -67,6 +67,19 @@ template class EccOpsTable { } return table.front().front(); // should never reach here } + + // highly inefficient copy-based reconstruction of the table for use in ECCVM/Translator + std::vector get_reconstructed() const + { + std::vector reconstructed_table; + reconstructed_table.reserve(size()); + for (const auto& subtable : table) { + for (const auto& op : subtable) { + reconstructed_table.push_back(op); + } + } + return reconstructed_table; + } }; using RawEccOpsTable = EccOpsTable>; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp index b8ccfe4c77bf..f3257d1bee07 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp @@ -165,8 +165,11 @@ TEST(EccOpsTableTest, RawOpsTable) auto expected_num_ops = std::accumulate(subtable_op_counts.begin(), subtable_op_counts.end(), size_t(0)); EXPECT_EQ(raw_ops_table.size(), expected_num_ops); - // Check that the table matches the manually constructed mock table + // Check that accessing the table values via operator[] matches the manually constructed mock table for (size_t i = 0; i < expected_num_ops; ++i) { EXPECT_EQ(expected_raw_ops_table.raw_ops[i], raw_ops_table[i]); } + + // Check that the copy-based reconstruction of the raw ops table matches the expected table + EXPECT_EQ(expected_raw_ops_table.raw_ops, raw_ops_table.get_reconstructed()); } From a13b40f603b50f58557c308f8fa8fa9b372e9163 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 18 Feb 2025 19:40:41 +0000 Subject: [PATCH 08/33] use new merge classes everywhere; things seem to be working --- .../eccvm/eccvm_circuit_builder.hpp | 2 +- .../cpp/src/barretenberg/goblin/goblin.hpp | 10 +- .../src/barretenberg/goblin/mock_circuits.hpp | 1 - .../mega_circuit_builder.hpp | 2 + .../op_queue/ecc_op_queue.hpp | 4 +- .../op_queue/ecc_op_queue.test.cpp | 2 +- .../translator_circuit_builder.cpp | 4 +- .../translator_circuit_builder.fuzzer.cpp | 4 +- .../translator_circuit_builder.test.cpp | 4 +- .../ultra_honk/mega_honk.test.cpp | 4 +- .../ultra_vanilla_client_ivc.test.cpp | 156 +++++++++--------- 11 files changed, 96 insertions(+), 97 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp index 7d472685f165..fcfadd09d8cf 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp @@ -113,7 +113,7 @@ class ECCVMCircuitBuilder { std::vector> msm_mul_index; std::vector msm_sizes; - const auto& raw_ops = op_queue->get_raw_ops(); + const auto raw_ops = op_queue->get_raw_ops(); size_t op_idx = 0; // populate opqueue and mul indices for (const auto& op : raw_ops) { diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 872b168f9605..df050006eaa2 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -14,8 +14,8 @@ #include "barretenberg/translator_vm/translator_circuit_builder.hpp" #include "barretenberg/translator_vm/translator_prover.hpp" #include "barretenberg/translator_vm/translator_verifier.hpp" -#include "barretenberg/ultra_honk/merge_prover.hpp" -#include "barretenberg/ultra_honk/merge_verifier.hpp" +#include "barretenberg/ultra_honk/merge_prover_new.hpp" +#include "barretenberg/ultra_honk/merge_verifier_new.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -37,7 +37,7 @@ class GoblinProver { using TranslatorBuilder = TranslatorCircuitBuilder; using RecursiveMergeVerifier = stdlib::recursion::goblin::MergeRecursiveVerifier_; using PairingPoints = RecursiveMergeVerifier::PairingPoints; - using MergeProver = MergeProver_; + using MergeProver = MergeProverNew_; using VerificationKey = MegaFlavor::VerificationKey; using MergeProof = std::vector; /** @@ -256,7 +256,7 @@ class GoblinVerifier { public: using ECCVMVerificationKey = ECCVMFlavor::VerificationKey; using TranslatorVerificationKey = bb::TranslatorFlavor::VerificationKey; - using MergeVerifier = bb::MergeVerifier_; + using MergeVerifier = bb::MergeVerifierNew_; struct VerifierInput { std::shared_ptr eccvm_verification_key; @@ -309,4 +309,4 @@ class GoblinVerifier { return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified; }; }; -} // namespace bb \ No newline at end of file +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 75f151c3262b..b63aaa9091dc 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -149,7 +149,6 @@ class GoblinMockCircuits { MockCircuits::construct_goblin_ecc_op_circuit(builder); op_queue->set_size_data(); - op_queue->initialize_new_subtable(); // WORKTODO: where to do this!? // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) #ifndef __wasm__ diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp index d796755d46a8..6e4ec2fd6cc9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp @@ -50,6 +50,8 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_initialize_new_subtable(); // Set indices to constants corresponding to Goblin ECC op codes set_goblin_ecc_op_code_constant_variables(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index bdbb8d1ef917..55ffe6052086 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -45,8 +45,6 @@ class ECCOpQueue { public: using ECCVMOperation = bb::eccvm::VMOperation; - ECCOpQueue() { initialize_new_subtable(); } - void initialize_new_subtable() { raw_ops_table.create_new_subtable(); @@ -97,7 +95,7 @@ class ECCOpQueue { size_t get_ultra_ops_table_size() const { return ultra_ops_table.ultra_table_size(); } size_t get_current_ultra_ops_subtable_size() const { return ultra_ops_table.current_ultra_subtable_size(); } - const std::vector& get_raw_ops() { return raw_ops; } + std::vector get_raw_ops() { return raw_ops_table.get_reconstructed(); } /** * @brief Get the number of rows in the 'msm' column section, for all msms in the circuit diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index a0d2596da286..9d88be6397fb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -6,7 +6,7 @@ using namespace bb; TEST(ECCOpQueueTest, Basic) { ECCOpQueue op_queue; - const auto& raw_ops = op_queue.get_raw_ops(); + const auto raw_ops = op_queue.get_raw_ops(); op_queue.add_accumulate(bb::g1::affine_one); EXPECT_EQ(raw_ops[0].base_point, bb::g1::affine_one); op_queue.empty_row_for_testing(); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index 6ef938873192..ee5516a38f3d 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -591,7 +591,7 @@ TranslatorCircuitBuilder::AccumulationInput TranslatorCircuitBuilder::compute_wi void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ptr ecc_op_queue) { using Fq = bb::fq; - const auto& raw_ops = ecc_op_queue->get_raw_ops(); + const auto raw_ops = ecc_op_queue->get_raw_ops(); std::vector accumulator_trace; Fq current_accumulator(0); if (raw_ops.empty()) { @@ -1055,4 +1055,4 @@ bool TranslatorCircuitBuilder::check_circuit() } return true; }; -} // namespace bb \ No newline at end of file +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp index aac38c9b9caf..864221003f14 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp @@ -23,7 +23,7 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) auto z_1_accumulator = Fq(0); auto z_2_accumulator = Fq(0); // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - const auto& raw_ops = op_queue->get_raw_ops(); + const auto raw_ops = op_queue->get_raw_ops(); for (const auto& ecc_op : raw_ops) { op_accumulator = op_accumulator * x_inv + ecc_op.get_opcode_value(); p_x_accumulator = p_x_accumulator * x_inv + ecc_op.base_point.x; @@ -45,4 +45,4 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) circuit_builder.check_circuit(); (void)result; return 0; -} \ No newline at end of file +} diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 95492d1acc0f..f78c12e1e435 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -105,7 +105,7 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) // Get an inverse Fq x_inv = x.invert(); // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - const auto& raw_ops = op_queue->get_raw_ops(); + const auto raw_ops = op_queue->get_raw_ops(); for (const auto& ecc_op : raw_ops) { op_accumulator = op_accumulator * x_inv + ecc_op.get_opcode_value(); const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); @@ -130,4 +130,4 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) EXPECT_TRUE(circuit_builder.check_circuit()); // Check the computation result is in line with what we've computed EXPECT_EQ(result, circuit_builder.get_computation_result()); -} \ No newline at end of file +} diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 78a9c19df9e1..10d60c169000 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -29,8 +29,8 @@ template class MegaHonkTests : public ::testing::Test { using FF = Curve::ScalarField; using Point = Curve::AffineElement; using CommitmentKey = bb::CommitmentKey; - using MergeProver = MergeProver_; - using MergeVerifier = MergeVerifier_; + using MergeProver = MergeProverNew_; + using MergeVerifier = MergeVerifierNew_; using MergeProverNew = MergeProverNew_; using MergeVerifierNew = MergeVerifierNew_; using Prover = UltraProver_; diff --git a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp index 653b7d8f6414..5c06e548cd0f 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp @@ -1,93 +1,93 @@ -#include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp" -#include "barretenberg/goblin/goblin.hpp" -#include "barretenberg/goblin/mock_circuits.hpp" -#include "barretenberg/protogalaxy/folding_test_utils.hpp" -#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include +// #include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp" +// #include "barretenberg/goblin/goblin.hpp" +// #include "barretenberg/goblin/mock_circuits.hpp" +// #include "barretenberg/protogalaxy/folding_test_utils.hpp" +// #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" +// #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +// #include -using namespace bb; +// using namespace bb; -class UltraVanillaClientIVCTests : public ::testing::Test { - protected: - static void SetUpTestSuite() - { - srs::init_crs_factory("../srs_db/ignition"); - srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); - } +// class UltraVanillaClientIVCTests : public ::testing::Test { +// protected: +// static void SetUpTestSuite() +// { +// srs::init_crs_factory("../srs_db/ignition"); +// srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); +// } - using Flavor = UltraVanillaClientIVC::Flavor; - using Builder = UltraCircuitBuilder; - using FF = typename Flavor::FF; - using VK = Flavor::VerificationKey; - using PK = DeciderProvingKey_; +// using Flavor = UltraVanillaClientIVC::Flavor; +// using Builder = UltraCircuitBuilder; +// using FF = typename Flavor::FF; +// using VK = Flavor::VerificationKey; +// using PK = DeciderProvingKey_; - class MockCircuitSource : public CircuitSource { - std::vector _sizes; - std::vector> _vks; - uint32_t step{ 0 }; +// class MockCircuitSource : public CircuitSource { +// std::vector _sizes; +// std::vector> _vks; +// uint32_t step{ 0 }; - public: - MockCircuitSource(const std::vector& sizes) - : _sizes(sizes) - { - std::fill_n(std::back_inserter(_vks), sizes.size(), nullptr); - } +// public: +// MockCircuitSource(const std::vector& sizes) +// : _sizes(sizes) +// { +// std::fill_n(std::back_inserter(_vks), sizes.size(), nullptr); +// } - MockCircuitSource(const MockCircuitSource& source_without_sizes, std::vector> vks) - : _sizes(source_without_sizes._sizes) - , _vks(vks) - {} +// MockCircuitSource(const MockCircuitSource& source_without_sizes, std::vector> vks) +// : _sizes(source_without_sizes._sizes) +// , _vks(vks) +// {} - Output next() override - { - Builder circuit; - MockCircuits::construct_arithmetic_circuit(circuit, _sizes[step]); - const auto& vk = _vks[step]; - ++step; - return { circuit, vk }; - } +// Output next() override +// { +// Builder circuit; +// MockCircuits::construct_arithmetic_circuit(circuit, _sizes[step]); +// const auto& vk = _vks[step]; +// ++step; +// return { circuit, vk }; +// } - size_t num_circuits() const override - { - ASSERT(_sizes.size() == _vks.size()); - return _sizes.size(); - } - }; -}; +// size_t num_circuits() const override +// { +// ASSERT(_sizes.size() == _vks.size()); +// return _sizes.size(); +// } +// }; +// }; -TEST_F(UltraVanillaClientIVCTests, TwoCircuits) -{ - static constexpr size_t LOG_SIZE = 10; - UltraVanillaClientIVC ivc(1 << LOG_SIZE); - MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE } }; - EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); -}; +// TEST_F(UltraVanillaClientIVCTests, TwoCircuits) +// { +// static constexpr size_t LOG_SIZE = 10; +// UltraVanillaClientIVC ivc(1 << LOG_SIZE); +// MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE } }; +// EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); +// }; -TEST_F(UltraVanillaClientIVCTests, ThreeCircuits) -{ - static constexpr size_t LOG_SIZE = 10; - UltraVanillaClientIVC ivc(1 << LOG_SIZE); - MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE, LOG_SIZE } }; - EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); -}; +// TEST_F(UltraVanillaClientIVCTests, ThreeCircuits) +// { +// static constexpr size_t LOG_SIZE = 10; +// UltraVanillaClientIVC ivc(1 << LOG_SIZE); +// MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE, LOG_SIZE } }; +// EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); +// }; -/** - * @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys - * @details The tests precomputed the keys via one pass of the ivc prover, then it usese then in a second pass. - */ -TEST_F(UltraVanillaClientIVCTests, PrecomputedVerificationKeys) -{ +// /** +// * @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys +// * @details The tests precomputed the keys via one pass of the ivc prover, then it usese then in a second pass. +// */ +// TEST_F(UltraVanillaClientIVCTests, PrecomputedVerificationKeys) +// { - static constexpr size_t LOG_SIZE = 10; +// static constexpr size_t LOG_SIZE = 10; - UltraVanillaClientIVC ivc_1(1 << LOG_SIZE); - MockCircuitSource circuit_source_no_vks{ { LOG_SIZE, LOG_SIZE } }; - auto vks = ivc_1.compute_vks(circuit_source_no_vks); +// UltraVanillaClientIVC ivc_1(1 << LOG_SIZE); +// MockCircuitSource circuit_source_no_vks{ { LOG_SIZE, LOG_SIZE } }; +// auto vks = ivc_1.compute_vks(circuit_source_no_vks); - UltraVanillaClientIVC ivc_2(1 << LOG_SIZE); // need to refactor accumulator_value use to reuse ivc_1 - MockCircuitSource circuit_source_with_vks{ circuit_source_no_vks, vks }; - EXPECT_TRUE(ivc_2.prove_and_verify(circuit_source_with_vks)); -}; +// UltraVanillaClientIVC ivc_2(1 << LOG_SIZE); // need to refactor accumulator_value use to reuse ivc_1 +// MockCircuitSource circuit_source_with_vks{ circuit_source_no_vks, vks }; +// EXPECT_TRUE(ivc_2.prove_and_verify(circuit_source_with_vks)); +// }; -// TODO(https://github.com/AztecProtocol/barretenberg/issues/1177) Implement failure tests \ No newline at end of file +// // TODO(https://github.com/AztecProtocol/barretenberg/issues/1177) Implement failure tests From 433055b488fd0ea5ae8df564ca537b74e23a8b0e Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 18 Feb 2025 20:11:10 +0000 Subject: [PATCH 09/33] delete old merge classes and old functionality from op queue --- .../mega_circuit_builder.test.cpp | 20 +-- .../src/barretenberg/goblin/mock_circuits.hpp | 24 ++-- .../op_queue/ecc_op_queue.hpp | 79 +---------- .../ultra_honk/mega_honk.test.cpp | 23 ++-- .../barretenberg/ultra_honk/merge_prover.cpp | 130 ------------------ .../barretenberg/ultra_honk/merge_prover.hpp | 41 ------ .../ultra_honk/merge_prover_new.cpp | 3 +- .../ultra_honk/merge_verifier.cpp | 89 ------------ .../ultra_honk/merge_verifier.hpp | 36 ----- 9 files changed, 38 insertions(+), 407 deletions(-) delete mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.hpp delete mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp delete mode 100644 barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp index 03e4d731d727..d39f28ae1621 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp @@ -148,15 +148,15 @@ TEST(MegaCircuitBuilder, GoblinEccOpQueueUltraOps) builder.queue_ecc_mul_accum(P2, z); builder.queue_ecc_eq(); - // Check that the ultra ops recorded in the EccOpQueue match the ops recorded in the wires - auto ultra_ops = builder.op_queue->get_aggregate_transcript(); - for (size_t i = 1; i < 4; ++i) { - for (size_t j = 0; j < builder.blocks.ecc_op.size(); ++j) { - auto op_wire_val = builder.variables[builder.blocks.ecc_op.wires[i][j]]; - auto ultra_op_val = ultra_ops[i][j]; - ASSERT_EQ(op_wire_val, ultra_op_val); - } - } + // // Check that the ultra ops recorded in the EccOpQueue match the ops recorded in the wires + // auto ultra_ops = builder.op_queue->get_aggregate_transcript(); + // for (size_t i = 1; i < 4; ++i) { + // for (size_t j = 0; j < builder.blocks.ecc_op.size(); ++j) { + // auto op_wire_val = builder.variables[builder.blocks.ecc_op.wires[i][j]]; + // auto ultra_op_val = ultra_ops[i][j]; + // ASSERT_EQ(op_wire_val, ultra_op_val); + // } + // } } /** @@ -203,4 +203,4 @@ TEST(MegaCircuitBuilder, CompleteSelectorPartitioningCheck) } } -} // namespace bb \ No newline at end of file +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index b63aaa9091dc..2b29d8caa72d 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -139,7 +139,8 @@ class GoblinMockCircuits { * @param op_queue */ static void perform_op_queue_interactions_for_mock_first_circuit( - std::shared_ptr& op_queue, std::shared_ptr commitment_key = nullptr) + std::shared_ptr& op_queue, + [[maybe_unused]] std::shared_ptr commitment_key = nullptr) { PROFILE_THIS(); @@ -148,22 +149,21 @@ class GoblinMockCircuits { // Add some goblinized ecc ops MockCircuits::construct_goblin_ecc_op_circuit(builder); - op_queue->set_size_data(); - // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) #ifndef __wasm__ // TODO(Adam): This is crashing wasm-in-browser. It doesn't make sense to call this in browser... bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); #endif - auto bn254_commitment_key = - commitment_key ? commitment_key : std::make_shared(op_queue->get_current_size()); - std::array op_queue_commitments; - size_t idx = 0; - for (auto& entry : op_queue->get_aggregate_transcript()) { - op_queue_commitments[idx++] = bn254_commitment_key->commit({ 0, entry }); - } - // Store the commitment data for use by the prover of the next circuit - op_queue->set_commitment_data(op_queue_commitments); + // WORKTODO: may want to reinstate something analogous to this in the future + // auto bn254_commitment_key = + // commitment_key ? commitment_key : std::make_shared(op_queue->get_ultra_ops_table_size()); + // std::array op_queue_commitments; + // size_t idx = 0; + // for (auto& entry : op_queue->get_aggregate_transcript()) { + // op_queue_commitments[idx++] = bn254_commitment_key->commit({ 0, entry }); + // } + // // Store the commitment data for use by the prover of the next circuit + // op_queue->set_commitment_data(op_queue_commitments); } /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index 55ffe6052086..969d71d35f01 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -28,8 +28,8 @@ class ECCOpQueue { static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION; - std::vector> raw_ops; - std::array, 4> ultra_ops; // ops encoded in the width-4 Ultra format + std::vector> fuzzing_raw_ops; + // std::array, 4> ultra_ops; // ops encoded in the width-4 Ultra format RawEccOpsTable raw_ops_table; UltraEccOpsTable ultra_ops_table; @@ -129,7 +129,7 @@ class ECCOpQueue { * @brief A fuzzing only method for setting raw ops directly * */ - void set_raw_ops_for_fuzzing(std::vector& raw_ops_in) { raw_ops = raw_ops_in; } + void set_raw_ops_for_fuzzing(std::vector& raw_ops_in) { fuzzing_raw_ops = raw_ops_in; } /** * @brief A testing only method that adds an erroneous equality op to the raw ops @@ -138,7 +138,7 @@ class ECCOpQueue { */ void add_erroneous_equality_op_for_testing() { - raw_ops.emplace_back(ECCVMOperation{ .eq = true, .reset = true, .base_point = Point::random_element() }); + append_raw_op(ECCVMOperation{ .eq = true, .reset = true, .base_point = Point::random_element() }); } /** @@ -150,56 +150,9 @@ class ECCOpQueue { Point get_accumulator() { return accumulator; } - /** - * @brief Set the current and previous size of the ultra_ops transcript - * - * @details previous_ultra_ops_size = M_{i-1} is needed by the prover to extract the previous aggregate op - * queue transcript T_{i-1} from the current one T_i. This method should be called when a circuit is 'finalized'. - */ - void set_size_data() - { - previous_ultra_ops_size = current_ultra_ops_size; - current_ultra_ops_size = ultra_ops[0].size(); - // initialize_new_subtable(); - } - - [[nodiscard]] size_t get_previous_size() const { return previous_ultra_ops_size; } - [[nodiscard]] size_t get_current_size() const { return current_ultra_ops_size; } - void set_commitment_data(std::array& commitments) { ultra_ops_commitments = commitments; } const auto& get_ultra_ops_commitments() { return ultra_ops_commitments; } - /** - * @brief Get a 'view' of the current ultra ops object - * - * @return std::vector> - */ - std::vector> get_aggregate_transcript() - { - std::vector> result; - result.reserve(ultra_ops.size()); - for (auto& entry : ultra_ops) { - result.emplace_back(entry); - } - return result; - } - - /** - * @brief Get a 'view' of the previous ultra ops object - * - * @return std::vector> - */ - std::vector> get_previous_aggregate_transcript() - { - std::vector> result; - result.reserve(ultra_ops.size()); - // Construct T_{i-1} as a view of size M_{i-1} into T_i - for (auto& entry : ultra_ops) { - result.emplace_back(entry.begin(), previous_ultra_ops_size); - } - return result; - } - /** * @brief Write point addition op to queue and natively perform addition * @@ -275,8 +228,7 @@ class ECCOpQueue { private: void append_raw_op(const ECCVMOperation& op) { - raw_ops.emplace_back(op); - eccvm_row_tracker.update_cached_msms(raw_ops.back()); + eccvm_row_tracker.update_cached_msms(op); raw_ops_table.push(op); } /** @@ -324,31 +276,10 @@ class ECCOpQueue { ultra_op.z_2 = z_2.to_montgomery_form(); } - append_to_ultra_ops(ultra_op); - ultra_ops_table.push(ultra_op); return ultra_op; } - - /** - * @brief Populate two rows of the ultra ops,representing a complete ECC operation - * @note Only the first 'op' field is utilized so the second is explicitly set to 0 - * - * @param tuple - */ - void append_to_ultra_ops(UltraOp tuple) - { - ultra_ops[0].emplace_back(tuple.op); - ultra_ops[1].emplace_back(tuple.x_lo); - ultra_ops[2].emplace_back(tuple.x_hi); - ultra_ops[3].emplace_back(tuple.y_lo); - - ultra_ops[0].emplace_back(0); - ultra_ops[1].emplace_back(tuple.y_hi); - ultra_ops[2].emplace_back(tuple.z_1); - ultra_ops[3].emplace_back(tuple.z_2); - } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 10d60c169000..d31426182b18 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -8,9 +8,7 @@ #include "barretenberg/plonk_honk_shared/relation_checker.hpp" #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include "barretenberg/ultra_honk/merge_prover.hpp" #include "barretenberg/ultra_honk/merge_prover_new.hpp" -#include "barretenberg/ultra_honk/merge_verifier.hpp" #include "barretenberg/ultra_honk/merge_verifier_new.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -302,7 +300,6 @@ TYPED_TEST(MegaHonkTests, NewMergePolyconstruction) GoblinMockCircuits::construct_simple_circuit(builder); const size_t expected_table_size = op_queue->get_ultra_ops_table_size(); - // op_queue->set_size_data(); // EXPECT_EQ(op_queue->get_current_size(), expected_table_size); @@ -401,16 +398,16 @@ TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge) EXPECT_TRUE(merge_verified); } - // Compute the commitments to the aggregate op queue directly and check that they match those that were computed - // iteratively during transcript aggregation by the provers and stored in the op queue. - size_t aggregate_op_queue_size = op_queue->get_current_size(); - auto ultra_ops = op_queue->get_aggregate_transcript(); - auto commitment_key = std::make_shared(aggregate_op_queue_size); - size_t idx = 0; - for (const auto& result : op_queue->get_ultra_ops_commitments()) { - auto expected = commitment_key->commit({ /* start index */ 0, ultra_ops[idx++] }); - EXPECT_EQ(result, expected); - } + // // Compute the commitments to the aggregate op queue directly and check that they match those that were computed + // // iteratively during transcript aggregation by the provers and stored in the op queue. + // size_t aggregate_op_queue_size = op_queue->get_current_size(); + // auto ultra_ops = op_queue->get_aggregate_transcript(); + // auto commitment_key = std::make_shared(aggregate_op_queue_size); + // size_t idx = 0; + // for (const auto& result : op_queue->get_ultra_ops_commitments()) { + // auto expected = commitment_key->commit({ /* start index */ 0, ultra_ops[idx++] }); + // EXPECT_EQ(result, expected); + // } } /** diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp deleted file mode 100644 index 00d3757db444..000000000000 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ /dev/null @@ -1,130 +0,0 @@ -#include "merge_prover.hpp" -#include "barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp" - -namespace bb { - -/** - * @brief Create MergeProver - * @details We require an SRS at least as large as the current op queue size in order to commit to the shifted - * per-circuit contribution t_i^{shift} - * - */ -template -MergeProver_::MergeProver_(const std::shared_ptr& op_queue, - std::shared_ptr commitment_key) - : op_queue(op_queue) -{ - // Update internal size data in the op queue that allows for extraction of e.g. previous aggregate transcript - op_queue->set_size_data(); - pcs_commitment_key = - commitment_key ? commitment_key : std::make_shared(op_queue->get_current_size()); -} - -/** - * @brief Prove proper construction of the aggregate Goblin ECC op queue polynomials T_i^(j), j = 1,2,3,4. - * @details Let T_i^(j) be the jth column of the aggregate op queue after incorporating the contribution from the - * present circuit. T_{i-1}^(j) corresponds to the aggregate op queue at the previous stage and $t_i^(j)$ represents - * the contribution from the present circuit only. For each j, we have the relationship T_i = T_{i-1} + right_shift(t_i, - * M_{i-1}), where the shift magnitude M_{i-1} is the honest length of T_{i-1}. This protocol demonstrates, assuming the - * length of T_{i-1} is at most M_{i-1}, that the aggregate op queue has been constructed correctly via a simple - * Schwartz-Zippel check. Evaluations are proven via batched KZG. - * - * TODO(#746): Prove connection between t_i^{shift}, committed to herein, and t_i, used in the main protocol. See issue - * for details (https://github.com/AztecProtocol/barretenberg/issues/746). - * - * @return honk::proof - */ -template HonkProof MergeProver_::construct_proof() -{ - transcript = std::make_shared(); - - size_t N = op_queue->get_current_size(); - - // Extract T_i, T_{i-1} - auto T_current = op_queue->get_aggregate_transcript(); - auto T_prev = op_queue->get_previous_aggregate_transcript(); - // TODO(#723): Cannot currently support an empty T_{i-1}. Need to be able to properly handle zero commitment. - ASSERT(T_prev[0].size() > 0); - ASSERT(T_current[0].size() > T_prev[0].size()); // Must have some new ops to accumulate otherwise C_t_shift = 0 - - // Construct t_i^{shift} as T_i - T_{i-1} - std::array t_shift; - for (size_t i = 0; i < NUM_WIRES; ++i) { - t_shift[i] = Polynomial(T_current[i]); - t_shift[i] -= { 0, T_prev[i] }; - } - - // Compute/get commitments [t_i^{shift}], [T_{i-1}], and [T_i] and add to transcript - std::array C_T_current; - for (size_t idx = 0; idx < t_shift.size(); ++idx) { - // Get previous transcript commitment [T_{i-1}] from op queue - const auto& C_T_prev = op_queue->get_ultra_ops_commitments()[idx]; - // Compute commitment [t_i^{shift}] directly - auto C_t_shift = pcs_commitment_key->commit(t_shift[idx]); - // Compute updated aggregate transcript commitment as [T_i] = [T_{i-1}] + [t_i^{shift}] - C_T_current[idx] = C_T_prev + C_t_shift; - - std::string suffix = std::to_string(idx + 1); - transcript->send_to_verifier("T_PREV_" + suffix, C_T_prev); - transcript->send_to_verifier("t_SHIFT_" + suffix, C_t_shift); - transcript->send_to_verifier("T_CURRENT_" + suffix, C_T_current[idx]); - } - - // Store the commitments [T_{i}] (to be used later in subsequent iterations as [T_{i-1}]). - op_queue->set_commitment_data(C_T_current); - - // Compute evaluations T_i(\kappa), T_{i-1}(\kappa), t_i^{shift}(\kappa), add to transcript. For each polynomial - // we add a univariate opening claim {p(X), (\kappa, p(\kappa))} to the set of claims to be checked via batched KZG. - FF kappa = transcript->template get_challenge("kappa"); - - // Add univariate opening claims for each polynomial. - std::vector opening_claims; - // Compute evaluation T_{i-1}(\kappa) - for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - auto polynomial = Polynomial(T_prev[idx]); - auto evaluation = polynomial.evaluate(kappa); - transcript->send_to_verifier("T_prev_eval_" + std::to_string(idx + 1), evaluation); - opening_claims.emplace_back(OpeningClaim{ polynomial, { kappa, evaluation } }); - } - // Compute evaluation t_i^{shift}(\kappa) - for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - auto evaluation = t_shift[idx].evaluate(kappa); - transcript->send_to_verifier("t_shift_eval_" + std::to_string(idx + 1), evaluation); - opening_claims.emplace_back(OpeningClaim{ t_shift[idx], { kappa, evaluation } }); - } - // Compute evaluation T_i(\kappa) - for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - auto polynomial = Polynomial(T_current[idx]); - auto evaluation = polynomial.evaluate(kappa); - transcript->send_to_verifier("T_current_eval_" + std::to_string(idx + 1), evaluation); - opening_claims.emplace_back(OpeningClaim{ polynomial, { kappa, evaluation } }); - } - - FF alpha = transcript->template get_challenge("alpha"); - - // Construct batched polynomial to opened via KZG - auto batched_polynomial = Polynomial(N); - auto batched_eval = FF(0); - auto alpha_pow = FF(1); - for (auto& claim : opening_claims) { - batched_polynomial.add_scaled(claim.polynomial, alpha_pow); - batched_eval += alpha_pow * claim.opening_pair.evaluation; - alpha_pow *= alpha; - } - - // Construct and commit to KZG quotient polynomial q = (f - v) / (X - kappa) - auto quotient = batched_polynomial; - quotient.at(0) -= batched_eval; - quotient.factor_roots(kappa); - - auto quotient_commitment = pcs_commitment_key->commit(quotient); - transcript->send_to_verifier("KZG:W", quotient_commitment); - - return transcript->proof_data; -} - -template class MergeProver_; -template class MergeProver_; -template class MergeProver_; - -} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.hpp deleted file mode 100644 index 9a265698c096..000000000000 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include "barretenberg/commitment_schemes/claim.hpp" -#include "barretenberg/honk/proof_system/types/proof.hpp" -#include "barretenberg/stdlib_circuit_builders/mega_flavor.hpp" -#include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/transcript/transcript.hpp" - -namespace bb { - -/** - * @brief Prover class for the Goblin ECC op queue transcript merge protocol - * - */ -template class MergeProver_ { - using FF = typename Flavor::FF; - using Polynomial = typename Flavor::Polynomial; - using CommitmentKey = typename Flavor::CommitmentKey; - using Commitment = typename Flavor::Commitment; - using PCS = typename Flavor::PCS; - using Curve = typename Flavor::Curve; - using OpeningClaim = ProverOpeningClaim; - using OpeningPair = bb::OpeningPair; - using Transcript = NativeTranscript; - - public: - std::shared_ptr transcript; - - explicit MergeProver_(const std::shared_ptr& op_queue, - std::shared_ptr commitment_key = nullptr); - - BB_PROFILE HonkProof construct_proof(); - - private: - std::shared_ptr op_queue; - std::shared_ptr pcs_commitment_key; - static constexpr size_t NUM_WIRES = MegaFlavor::NUM_WIRES; -}; - -} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp index 814cd656e736..42a016bd1335 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp @@ -15,9 +15,8 @@ MergeProverNew_::MergeProverNew_(const std::shared_ptr& op_q : op_queue(op_queue) { // Update internal size data in the op queue that allows for extraction of e.g. previous aggregate transcript - op_queue->set_size_data(); pcs_commitment_key = - commitment_key ? commitment_key : std::make_shared(op_queue->get_current_size()); + commitment_key ? commitment_key : std::make_shared(op_queue->get_ultra_ops_table_size()); } /** diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp deleted file mode 100644 index 13f2bf21ba07..000000000000 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp +++ /dev/null @@ -1,89 +0,0 @@ -#include "merge_verifier.hpp" -#include "barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" - -namespace bb { - -template -MergeVerifier_::MergeVerifier_() - : transcript(std::make_shared()) - , pcs_verification_key(std::make_unique()){}; - -/** - * @brief Verify proper construction of the aggregate Goblin ECC op queue polynomials T_i^(j), j = 1,2,3,4. - * @details Let T_i^(j) be the jth column of the aggregate op queue after incorporating the contribution from the - * present circuit. T_{i-1}^(j) corresponds to the aggregate op queue at the previous stage and $t_i^(j)$ represents - * the contribution from the present circuit only. For each j, we have the relationship T_i = T_{i-1} + right_shift(t_i, - * M_{i-1}), where the shift magnitude M_{i-1} is the honest length of T_{i-1}. This protocol verfies, assuming the - * length of T_{i-1} is at most M_{i-1}, that the aggregate op queue has been constructed correctly via a simple - * Schwartz-Zippel check. Evaluations are checked via batched KZG. - * - * @tparam Flavor - * @return bool - */ -template bool MergeVerifier_::verify_proof(const HonkProof& proof) -{ - transcript = std::make_shared(proof); - - // Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i] - std::array C_T_prev; - std::array C_t_shift; - std::array C_T_current; - for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - C_T_prev[idx] = transcript->template receive_from_prover("T_PREV_" + std::to_string(idx + 1)); - C_t_shift[idx] = transcript->template receive_from_prover("t_SHIFT_" + std::to_string(idx + 1)); - C_T_current[idx] = transcript->template receive_from_prover("T_CURRENT_" + std::to_string(idx + 1)); - } - - FF kappa = transcript->template get_challenge("kappa"); - - // Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]} - std::array T_prev_evals; - std::array t_shift_evals; - std::array T_current_evals; - std::vector opening_claims; - for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - T_prev_evals[idx] = transcript->template receive_from_prover("T_prev_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, C_T_prev[idx] }); - } - for (size_t idx = 0; idx < Flavor::NUM_WIRES; ++idx) { - t_shift_evals[idx] = transcript->template receive_from_prover("t_shift_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, t_shift_evals[idx] }, C_t_shift[idx] }); - } - for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - T_current_evals[idx] = - transcript->template receive_from_prover("T_current_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, C_T_current[idx] }); - } - - // Check the identity T_i(\kappa) = T_{i-1}(\kappa) + t_i^{shift}(\kappa). If it fails, return false - bool identity_checked = true; - for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - identity_checked = identity_checked && (T_current_evals[idx] == T_prev_evals[idx] + t_shift_evals[idx]); - } - - FF alpha = transcript->template get_challenge("alpha"); - - // Construct batched commitment and evaluation from constituents - auto batched_commitment = opening_claims[0].commitment; - auto batched_eval = opening_claims[0].opening_pair.evaluation; - auto alpha_pow = alpha; - for (size_t idx = 1; idx < opening_claims.size(); ++idx) { - auto& claim = opening_claims[idx]; - batched_commitment = batched_commitment + (claim.commitment * alpha_pow); - batched_eval += alpha_pow * claim.opening_pair.evaluation; - alpha_pow *= alpha; - } - - OpeningClaim batched_claim = { { kappa, batched_eval }, batched_commitment }; - - auto pairing_points = PCS::reduce_verify(batched_claim, transcript); - auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); - return identity_checked && verified; -} - -template class MergeVerifier_; -template class MergeVerifier_; -template class MergeVerifier_; - -} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp deleted file mode 100644 index 80e0ccc158af..000000000000 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include "barretenberg/commitment_schemes/claim.hpp" -#include "barretenberg/honk/proof_system/types/proof.hpp" -#include "barretenberg/srs/global_crs.hpp" -#include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp" -#include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" -#include "barretenberg/transcript/transcript.hpp" - -namespace bb { - -/** - * @brief Verifier class for the Goblin ECC op queue transcript merge protocol - * - */ -template class MergeVerifier_ { - using Curve = typename Flavor::Curve; - using FF = typename Curve::ScalarField; - using Commitment = typename Curve::AffineElement; - using PCS = bb::KZG; - using OpeningClaim = bb::OpeningClaim; - using VerifierCommitmentKey = bb::VerifierCommitmentKey; - using Transcript = NativeTranscript; - - public: - std::shared_ptr transcript; - - explicit MergeVerifier_(); - bool verify_proof(const HonkProof& proof); - - private: - std::shared_ptr pcs_verification_key; - static constexpr size_t NUM_WIRES = Flavor::NUM_WIRES; -}; - -} // namespace bb From e56df0aef2e1144e87b41241cb89f00eccf6e3b6 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 18 Feb 2025 20:47:42 +0000 Subject: [PATCH 10/33] fix convert to Frs on size_t --- .../cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp index 42a016bd1335..bb92e5384269 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp @@ -49,7 +49,7 @@ template HonkProof MergeProverNew_::construct_proof() const size_t current_table_size = T_current[0].size(); const size_t current_subtable_size = t_current[0].size(); - transcript->send_to_verifier("subtable_size", current_subtable_size); + transcript->send_to_verifier("subtable_size", static_cast(current_subtable_size)); info("subtable_size: ", current_subtable_size); // Compute/get commitments [t^{shift}], [T_prev], and [T] and add to transcript From e6614adc06cbfe38ca865481131e935534f62e04 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 18 Feb 2025 23:10:35 +0000 Subject: [PATCH 11/33] fix mock merge proof and acir mega builder --- .../barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp | 4 ++++ .../stdlib_circuit_builders/mega_circuit_builder.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp index 7a6bc5e88640..a1a6fd057bb9 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp @@ -236,6 +236,7 @@ std::shared_ptr create_mock_decider_vk() * * @return ClientIVC::MergeProof */ +// WORKTODO: Make sure there is a test to check that this produces a correctly sized mock merge proof ClientIVC::MergeProof create_dummy_merge_proof() { using FF = ClientIVC::FF; @@ -246,6 +247,9 @@ ClientIVC::MergeProof create_dummy_merge_proof() auto mock_commitment = curve::BN254::AffineElement::one(); std::vector mock_commitment_frs = field_conversion::convert_to_bn254_frs(mock_commitment); + // Populate mock subtable size + proof.emplace_back(mock_val); + // There are 12 entities in the merge protocol (4 columns x 3 components; aggregate transcript, previous aggregate // transcript, current transcript contribution) const size_t NUM_TRANSCRIPT_ENTITIES = 12; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp index 6e4ec2fd6cc9..53d8f2f6581e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp @@ -81,6 +81,9 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_(/*size_hint=*/0, witness_values, public_inputs, varnum) , op_queue(std::move(op_queue_in)) { + // Instantiate the subtable to be populated with goblin ecc ops from this circuit + op_queue->initialize_new_subtable(); + // Set indices to constants corresponding to Goblin ECC op codes set_goblin_ecc_op_code_constant_variables(); }; From 2d1ee510f42142fc4a85e3ef8667eb0007def529 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 19 Feb 2025 14:35:50 +0000 Subject: [PATCH 12/33] cleanup and rename files --- .../mega_circuit_builder.test.cpp | 18 ++++---- .../commitment_schemes/kzg/kzg.test.cpp | 28 ------------ .../cpp/src/barretenberg/goblin/goblin.hpp | 8 ++-- .../goblin_verifier/merge_verifier.test.cpp | 8 ++-- .../ultra_honk/mega_honk.test.cpp | 43 +++---------------- ...{merge_prover_new.cpp => merge_prover.cpp} | 14 +++--- ...{merge_prover_new.hpp => merge_prover.hpp} | 6 +-- ...ge_verifier_new.cpp => merge_verifier.cpp} | 12 +++--- ...ge_verifier_new.hpp => merge_verifier.hpp} | 4 +- 9 files changed, 40 insertions(+), 101 deletions(-) rename barretenberg/cpp/src/barretenberg/ultra_honk/{merge_prover_new.cpp => merge_prover.cpp} (92%) rename barretenberg/cpp/src/barretenberg/ultra_honk/{merge_prover_new.hpp => merge_prover.hpp} (84%) rename barretenberg/cpp/src/barretenberg/ultra_honk/{merge_verifier_new.cpp => merge_verifier.cpp} (93%) rename barretenberg/cpp/src/barretenberg/ultra_honk/{merge_verifier_new.hpp => merge_verifier.hpp} (92%) diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp index d39f28ae1621..9f2b93714a7e 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp @@ -148,15 +148,15 @@ TEST(MegaCircuitBuilder, GoblinEccOpQueueUltraOps) builder.queue_ecc_mul_accum(P2, z); builder.queue_ecc_eq(); - // // Check that the ultra ops recorded in the EccOpQueue match the ops recorded in the wires - // auto ultra_ops = builder.op_queue->get_aggregate_transcript(); - // for (size_t i = 1; i < 4; ++i) { - // for (size_t j = 0; j < builder.blocks.ecc_op.size(); ++j) { - // auto op_wire_val = builder.variables[builder.blocks.ecc_op.wires[i][j]]; - // auto ultra_op_val = ultra_ops[i][j]; - // ASSERT_EQ(op_wire_val, ultra_op_val); - // } - // } + // Check that the ultra ops recorded in the EccOpQueue match the ops recorded in the wires + auto ultra_ops = builder.op_queue->get_current_subtable_columns(); + for (size_t i = 1; i < 4; ++i) { + for (size_t j = 0; j < builder.blocks.ecc_op.size(); ++j) { + auto op_wire_val = builder.variables[builder.blocks.ecc_op.wires[i][j]]; + auto ultra_op_val = ultra_ops[i][j]; + ASSERT_EQ(op_wire_val, ultra_op_val); + } + } } /** diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index f62926e12cc4..74099582ed38 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -59,34 +59,6 @@ TEST_F(KZGTest, single) EXPECT_EQ(vk->pairing_check(pairing_points[0], pairing_points[1]), true); } -TEST_F(KZGTest, OpenShiftViaUnshiftedCommitment) -{ - // Construct a polynomial that is right shiftable by shift_magnitude - const size_t shift_magnitude = 4; - // const size_t shift_magnitude = 0; - auto witness = bb::Polynomial::random(n - shift_magnitude, n, 0); - bb::Polynomial witness_shifted(n); - witness_shifted += witness.right_shifted(shift_magnitude); - - // Commit to the unshifted polynomial - const Commitment commitment = ck->commit(witness); - - // Compute the shifted evaluation - const Fr challenge = Fr::random_element(); - const Fr unshifted_evaluation = witness.evaluate(challenge); - const Fr shifted_evaluation = unshifted_evaluation * challenge.pow(shift_magnitude); - - auto prover_transcript = NativeTranscript::prover_init_empty(); - PCS::compute_opening_proof(ck, { witness, { challenge, unshifted_evaluation } }, prover_transcript); - - Fr unshifted_eval_reconstructed = shifted_evaluation * (challenge.pow(shift_magnitude)).invert(); - auto opening_claim = OpeningClaim{ { challenge, unshifted_eval_reconstructed }, commitment }; - auto verifier_transcript = NativeTranscript::verifier_init_empty(prover_transcript); - const auto pairing_points = PCS::reduce_verify(opening_claim, verifier_transcript); - - EXPECT_EQ(vk->pairing_check(pairing_points[0], pairing_points[1]), true); -} - /** * @brief Test opening proof of a polynomial given by its evaluations at \f$ i = 0, \ldots, n \f$. Should only be used * for small values of \f$ n \f$. diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index df050006eaa2..e7e89185d583 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -14,8 +14,8 @@ #include "barretenberg/translator_vm/translator_circuit_builder.hpp" #include "barretenberg/translator_vm/translator_prover.hpp" #include "barretenberg/translator_vm/translator_verifier.hpp" -#include "barretenberg/ultra_honk/merge_prover_new.hpp" -#include "barretenberg/ultra_honk/merge_verifier_new.hpp" +#include "barretenberg/ultra_honk/merge_prover.hpp" +#include "barretenberg/ultra_honk/merge_verifier.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -37,7 +37,7 @@ class GoblinProver { using TranslatorBuilder = TranslatorCircuitBuilder; using RecursiveMergeVerifier = stdlib::recursion::goblin::MergeRecursiveVerifier_; using PairingPoints = RecursiveMergeVerifier::PairingPoints; - using MergeProver = MergeProverNew_; + using MergeProver = MergeProver_; using VerificationKey = MegaFlavor::VerificationKey; using MergeProof = std::vector; /** @@ -256,7 +256,7 @@ class GoblinVerifier { public: using ECCVMVerificationKey = ECCVMFlavor::VerificationKey; using TranslatorVerificationKey = bb::TranslatorFlavor::VerificationKey; - using MergeVerifier = bb::MergeVerifierNew_; + using MergeVerifier = bb::MergeVerifier_; struct VerifierInput { std::shared_ptr eccvm_verification_key; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_verifier.test.cpp index 4a8d34d90414..7f3f302ad449 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_verifier.test.cpp @@ -1,10 +1,10 @@ +#include "barretenberg/ultra_honk/merge_verifier.hpp" #include "barretenberg/circuit_checker/circuit_checker.hpp" #include "barretenberg/common/test.hpp" #include "barretenberg/goblin/mock_circuits.hpp" #include "barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.hpp" #include "barretenberg/stdlib/primitives/curves/bn254.hpp" -#include "barretenberg/ultra_honk/merge_prover_new.hpp" -#include "barretenberg/ultra_honk/merge_verifier_new.hpp" +#include "barretenberg/ultra_honk/merge_prover.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -31,8 +31,8 @@ template class RecursiveMergeVerifierTest : public test using Commitment = InnerFlavor::Commitment; using FF = InnerFlavor::FF; using VerifierCommitmentKey = bb::VerifierCommitmentKey; - using MergeProver = MergeProverNew_; - using MergeVerifier = MergeVerifierNew_; + using MergeProver = MergeProver_; + using MergeVerifier = MergeVerifier_; public: static void SetUpTestSuite() { bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index d31426182b18..649bde6c55c8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -8,8 +8,8 @@ #include "barretenberg/plonk_honk_shared/relation_checker.hpp" #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -#include "barretenberg/ultra_honk/merge_prover_new.hpp" -#include "barretenberg/ultra_honk/merge_verifier_new.hpp" +#include "barretenberg/ultra_honk/merge_prover.hpp" +#include "barretenberg/ultra_honk/merge_verifier.hpp" #include "barretenberg/ultra_honk/ultra_prover.hpp" #include "barretenberg/ultra_honk/ultra_verifier.hpp" @@ -27,10 +27,8 @@ template class MegaHonkTests : public ::testing::Test { using FF = Curve::ScalarField; using Point = Curve::AffineElement; using CommitmentKey = bb::CommitmentKey; - using MergeProver = MergeProverNew_; - using MergeVerifier = MergeVerifierNew_; - using MergeProverNew = MergeProverNew_; - using MergeVerifierNew = MergeVerifierNew_; + using MergeProver = MergeProver_; + using MergeVerifier = MergeVerifier_; using Prover = UltraProver_; using Verifier = UltraVerifier_; using VerificationKey = typename Flavor::VerificationKey; @@ -87,20 +85,6 @@ template class MegaHonkTests : public ::testing::Test { return verified; } - - /** - * @brief Construct and verify a Goblin ECC op queue merge proof - * - */ - bool construct_and_verify_merge_proof_new(auto& op_queue) - { - MergeProverNew merge_prover{ op_queue }; - MergeVerifierNew merge_verifier; - auto merge_proof = merge_prover.construct_proof(); - bool verified = merge_verifier.verify_proof(merge_proof); - - return verified; - } }; TYPED_TEST_SUITE(MegaHonkTests, FlavorTypes); @@ -269,24 +253,7 @@ TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly) } } -TYPED_TEST(MegaHonkTests, NewMultipleCircuitsMergeOnly) -{ - using Flavor = TypeParam; - // Instantiate EccOpQueue. This will be shared across all circuits in the series - auto op_queue = std::make_shared(); - - GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - - // Construct multiple test circuits that share an ECC op queue. Generate and verify a proof for each. - auto builder = typename Flavor::CircuitBuilder{ op_queue }; - - GoblinMockCircuits::construct_simple_circuit(builder); - - // Construct and verify Goblin ECC op queue Merge proof - auto merge_verified = this->construct_and_verify_merge_proof_new(op_queue); - EXPECT_TRUE(merge_verified); -} - +// WORKTODO: move to op queue test suite? TYPED_TEST(MegaHonkTests, NewMergePolyconstruction) { using Flavor = TypeParam; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp similarity index 92% rename from barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index bb92e5384269..de744eb0068c 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -1,4 +1,4 @@ -#include "merge_prover_new.hpp" +#include "merge_prover.hpp" #include "barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp" namespace bb { @@ -10,8 +10,8 @@ namespace bb { * */ template -MergeProverNew_::MergeProverNew_(const std::shared_ptr& op_queue, - std::shared_ptr commitment_key) +MergeProver_::MergeProver_(const std::shared_ptr& op_queue, + std::shared_ptr commitment_key) : op_queue(op_queue) { // Update internal size data in the op queue that allows for extraction of e.g. previous aggregate transcript @@ -33,7 +33,7 @@ MergeProverNew_::MergeProverNew_(const std::shared_ptr& op_q * * @return honk::proof */ -template HonkProof MergeProverNew_::construct_proof() +template HonkProof MergeProver_::construct_proof() { transcript = std::make_shared(); @@ -119,8 +119,8 @@ template HonkProof MergeProverNew_::construct_proof() return transcript->proof_data; } -template class MergeProverNew_; -template class MergeProverNew_; -template class MergeProverNew_; +template class MergeProver_; +template class MergeProver_; +template class MergeProver_; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.hpp similarity index 84% rename from barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.hpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.hpp index 3467f908c451..9a265698c096 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover_new.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.hpp @@ -13,7 +13,7 @@ namespace bb { * @brief Prover class for the Goblin ECC op queue transcript merge protocol * */ -template class MergeProverNew_ { +template class MergeProver_ { using FF = typename Flavor::FF; using Polynomial = typename Flavor::Polynomial; using CommitmentKey = typename Flavor::CommitmentKey; @@ -27,8 +27,8 @@ template class MergeProverNew_ { public: std::shared_ptr transcript; - explicit MergeProverNew_(const std::shared_ptr& op_queue, - std::shared_ptr commitment_key = nullptr); + explicit MergeProver_(const std::shared_ptr& op_queue, + std::shared_ptr commitment_key = nullptr); BB_PROFILE HonkProof construct_proof(); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp similarity index 93% rename from barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp index 4712a69fe13b..6799a1ac0266 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp @@ -1,11 +1,11 @@ -#include "merge_verifier_new.hpp" +#include "merge_verifier.hpp" #include "barretenberg/stdlib_circuit_builders/mega_zk_flavor.hpp" #include "barretenberg/stdlib_circuit_builders/ultra_flavor.hpp" namespace bb { template -MergeVerifierNew_::MergeVerifierNew_() +MergeVerifier_::MergeVerifier_() : transcript(std::make_shared()) , pcs_verification_key(std::make_unique()){}; @@ -21,7 +21,7 @@ MergeVerifierNew_::MergeVerifierNew_() * @tparam Flavor * @return bool */ -template bool MergeVerifierNew_::verify_proof(const HonkProof& proof) +template bool MergeVerifier_::verify_proof(const HonkProof& proof) { transcript = std::make_shared(proof); @@ -98,8 +98,8 @@ template bool MergeVerifierNew_::verify_proof(const Ho return identity_checked && verified; } -template class MergeVerifierNew_; -template class MergeVerifierNew_; -template class MergeVerifierNew_; +template class MergeVerifier_; +template class MergeVerifier_; +template class MergeVerifier_; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.hpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp similarity index 92% rename from barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.hpp rename to barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp index 4095bfe6d859..80e0ccc158af 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier_new.hpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.hpp @@ -13,7 +13,7 @@ namespace bb { * @brief Verifier class for the Goblin ECC op queue transcript merge protocol * */ -template class MergeVerifierNew_ { +template class MergeVerifier_ { using Curve = typename Flavor::Curve; using FF = typename Curve::ScalarField; using Commitment = typename Curve::AffineElement; @@ -25,7 +25,7 @@ template class MergeVerifierNew_ { public: std::shared_ptr transcript; - explicit MergeVerifierNew_(); + explicit MergeVerifier_(); bool verify_proof(const HonkProof& proof); private: From b00aff3891055df62bfb9eb3d5f10ff4e82deacf Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 19 Feb 2025 15:11:57 +0000 Subject: [PATCH 13/33] undo formatting --- .../cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp | 2 +- barretenberg/cpp/src/barretenberg/goblin/goblin.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp index 74099582ed38..5bac7124bcd4 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/kzg/kzg.test.cpp @@ -330,4 +330,4 @@ TEST_F(KZGTest, ShpleminiKzgShiftsRemoval) } // namespace bb std::shared_ptr bb::KZGTest::ck = nullptr; -std::shared_ptr bb::KZGTest::vk = nullptr; +std::shared_ptr bb::KZGTest::vk = nullptr; \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index e7e89185d583..872b168f9605 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -309,4 +309,4 @@ class GoblinVerifier { return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified; }; }; -} // namespace bb +} // namespace bb \ No newline at end of file From 5d08ff1d2033250ad4e2a311803d441ab59c7919 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 19 Feb 2025 15:34:04 +0000 Subject: [PATCH 14/33] bump trace structure for increased hashing --- .../src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp | 3 ++- .../plonk_honk_shared/execution_trace/mega_execution_trace.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp index 5765a9902ddc..6bf11bc07b61 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/mock_kernel_pinning.test.cpp @@ -33,7 +33,8 @@ TEST_F(MockKernelTest, PinFoldingKernelSizes) Builder circuit = circuit_producer.create_next_circuit(ivc); ivc.accumulate(circuit); + EXPECT_FALSE(circuit.blocks.has_overflow); // trace oveflow mechanism should not be triggered } EXPECT_EQ(ivc.fold_output.accumulator->proving_key.log_circuit_size, 19); -} \ No newline at end of file +} diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp index 42b0eb09ec0d..cac4d6cc09ba 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/execution_trace/mega_execution_trace.hpp @@ -294,7 +294,7 @@ static constexpr TraceStructure CLIENT_IVC_BENCH_STRUCTURE{ .ecc_op = 1 << 10, .elliptic = 9000, .aux = 136000, .poseidon2_external = 2500, - .poseidon2_internal = 14000, + .poseidon2_internal = 14500, .overflow = 0 }; /** From c3b151d08331412b5cedcacf71d6bf870bcda893 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 19 Feb 2025 15:56:50 +0000 Subject: [PATCH 15/33] comment and clean merge prover --- .../barretenberg/ultra_honk/merge_prover.cpp | 39 +++++++++---------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index de744eb0068c..6cff7082bbbf 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -21,12 +21,13 @@ MergeProver_::MergeProver_(const std::shared_ptr& op_queue, /** * @brief Prove proper construction of the aggregate Goblin ECC op queue polynomials T^(j), j = 1,2,3,4. - * @details Let T^(j) be the jth column of the aggregate op queue after incorporating the contribution from the - * present circuit. T_prev^(j) corresponds to the aggregate op queue at the previous stage and $t^(j)$ represents - * the contribution from the present circuit only. For each j, we have the relationship T = T_prev + right_shift(t, - * M_{i-1}), where the shift magnitude M_{i-1} is the honest length of T_prev. This protocol demonstrates, assuming the - * length of T_prev is at most M_{i-1}, that the aggregate op queue has been constructed correctly via a simple - * Schwartz-Zippel check. Evaluations are proven via batched KZG. + * @details Let T_j be the jth column of the aggregate ecc op table after prepending the subtable columns t_j containing + * the contribution from the present circuit. T_{j,prev} corresponds to the columns of the aggregate table at the + * previous stage. For each column we have the relationship T_j = t_j + right_shift(T_{j,prev}, k), where k is the + * length of the subtable columns t_j. This protocol demonstrates, assuming the length of t is at most k, that the + * aggregate ecc op table has been constructed correctly via the simple Schwartz-Zippel check: + * + * T_j(\kappa) = t_j(\kappa) + \kappa^k * (T_{j,prev}(\kappa)). * * TODO(#746): Prove connection between t^{shift}, committed to herein, and t, used in the main protocol. See issue * for details (https://github.com/AztecProtocol/barretenberg/issues/746). @@ -37,14 +38,14 @@ template HonkProof MergeProver_::construct_proof() { transcript = std::make_shared(); - // Extract T, T_prev, t + // Extract columns of the full table T_j, the previous table T_{j,prev}, and the current subtable t_j std::array T_current = op_queue->get_ultra_ops_table_columns(); std::array T_prev = op_queue->get_previous_ultra_ops_table_columns(); std::array t_current = op_queue->get_current_subtable_columns(); // TODO(#723): Cannot currently support an empty T_prev. Need to be able to properly handle zero commitment. ASSERT(T_prev[0].size() > 0); - ASSERT(T_current[0].size() > T_prev[0].size()); // Must have some new ops to accumulate otherwise C_t_shift = 0 + ASSERT(T_current[0].size() > T_prev[0].size()); // Must have some new ops to accumulate otherwise [t_j] = 0 const size_t current_table_size = T_current[0].size(); const size_t current_subtable_size = t_current[0].size(); @@ -55,17 +56,17 @@ template HonkProof MergeProver_::construct_proof() // Compute/get commitments [t^{shift}], [T_prev], and [T] and add to transcript for (size_t idx = 0; idx < NUM_WIRES; ++idx) { // Compute commitments - Commitment C_t_current = pcs_commitment_key->commit(t_current[idx]); - Commitment C_T_prev = pcs_commitment_key->commit(T_prev[idx]); - Commitment C_T_current = pcs_commitment_key->commit(T_current[idx]); + Commitment t_commitment = pcs_commitment_key->commit(t_current[idx]); + Commitment T_prev_commitment = pcs_commitment_key->commit(T_prev[idx]); + Commitment T_commitment = pcs_commitment_key->commit(T_current[idx]); std::string suffix = std::to_string(idx); - transcript->send_to_verifier("t_CURRENT_" + suffix, C_t_current); - transcript->send_to_verifier("T_PREV_" + suffix, C_T_prev); - transcript->send_to_verifier("T_CURRENT_" + suffix, C_T_current); + transcript->send_to_verifier("t_CURRENT_" + suffix, t_commitment); + transcript->send_to_verifier("T_PREV_" + suffix, T_prev_commitment); + transcript->send_to_verifier("T_CURRENT_" + suffix, T_commitment); } - // Compute evaluations T(\kappa), T_prev_shift(\kappa), t(\kappa), add to transcript. For each polynomial we add a + // Compute evaluations T_j(\kappa), T_{j,prev}(\kappa), t_j(\kappa), add to transcript. For each polynomial we add a // univariate opening claim {p(X), (\kappa, p(\kappa))} to the set of claims to be checked via batched KZG. FF kappa = transcript->template get_challenge("kappa"); info("kappa: ", kappa); @@ -109,12 +110,8 @@ template HonkProof MergeProver_::construct_proof() info("batched_commitment: ", pcs_commitment_key->commit(batched_polynomial)); // Construct and commit to KZG quotient polynomial q = (f - v) / (X - kappa) - auto quotient = batched_polynomial; - quotient.at(0) -= batched_eval; - quotient.factor_roots(kappa); - - auto quotient_commitment = pcs_commitment_key->commit(quotient); - transcript->send_to_verifier("KZG:W", quotient_commitment); + OpeningClaim batched_claim = { std::move(batched_polynomial), { kappa, batched_eval } }; + PCS::compute_opening_proof(pcs_commitment_key, batched_claim, transcript); return transcript->proof_data; } From da778e879e6af4ccbe6bf74b43b9c2b64687da85 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 19 Feb 2025 17:30:47 +0000 Subject: [PATCH 16/33] WiP cleanup --- .../op_queue/ecc_op_queue.hpp | 49 +++------------ .../op_queue/ecc_op_queue.test.cpp | 6 +- .../op_queue/ecc_ops_table.hpp | 60 +++++++++++++------ .../ultra_honk/mega_honk.test.cpp | 14 ----- 4 files changed, 56 insertions(+), 73 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index 969d71d35f01..66bffc26c610 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -28,16 +28,11 @@ class ECCOpQueue { static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION; - std::vector> fuzzing_raw_ops; - // std::array, 4> ultra_ops; // ops encoded in the width-4 Ultra format - RawEccOpsTable raw_ops_table; UltraEccOpsTable ultra_ops_table; - size_t current_ultra_ops_size = 0; // M_i - size_t previous_ultra_ops_size = 0; // M_{i-1} - - std::array ultra_ops_commitments; + // Storage for the reconstructed raw ops table in contiguous memory + std::vector> raw_ops_reconstructed; // Tracks numer of muls and size of eccvm in real time as the op queue is updated EccvmRowTracker eccvm_row_tracker; @@ -53,45 +48,22 @@ class ECCOpQueue { std::array, 4> get_ultra_ops_table_columns() const { - const size_t table_size = ultra_ops_table.ultra_table_size(); - std::array, 4> column_polynomials; - std::array, 4> column_spans; - for (auto [column_span, column] : zip_view(column_spans, column_polynomials)) { - column = Polynomial(table_size); - column_span = column.coeffs(); - } - ultra_ops_table.populate_table_columns(column_spans); - return column_polynomials; + return ultra_ops_table.construct_table_columns(); } std::array, 4> get_previous_ultra_ops_table_columns() const { - const size_t table_size = ultra_ops_table.ultra_table_size(); - const size_t current_subtable_size = ultra_ops_table.current_ultra_subtable_size(); - const size_t previous_table_size = table_size - current_subtable_size; - std::array, 4> column_polynomials; - std::array, 4> column_spans; - for (auto [column_span, column] : zip_view(column_spans, column_polynomials)) { - column = Polynomial(previous_table_size, table_size); - column_span = column.coeffs(); - } - ultra_ops_table.populate_previous_table_columns(column_spans); - return column_polynomials; + return ultra_ops_table.construct_previous_table_columns(); } std::array, 4> get_current_subtable_columns() const { - const size_t current_subtable_size = ultra_ops_table.current_ultra_subtable_size(); - std::array, 4> column_polynomials; - std::array, 4> column_spans; - for (auto [column_span, column] : zip_view(column_spans, column_polynomials)) { - column = Polynomial(current_subtable_size); - column_span = column.coeffs(); - } - ultra_ops_table.populate_current_subtable_columns(column_spans); - return column_polynomials; + return ultra_ops_table.construct_current_subtable_columns(); } + // Reconstruct the full table of raw ops in contiguous memory from the independent subtables + void construct_full_raw_ops_table() { raw_ops_reconstructed = raw_ops_table.get_reconstructed(); } + size_t get_ultra_ops_table_size() const { return ultra_ops_table.ultra_table_size(); } size_t get_current_ultra_ops_subtable_size() const { return ultra_ops_table.current_ultra_subtable_size(); } @@ -129,7 +101,7 @@ class ECCOpQueue { * @brief A fuzzing only method for setting raw ops directly * */ - void set_raw_ops_for_fuzzing(std::vector& raw_ops_in) { fuzzing_raw_ops = raw_ops_in; } + void set_raw_ops_for_fuzzing(std::vector& raw_ops_in) { raw_ops_reconstructed = raw_ops_in; } /** * @brief A testing only method that adds an erroneous equality op to the raw ops @@ -150,9 +122,6 @@ class ECCOpQueue { Point get_accumulator() { return accumulator; } - void set_commitment_data(std::array& commitments) { ultra_ops_commitments = commitments; } - const auto& get_ultra_ops_commitments() { return ultra_ops_commitments; } - /** * @brief Write point addition op to queue and natively perform addition * diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index 9d88be6397fb..fb6c3b057ca0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -6,10 +6,11 @@ using namespace bb; TEST(ECCOpQueueTest, Basic) { ECCOpQueue op_queue; - const auto raw_ops = op_queue.get_raw_ops(); + op_queue.initialize_new_subtable(); op_queue.add_accumulate(bb::g1::affine_one); - EXPECT_EQ(raw_ops[0].base_point, bb::g1::affine_one); op_queue.empty_row_for_testing(); + const auto raw_ops = op_queue.get_raw_ops(); + EXPECT_EQ(raw_ops[0].base_point, bb::g1::affine_one); EXPECT_EQ(raw_ops[1].add, false); } @@ -26,6 +27,7 @@ TEST(ECCOpQueueTest, InternalAccumulatorCorrectness) // Add the same operations to the ECC op queue; the native computation is performed under the hood. ECCOpQueue op_queue; + op_queue.initialize_new_subtable(); op_queue.add_accumulate(P1); op_queue.mul_accumulate(P2, z); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index e538ba2cc7fd..3f9c3e42adca 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -2,6 +2,7 @@ #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/eccvm/eccvm_builder_types.hpp" +#include "barretenberg/polynomials/polynomial.hpp" #include namespace bb { @@ -43,6 +44,8 @@ template class EccOpsTable { return total; } + size_t num_subtables() const { return table.size(); } + auto& get() const { return table; } void push(const OpFormat& op) { table.front().push_back(op); } @@ -105,6 +108,7 @@ class UltraEccOpsTable { using Fr = Curve::ScalarField; using UltraOpsTable = EccOpsTable; using TableView = std::array, TABLE_WIDTH>; + using ColumnPolynomials = std::array, TABLE_WIDTH>; UltraOpsTable table; @@ -112,6 +116,7 @@ class UltraEccOpsTable { size_t size() const { return table.size(); } size_t ultra_table_size() const { return table.size() * NUM_ROWS_PER_OP; } size_t current_ultra_subtable_size() const { return table.get()[0].size() * NUM_ROWS_PER_OP; } + size_t previous_ultra_table_size() const { return (ultra_table_size() - current_ultra_subtable_size()); } void create_new_subtable(size_t size_hint = 0) { table.create_new_subtable(size_hint); } void push(const UltraOp& op) { table.push(op); } @@ -139,7 +144,7 @@ class UltraEccOpsTable { } } - void populate_column_data_from_subtables(std::array, TABLE_WIDTH>& target_columns, + void populate_column_data_from_subtables(ColumnPolynomials& column_polynomials, const size_t start_idx, const size_t end_idx) const { @@ -147,39 +152,60 @@ class UltraEccOpsTable { for (size_t j = start_idx; j < end_idx; ++j) { const auto& subtable = table.get()[j]; for (const auto& op : subtable) { - target_columns[0][i] = op.op; - target_columns[1][i] = op.x_lo; - target_columns[2][i] = op.x_hi; - target_columns[3][i] = op.y_lo; + column_polynomials[0].at(i) = op.op; + column_polynomials[1].at(i) = op.x_lo; + column_polynomials[2].at(i) = op.x_hi; + column_polynomials[3].at(i) = op.y_lo; i++; - target_columns[0][i] = 0; // only the first 'op' field is utilized - target_columns[1][i] = op.y_hi; - target_columns[2][i] = op.z_1; - target_columns[3][i] = op.z_2; + column_polynomials[0].at(i) = 0; // only the first 'op' field is utilized + column_polynomials[1].at(i) = op.y_hi; + column_polynomials[2].at(i) = op.z_1; + column_polynomials[3].at(i) = op.z_2; i++; } } } - void populate_table_columns(TableView& target_columns) const + ColumnPolynomials construct_table_columns() const { + ColumnPolynomials column_polynomials; + for (auto& poly : column_polynomials) { + poly = Polynomial(ultra_table_size()); + } + const size_t start_idx = 0; - const size_t end_idx = table.get().size(); - populate_column_data_from_subtables(target_columns, start_idx, end_idx); + const size_t end_idx = table.num_subtables(); + populate_column_data_from_subtables(column_polynomials, start_idx, end_idx); + + return column_polynomials; } - void populate_previous_table_columns(TableView& target_columns) const + ColumnPolynomials construct_previous_table_columns() const { + ColumnPolynomials column_polynomials; + for (auto& poly : column_polynomials) { + poly = Polynomial(previous_ultra_table_size()); + } + const size_t start_idx = 1; - const size_t end_idx = table.get().size(); - populate_column_data_from_subtables(target_columns, start_idx, end_idx); + const size_t end_idx = table.num_subtables(); + populate_column_data_from_subtables(column_polynomials, start_idx, end_idx); + + return column_polynomials; } - void populate_current_subtable_columns(TableView& target_columns) const + ColumnPolynomials construct_current_subtable_columns() const { + ColumnPolynomials column_polynomials; + for (auto& poly : column_polynomials) { + poly = Polynomial(current_ultra_subtable_size()); + } + const size_t start_idx = 0; const size_t end_idx = 1; - populate_column_data_from_subtables(target_columns, start_idx, end_idx); + populate_column_data_from_subtables(column_polynomials, start_idx, end_idx); + + return column_polynomials; } }; diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 649bde6c55c8..b9cfdbd02aa6 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -266,25 +266,11 @@ TYPED_TEST(MegaHonkTests, NewMergePolyconstruction) auto builder = typename Flavor::CircuitBuilder{ op_queue }; GoblinMockCircuits::construct_simple_circuit(builder); - const size_t expected_table_size = op_queue->get_ultra_ops_table_size(); - - // EXPECT_EQ(op_queue->get_current_size(), expected_table_size); - std::array, 4> table_polynomials = op_queue->get_ultra_ops_table_columns(); std::array, 4> previous_table_polynomials = op_queue->get_previous_ultra_ops_table_columns(); std::array, 4> subtable_polynomials = op_queue->get_current_subtable_columns(); const size_t current_subtable_size = op_queue->get_current_ultra_ops_subtable_size(); - std::array, 4> reconstructed_table_polynomials; - for (size_t i = 0; i < 4; ++i) { - reconstructed_table_polynomials[i] = Polynomial(expected_table_size); - reconstructed_table_polynomials[i] += subtable_polynomials[i]; - reconstructed_table_polynomials[i] += previous_table_polynomials[i].right_shifted(current_subtable_size); - } - - for (auto [reconstructed, table] : zip_view(reconstructed_table_polynomials, table_polynomials)) { - EXPECT_EQ(reconstructed, table); - } Fr eval_challenge = Fr::random_element(); From 1cd8f635b3f24e8a94b60fb3632781ad67bbf6f0 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 19 Feb 2025 19:43:37 +0000 Subject: [PATCH 17/33] compute raw ops once and for all --- .../cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp | 2 +- barretenberg/cpp/src/barretenberg/goblin/goblin.hpp | 2 +- .../stdlib_circuit_builders/op_queue/ecc_op_queue.hpp | 8 +++++++- .../op_queue/ecc_op_queue.test.cpp | 2 +- .../translator_vm/translator_circuit_builder.cpp | 2 +- .../translator_vm/translator_circuit_builder.fuzzer.cpp | 2 +- .../translator_vm/translator_circuit_builder.test.cpp | 2 +- 7 files changed, 13 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp index fcfadd09d8cf..7d472685f165 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp @@ -113,7 +113,7 @@ class ECCVMCircuitBuilder { std::vector> msm_mul_index; std::vector msm_sizes; - const auto raw_ops = op_queue->get_raw_ops(); + const auto& raw_ops = op_queue->get_raw_ops(); size_t op_idx = 0; // populate opqueue and mul indices for (const auto& op : raw_ops) { diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index 872b168f9605..e7e89185d583 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -309,4 +309,4 @@ class GoblinVerifier { return merge_verified && eccvm_verified && accumulator_construction_verified && translation_verified; }; }; -} // namespace bb \ No newline at end of file +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index 66bffc26c610..b8b9ad826fcc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -67,7 +67,13 @@ class ECCOpQueue { size_t get_ultra_ops_table_size() const { return ultra_ops_table.ultra_table_size(); } size_t get_current_ultra_ops_subtable_size() const { return ultra_ops_table.current_ultra_subtable_size(); } - std::vector get_raw_ops() { return raw_ops_table.get_reconstructed(); } + std::vector& get_raw_ops() + { + if (raw_ops_reconstructed.empty()) { + construct_full_raw_ops_table(); + } + return raw_ops_reconstructed; + } /** * @brief Get the number of rows in the 'msm' column section, for all msms in the circuit diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index fb6c3b057ca0..8e11f9b78ffd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -9,7 +9,7 @@ TEST(ECCOpQueueTest, Basic) op_queue.initialize_new_subtable(); op_queue.add_accumulate(bb::g1::affine_one); op_queue.empty_row_for_testing(); - const auto raw_ops = op_queue.get_raw_ops(); + const auto& raw_ops = op_queue.get_raw_ops(); EXPECT_EQ(raw_ops[0].base_point, bb::g1::affine_one); EXPECT_EQ(raw_ops[1].add, false); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index ee5516a38f3d..ba66e1311284 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -591,7 +591,7 @@ TranslatorCircuitBuilder::AccumulationInput TranslatorCircuitBuilder::compute_wi void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ptr ecc_op_queue) { using Fq = bb::fq; - const auto raw_ops = ecc_op_queue->get_raw_ops(); + const auto& raw_ops = ecc_op_queue->get_raw_ops(); std::vector accumulator_trace; Fq current_accumulator(0); if (raw_ops.empty()) { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp index 864221003f14..6b558421b2b0 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp @@ -23,7 +23,7 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) auto z_1_accumulator = Fq(0); auto z_2_accumulator = Fq(0); // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - const auto raw_ops = op_queue->get_raw_ops(); + const auto& raw_ops = op_queue->get_raw_ops(); for (const auto& ecc_op : raw_ops) { op_accumulator = op_accumulator * x_inv + ecc_op.get_opcode_value(); p_x_accumulator = p_x_accumulator * x_inv + ecc_op.base_point.x; diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index f78c12e1e435..3589a8bb0c25 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -105,7 +105,7 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) // Get an inverse Fq x_inv = x.invert(); // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - const auto raw_ops = op_queue->get_raw_ops(); + const auto& raw_ops = op_queue->get_raw_ops(); for (const auto& ecc_op : raw_ops) { op_accumulator = op_accumulator * x_inv + ecc_op.get_opcode_value(); const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); From 19327e0518f3d512722c9b974f0510cf6250ce30 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 18:36:45 +0000 Subject: [PATCH 18/33] simplify table poly constrcution --- .../op_queue/ecc_ops_table.hpp | 73 ++++++------------- .../op_queue/ecc_ops_table.test.cpp | 11 +-- 2 files changed, 24 insertions(+), 60 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index 3f9c3e42adca..273519b73e17 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -121,36 +121,23 @@ class UltraEccOpsTable { void push(const UltraOp& op) { table.push(op); } /** - * @brief Populate the provided array of columns with the width-4 representation of the table data + * @brief Construct polynomials corresponding to the columns of the reconstructed ultra ops table for the given + * range of subtables * @todo multithreaded this functionality * @param target_columns */ - void populate_column_data(std::array, TABLE_WIDTH>& target_columns) const + ColumnPolynomials construct_column_polynomials_from_subtables(const size_t poly_size, + const size_t subtable_start_idx, + const size_t subtable_end_idx) const { - size_t i = 0; - for (const auto& subtable : table.get()) { - for (const auto& op : subtable) { - target_columns[0][i] = op.op; - target_columns[1][i] = op.x_lo; - target_columns[2][i] = op.x_hi; - target_columns[3][i] = op.y_lo; - i++; - target_columns[0][i] = 0; // only the first 'op' field is utilized - target_columns[1][i] = op.y_hi; - target_columns[2][i] = op.z_1; - target_columns[3][i] = op.z_2; - i++; - } + ColumnPolynomials column_polynomials; + for (auto& poly : column_polynomials) { + poly = Polynomial(poly_size); } - } - void populate_column_data_from_subtables(ColumnPolynomials& column_polynomials, - const size_t start_idx, - const size_t end_idx) const - { size_t i = 0; - for (size_t j = start_idx; j < end_idx; ++j) { - const auto& subtable = table.get()[j]; + for (size_t subtable_idx = subtable_start_idx; subtable_idx < subtable_end_idx; ++subtable_idx) { + const auto& subtable = table.get()[subtable_idx]; for (const auto& op : subtable) { column_polynomials[0].at(i) = op.op; column_polynomials[1].at(i) = op.x_lo; @@ -164,48 +151,34 @@ class UltraEccOpsTable { i++; } } + return column_polynomials; } ColumnPolynomials construct_table_columns() const { - ColumnPolynomials column_polynomials; - for (auto& poly : column_polynomials) { - poly = Polynomial(ultra_table_size()); - } + const size_t poly_size = ultra_table_size(); + const size_t subtable_start_idx = 0; + const size_t subtable_end_idx = table.num_subtables(); - const size_t start_idx = 0; - const size_t end_idx = table.num_subtables(); - populate_column_data_from_subtables(column_polynomials, start_idx, end_idx); - - return column_polynomials; + return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); } ColumnPolynomials construct_previous_table_columns() const { - ColumnPolynomials column_polynomials; - for (auto& poly : column_polynomials) { - poly = Polynomial(previous_ultra_table_size()); - } - - const size_t start_idx = 1; - const size_t end_idx = table.num_subtables(); - populate_column_data_from_subtables(column_polynomials, start_idx, end_idx); + const size_t poly_size = previous_ultra_table_size(); + const size_t subtable_start_idx = 1; + const size_t subtable_end_idx = table.num_subtables(); - return column_polynomials; + return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); } ColumnPolynomials construct_current_subtable_columns() const { - ColumnPolynomials column_polynomials; - for (auto& poly : column_polynomials) { - poly = Polynomial(current_ultra_subtable_size()); - } - - const size_t start_idx = 0; - const size_t end_idx = 1; - populate_column_data_from_subtables(column_polynomials, start_idx, end_idx); + const size_t poly_size = current_ultra_subtable_size(); + const size_t subtable_start_idx = 0; + const size_t subtable_end_idx = 1; - return column_polynomials; + return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); } }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp index f3257d1bee07..3d6369ac01ba 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp @@ -88,8 +88,6 @@ TEST(EccOpsTableTest, UltraOpsTable) { using Fr = fr; - constexpr size_t NUM_ROWS_PER_OP = 2; // Each ECC op is represented by two rows in the ultra ops table - // Construct sets of ultra ops, each representing those added by a single circuit const size_t NUM_SUBTABLES = 3; std::array, NUM_SUBTABLES> subtable_ultra_ops; @@ -117,14 +115,7 @@ TEST(EccOpsTableTest, UltraOpsTable) EXPECT_EQ(ultra_ops_table.size(), expected_num_ops); // Construct polynomials corresponding to the columns of the ultra ops table - const size_t expected_table_size = expected_num_ops * NUM_ROWS_PER_OP; - std::array, 4> ultra_ops_table_polynomials; - std::array, 4> column_spans; - for (auto [column_span, column] : zip_view(column_spans, ultra_ops_table_polynomials)) { - column = Polynomial(expected_table_size); - column_span = column.coeffs(); - } - ultra_ops_table.populate_column_data(column_spans); + std::array, 4> ultra_ops_table_polynomials = ultra_ops_table.construct_table_columns(); // Check that the ultra ops table constructed by the op queue matches the expected table for (auto [expected_column, poly] : zip_view(expected_ultra_ops_table.columns, ultra_ops_table_polynomials)) { From 0785f90cf8800497271ab3b8c3a617eeebabe266 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 19:44:35 +0000 Subject: [PATCH 19/33] test to ensure mock merge proof is correctly sized --- .../cpp/src/barretenberg/constants.hpp | 4 +++- .../acir_format/ivc_recursion_constraint.cpp | 4 +++- .../ivc_recursion_constraint.test.cpp | 9 +++++++ .../mega_circuit_builder.hpp | 1 + .../ultra_honk/mega_honk.test.cpp | 24 +++++++++++++++++++ 5 files changed, 40 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/constants.hpp b/barretenberg/cpp/src/barretenberg/constants.hpp index 53f097b30c4d..8ef4e4707240 100644 --- a/barretenberg/cpp/src/barretenberg/constants.hpp +++ b/barretenberg/cpp/src/barretenberg/constants.hpp @@ -24,4 +24,6 @@ static constexpr uint32_t MASKING_OFFSET = 4; // For ZK Flavors: the number of the commitments required by Libra and SmallSubgroupIPA. static constexpr uint32_t NUM_LIBRA_COMMITMENTS = 3; static constexpr uint32_t NUM_LIBRA_EVALUATIONS = 4; -} // namespace bb \ No newline at end of file + +static constexpr uint32_t MERGE_PROOF_SIZE = 65; // used to ensure mock proofs are generated correctly +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp index a1a6fd057bb9..4d77b3fbce11 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.cpp @@ -236,12 +236,12 @@ std::shared_ptr create_mock_decider_vk() * * @return ClientIVC::MergeProof */ -// WORKTODO: Make sure there is a test to check that this produces a correctly sized mock merge proof ClientIVC::MergeProof create_dummy_merge_proof() { using FF = ClientIVC::FF; std::vector proof; + proof.reserve(MERGE_PROOF_SIZE); FF mock_val(5); auto mock_commitment = curve::BN254::AffineElement::one(); @@ -269,6 +269,8 @@ ClientIVC::MergeProof create_dummy_merge_proof() proof.emplace_back(val); } + ASSERT(proof.size() == MERGE_PROOF_SIZE); + return proof; } diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp index 78a75d6c2391..5c14bc33dd93 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/ivc_recursion_constraint.test.cpp @@ -136,6 +136,15 @@ class IvcRecursionConstraintTest : public ::testing::Test { } }; +/** + * @brief Check that the size of a mock merge proof matches expectation + */ +TEST_F(IvcRecursionConstraintTest, MockMergeProofSize) +{ + ClientIVC::MergeProof merge_proof = create_dummy_merge_proof(); + EXPECT_EQ(merge_proof.size(), MERGE_PROOF_SIZE); +} + /** * @brief Test IVC accumulation of a one app and one kernel; The kernel includes a recursive oink verification for the * app, specified via an ACIR RecursionConstraint. diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp index 53d8f2f6581e..ebe2588bf2e5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp @@ -56,6 +56,7 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_ op_queue_in) : MegaCircuitBuilder_(0, op_queue_in) {} diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index b9cfdbd02aa6..3d04b1324395 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -89,6 +89,30 @@ template class MegaHonkTests : public ::testing::Test { TYPED_TEST_SUITE(MegaHonkTests, FlavorTypes); +/** + * @brief Check that size of a merge proof matches the corresponding constant + * @details This is useful for ensuring correct construction of mock merge proofs + * + */ +TYPED_TEST(MegaHonkTests, MergeProofSizeCheck) +{ + using Flavor = TypeParam; + using MergeProver = MergeProver_; + + // Constuct an op queue and populate it with some arbitrary ops + auto op_queue = std::make_shared(); + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); + + auto builder = typename Flavor::CircuitBuilder{ op_queue }; + GoblinMockCircuits::construct_simple_circuit(builder); + + // Construct a merge proof and ensure its size matches expectation; if not, the constant may need to be updated + MergeProver merge_prover{ op_queue }; + auto merge_proof = merge_prover.construct_proof(); + + EXPECT_EQ(merge_proof.size(), MERGE_PROOF_SIZE); +} + /** * @brief Test proof construction/verification for a circuit with ECC op gates, public inputs, and basic arithmetic * gates From 9b9a5fb3e9da2304d3fb6dfd2bb4ba9cc02297a2 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 20:22:49 +0000 Subject: [PATCH 20/33] move column poly constructon test to op queue suite --- .../src/barretenberg/goblin/mock_circuits.hpp | 20 +---- .../op_queue/ecc_op_queue.test.cpp | 81 +++++++++++++++++-- .../ultra_honk/mega_honk.test.cpp | 41 ---------- 3 files changed, 76 insertions(+), 66 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp index 2b29d8caa72d..4964a6d73372 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/mock_circuits.hpp @@ -138,9 +138,7 @@ class GoblinMockCircuits { * * @param op_queue */ - static void perform_op_queue_interactions_for_mock_first_circuit( - std::shared_ptr& op_queue, - [[maybe_unused]] std::shared_ptr commitment_key = nullptr) + static void perform_op_queue_interactions_for_mock_first_circuit(std::shared_ptr& op_queue) { PROFILE_THIS(); @@ -148,22 +146,6 @@ class GoblinMockCircuits { // Add some goblinized ecc ops MockCircuits::construct_goblin_ecc_op_circuit(builder); - - // Manually compute the op queue transcript commitments (which would normally be done by the merge prover) -#ifndef __wasm__ - // TODO(Adam): This is crashing wasm-in-browser. It doesn't make sense to call this in browser... - bb::srs::init_crs_factory(bb::srs::get_ignition_crs_path()); -#endif - // WORKTODO: may want to reinstate something analogous to this in the future - // auto bn254_commitment_key = - // commitment_key ? commitment_key : std::make_shared(op_queue->get_ultra_ops_table_size()); - // std::array op_queue_commitments; - // size_t idx = 0; - // for (auto& entry : op_queue->get_aggregate_transcript()) { - // op_queue_commitments[idx++] = bn254_commitment_key->commit({ 0, entry }); - // } - // // Store the commitment data for use by the prover of the next circuit - // op_queue->set_commitment_data(op_queue_commitments); } /** diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index 8e11f9b78ffd..5ebfaa473b9a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -3,26 +3,48 @@ using namespace bb; +class ECCOpQueueTest { + public: + using Curve = curve::BN254; + using G1 = Curve::AffineElement; + using Fr = Curve::ScalarField; + + // Perform some basic interactions with the ECC op queue to mock the behavior of a single circuit + static void populate_an_arbitrary_subtable_of_ops(const std::shared_ptr& op_queue) + { + auto P1 = G1::random_element(); + auto P2 = G1::random_element(); + auto z = Fr::random_element(); + + op_queue->initialize_new_subtable(); + op_queue->add_accumulate(P1); + op_queue->mul_accumulate(P2, z); + op_queue->eq_and_reset(); + } +}; + TEST(ECCOpQueueTest, Basic) { + using G1 = ECCOpQueueTest::G1; + ECCOpQueue op_queue; op_queue.initialize_new_subtable(); op_queue.add_accumulate(bb::g1::affine_one); op_queue.empty_row_for_testing(); const auto& raw_ops = op_queue.get_raw_ops(); - EXPECT_EQ(raw_ops[0].base_point, bb::g1::affine_one); + EXPECT_EQ(raw_ops[0].base_point, G1::one()); EXPECT_EQ(raw_ops[1].add, false); } TEST(ECCOpQueueTest, InternalAccumulatorCorrectness) { - using point = g1::affine_element; - using scalar = fr; + using G1 = ECCOpQueueTest::G1; + using Fr = ECCOpQueueTest::Fr; // Compute a simple point accumulation natively - auto P1 = point::random_element(); - auto P2 = point::random_element(); - auto z = scalar::random_element(); + auto P1 = G1::random_element(); + auto P2 = G1::random_element(); + auto z = Fr::random_element(); auto P_expected = P1 + P2 * z; // Add the same operations to the ECC op queue; the native computation is performed under the hood. @@ -38,3 +60,50 @@ TEST(ECCOpQueueTest, InternalAccumulatorCorrectness) op_queue.eq_and_reset(); EXPECT_TRUE(op_queue.get_accumulator().is_point_at_infinity()); } + +// Check that the ECC op queue correctly constructs the table column polynomials for the full table, the previous table, +// and the current subtable via successive prepending of subtables +TEST(ECCOpQueueTest, ColumnPolynomialConstruction) +{ + using Fr = fr; + + // Instantiate and EccOpQueue and populate it with several subtables of ECC ops + auto op_queue = std::make_shared(); + + const size_t NUM_SUBTABLES = 5; + for (size_t i = 0; i < NUM_SUBTABLES; ++i) { + ECCOpQueueTest::populate_an_arbitrary_subtable_of_ops(op_queue); + } + + // Construct column polynomials corresponding to the full table (T), the previous table (T_prev), and the current + // subtable (t_current) + std::array, 4> table_polynomials = op_queue->get_ultra_ops_table_columns(); + std::array, 4> previous_table_polynomials = op_queue->get_previous_ultra_ops_table_columns(); + std::array, 4> subtable_polynomials = op_queue->get_current_subtable_columns(); + + // Check that the table polynomials are constructed correctly by checking the following identity at a single point: + // T(x) = t_current(x) + x^k * T_prev(x), where k is the size of the current subtable + const size_t current_subtable_size = op_queue->get_current_ultra_ops_subtable_size(); + + Fr eval_challenge = Fr::random_element(); + + std::array table_evals; + std::array shifted_previous_table_evals; + std::array subtable_evals; + for (auto [eval, poly] : zip_view(table_evals, table_polynomials)) { + eval = poly.evaluate(eval_challenge); // T(x) + } + for (auto [eval, poly] : zip_view(shifted_previous_table_evals, previous_table_polynomials)) { + eval = poly.evaluate(eval_challenge); + eval *= eval_challenge.pow(current_subtable_size); // x^k * T_prev(x) + } + for (auto [eval, poly] : zip_view(subtable_evals, subtable_polynomials)) { + eval = poly.evaluate(eval_challenge); // t_current(x) + } + + // Check T(x) = t_current(x) + x^k * T_prev(x) + for (auto [table_eval, shifted_previous_table_eval, subtable_eval] : + zip_view(table_evals, shifted_previous_table_evals, subtable_evals)) { + EXPECT_EQ(table_eval, subtable_eval + shifted_previous_table_eval); + } +} diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index 3d04b1324395..c2b59479425d 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -277,47 +277,6 @@ TYPED_TEST(MegaHonkTests, MultipleCircuitsMergeOnly) } } -// WORKTODO: move to op queue test suite? -TYPED_TEST(MegaHonkTests, NewMergePolyconstruction) -{ - using Flavor = TypeParam; - using Fr = typename Flavor::Curve::ScalarField; - // Instantiate EccOpQueue. This will be shared across all circuits in the series - auto op_queue = std::make_shared(); - - GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); - - auto builder = typename Flavor::CircuitBuilder{ op_queue }; - GoblinMockCircuits::construct_simple_circuit(builder); - - std::array, 4> table_polynomials = op_queue->get_ultra_ops_table_columns(); - std::array, 4> previous_table_polynomials = op_queue->get_previous_ultra_ops_table_columns(); - std::array, 4> subtable_polynomials = op_queue->get_current_subtable_columns(); - - const size_t current_subtable_size = op_queue->get_current_ultra_ops_subtable_size(); - - Fr eval_challenge = Fr::random_element(); - - std::array table_evals; - std::array shifted_previous_table_evals; - std::array subtable_evals; - for (auto [eval, poly] : zip_view(table_evals, table_polynomials)) { - eval = poly.evaluate(eval_challenge); - } - for (auto [eval, poly] : zip_view(shifted_previous_table_evals, previous_table_polynomials)) { - eval = poly.evaluate(eval_challenge); - eval *= eval_challenge.pow(current_subtable_size); - } - for (auto [eval, poly] : zip_view(subtable_evals, subtable_polynomials)) { - eval = poly.evaluate(eval_challenge); - } - - for (auto [table_eval, shifted_previous_table_eval, subtable_eval] : - zip_view(table_evals, shifted_previous_table_evals, subtable_evals)) { - EXPECT_EQ(table_eval, subtable_eval + shifted_previous_table_eval); - } -} - /** * @brief Test Honk proof construction/verification for multiple circuits with ECC op gates, public inputs, and * basic arithmetic gates From 39891d56bfca6603e71d932d9bb533f70e5fe451 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 20:43:20 +0000 Subject: [PATCH 21/33] cleanup comments in merge prover verifier --- .../merge_recursive_verifier.cpp | 22 +++++++++----- .../barretenberg/ultra_honk/merge_prover.cpp | 12 ++------ .../ultra_honk/merge_verifier.cpp | 30 ++++++++----------- 3 files changed, 29 insertions(+), 35 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp index f374a2ba9733..d453465dabe5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp @@ -8,9 +8,17 @@ MergeRecursiveVerifier_::MergeRecursiveVerifier_(CircuitBuilder* {} /** - * @brief Construct recursive verifier for Goblin Merge protocol, up to but not including the pairing + * @brief Reduce verification of proper construction of the aggregate Goblin ECC op queue polynomials T_j, j = 1,2,3,4 + * to a set of inputs to a pairing check. + * @details Let T_j be the jth column of the aggregate ecc op table after prepending the subtable columns t_j containing + * the contribution from the present circuit. T_{j,prev} corresponds to the columns of the aggregate table at the + * previous stage. For each column we have the relationship T_j = t_j + right_shift(T_{j,prev}, k), where k is the + * length of the subtable columns t_j. This protocol demonstrates, assuming the length of t is at most k, that the + * aggregate ecc op table has been constructed correctly via the simple Schwartz-Zippel check: * - * @tparam Flavor + * T_j(\kappa) = t_j(\kappa) + \kappa^k * (T_{j,prev}(\kappa)). + * + * @tparam CircuitBuilder * @param proof * @return std::array Inputs to final pairing */ @@ -18,13 +26,13 @@ template std::array::Element, 2> MergeRecursiveVerifier_::verify_proof( const HonkProof& proof) { - // transform it into stdlib proof + // Transform proof into a stdlib object StdlibProof stdlib_proof = bb::convert_native_proof_to_stdlib(builder, proof); transcript = std::make_shared(stdlib_proof); FF subtable_size = transcript->template receive_from_prover("subtable_size"); - // Receive commitments [t], [T_prev], and [T] + // Receive table column polynomial commitments [t_j], [T_{j,prev}], and [T_j], j = 1,2,3,4 std::array C_t; std::array C_T_prev; std::array C_T; @@ -36,7 +44,7 @@ std::array::Element, 2> MergeRecursiveVerifier_template get_challenge("kappa"); - // Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]} + // Receive evaluations t_j(\kappa), T_{j,prev}(\kappa), T_j(\kappa), j = 1,2,3,4 std::array t_evals; std::array T_prev_evals; std::array T_current_evals; @@ -55,7 +63,7 @@ std::array::Element, 2> MergeRecursiveVerifier_::Element, 2> MergeRecursiveVerifier_template get_challenge("alpha"); - // Constuct batched commitment and batched evaluation from constituents using batching challenge \alpha + // Constuct inputs to batched commitment and batched evaluation from constituents using batching challenge \alpha std::vector scalars; std::vector commitments; scalars.emplace_back(FF(builder, 1)); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 6cff7082bbbf..9ee454fd7112 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -5,8 +5,7 @@ namespace bb { /** * @brief Create MergeProver - * @details We require an SRS at least as large as the current op queue size in order to commit to the shifted - * per-circuit contribution t^{shift} + * @details We require an SRS at least as large as the current ultra ecc ops table * */ template @@ -20,7 +19,7 @@ MergeProver_::MergeProver_(const std::shared_ptr& op_queue, } /** - * @brief Prove proper construction of the aggregate Goblin ECC op queue polynomials T^(j), j = 1,2,3,4. + * @brief Prove proper construction of the aggregate Goblin ECC op queue polynomials T_j, j = 1,2,3,4. * @details Let T_j be the jth column of the aggregate ecc op table after prepending the subtable columns t_j containing * the contribution from the present circuit. T_{j,prev} corresponds to the columns of the aggregate table at the * previous stage. For each column we have the relationship T_j = t_j + right_shift(T_{j,prev}, k), where k is the @@ -51,7 +50,6 @@ template HonkProof MergeProver_::construct_proof() const size_t current_subtable_size = t_current[0].size(); transcript->send_to_verifier("subtable_size", static_cast(current_subtable_size)); - info("subtable_size: ", current_subtable_size); // Compute/get commitments [t^{shift}], [T_prev], and [T] and add to transcript for (size_t idx = 0; idx < NUM_WIRES; ++idx) { @@ -69,7 +67,6 @@ template HonkProof MergeProver_::construct_proof() // Compute evaluations T_j(\kappa), T_{j,prev}(\kappa), t_j(\kappa), add to transcript. For each polynomial we add a // univariate opening claim {p(X), (\kappa, p(\kappa))} to the set of claims to be checked via batched KZG. FF kappa = transcript->template get_challenge("kappa"); - info("kappa: ", kappa); // Add univariate opening claims for each polynomial. std::vector opening_claims; @@ -93,7 +90,6 @@ template HonkProof MergeProver_::construct_proof() } FF alpha = transcript->template get_challenge("alpha"); - info("alpha: ", alpha); // Construct batched polynomial to opened via KZG Polynomial batched_polynomial(current_table_size); @@ -105,10 +101,6 @@ template HonkProof MergeProver_::construct_proof() alpha_pow *= alpha; } - info("Prover: batched_eval: ", batched_eval); - info("reconstructed batched_eval: ", batched_polynomial.evaluate(kappa)); - info("batched_commitment: ", pcs_commitment_key->commit(batched_polynomial)); - // Construct and commit to KZG quotient polynomial q = (f - v) / (X - kappa) OpeningClaim batched_claim = { std::move(batched_polynomial), { kappa, batched_eval } }; PCS::compute_opening_proof(pcs_commitment_key, batched_claim, transcript); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp index 6799a1ac0266..1d636abf30c3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp @@ -10,25 +10,25 @@ MergeVerifier_::MergeVerifier_() , pcs_verification_key(std::make_unique()){}; /** - * @brief Verify proper construction of the aggregate Goblin ECC op queue polynomials T_i^(j), j = 1,2,3,4. - * @details Let T_i^(j) be the jth column of the aggregate op queue after incorporating the contribution from the - * present circuit. T_{i-1}^(j) corresponds to the aggregate op queue at the previous stage and $t_i^(j)$ represents - * the contribution from the present circuit only. For each j, we have the relationship T_i = T_{i-1} + right_shift(t_i, - * M_{i-1}), where the shift magnitude M_{i-1} is the honest length of T_{i-1}. This protocol verfies, assuming the - * length of T_{i-1} is at most M_{i-1}, that the aggregate op queue has been constructed correctly via a simple - * Schwartz-Zippel check. Evaluations are checked via batched KZG. + * @brief Verify proper construction of the aggregate Goblin ECC op queue polynomials T_j, j = 1,2,3,4. + * @details Let T_j be the jth column of the aggregate ecc op table after prepending the subtable columns t_j containing + * the contribution from the present circuit. T_{j,prev} corresponds to the columns of the aggregate table at the + * previous stage. For each column we have the relationship T_j = t_j + right_shift(T_{j,prev}, k), where k is the + * length of the subtable columns t_j. This protocol demonstrates, assuming the length of t is at most k, that the + * aggregate ecc op table has been constructed correctly via the simple Schwartz-Zippel check: + * + * T_j(\kappa) = t_j(\kappa) + \kappa^k * (T_{j,prev}(\kappa)). * * @tparam Flavor - * @return bool + * @return bool Verification result */ template bool MergeVerifier_::verify_proof(const HonkProof& proof) { transcript = std::make_shared(proof); uint32_t subtable_size = transcript->template receive_from_prover("subtable_size"); - info("subtable_size: ", subtable_size); - // Receive commitments [t_i^{shift}], [T_{i-1}], and [T_i] + // Receive table column polynomial commitments [t_j], [T_{j,prev}], and [T_j], j = 1,2,3,4 std::array t_commitments; std::array T_prev_commitments; std::array T_commitments; @@ -40,9 +40,8 @@ template bool MergeVerifier_::verify_proof(const HonkP } FF kappa = transcript->template get_challenge("kappa"); - info("kappa: ", kappa); - // Receive transcript poly evaluations and add corresponding univariate opening claims {(\kappa, p(\kappa), [p(X)]} + // Receive evaluations t_j(\kappa), T_{j,prev}(\kappa), T_j(\kappa), j = 1,2,3,4 std::array t_evals; std::array T_prev_evals; std::array T_evals; @@ -56,17 +55,15 @@ template bool MergeVerifier_::verify_proof(const HonkP T_evals[idx] = transcript->template receive_from_prover("T_eval_" + std::to_string(idx)); } - // Check the identity T(\kappa) = t(\kappa) + \kappa^m * T_prev_(\kappa). If it fails, return false + // Check the identity T_j(\kappa) = t_j(\kappa) + \kappa^m * T_{j,prev}(\kappa). If it fails, return false bool identity_checked = true; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { FF T_prev_shifted_eval_reconstructed = T_prev_evals[idx] * kappa.pow(subtable_size); bool current_check = T_evals[idx] == t_evals[idx] + T_prev_shifted_eval_reconstructed; - info("current_check: ", current_check); identity_checked = identity_checked && current_check; } FF alpha = transcript->template get_challenge("alpha"); - info("alpha: ", alpha); // Construct batched commitment and evaluation from constituents Commitment batched_commitment = t_commitments[0]; @@ -90,9 +87,6 @@ template bool MergeVerifier_::verify_proof(const HonkP OpeningClaim batched_claim = { { kappa, batched_eval }, batched_commitment }; - info("Verifier: batched_eval: ", batched_eval); - info("batched_commitment: ", batched_commitment); - auto pairing_points = PCS::reduce_verify(batched_claim, transcript); auto verified = pcs_verification_key->pairing_check(pairing_points[0], pairing_points[1]); return identity_checked && verified; From 6bbf9ab9086434c31c09252322d6e854973e34ab Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 20:47:44 +0000 Subject: [PATCH 22/33] consistent naming in rec merge --- .../merge_recursive_verifier.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp index d453465dabe5..2fca18dd68e6 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp @@ -33,13 +33,14 @@ std::array::Element, 2> MergeRecursiveVerifier_template receive_from_prover("subtable_size"); // Receive table column polynomial commitments [t_j], [T_{j,prev}], and [T_j], j = 1,2,3,4 - std::array C_t; - std::array C_T_prev; - std::array C_T; + std::array t_commitments; + std::array T_prev_commitments; + std::array T_commitments; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { - C_t[idx] = transcript->template receive_from_prover("t_CURRENT_" + std::to_string(idx + 1)); - C_T_prev[idx] = transcript->template receive_from_prover("T_PREV_" + std::to_string(idx + 1)); - C_T[idx] = transcript->template receive_from_prover("T_CURRENT_" + std::to_string(idx + 1)); + std::string suffix = std::to_string(idx); + t_commitments[idx] = transcript->template receive_from_prover("t_CURRENT_" + suffix); + T_prev_commitments[idx] = transcript->template receive_from_prover("T_PREV_" + suffix); + T_commitments[idx] = transcript->template receive_from_prover("T_CURRENT_" + suffix); } FF kappa = transcript->template get_challenge("kappa"); @@ -51,16 +52,16 @@ std::array::Element, 2> MergeRecursiveVerifier_ opening_claims; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { t_evals[idx] = transcript->template receive_from_prover("t_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, t_evals[idx] }, C_t[idx] }); + opening_claims.emplace_back(OpeningClaim{ { kappa, t_evals[idx] }, t_commitments[idx] }); } for (size_t idx = 0; idx < NUM_WIRES; ++idx) { T_prev_evals[idx] = transcript->template receive_from_prover("T_prev_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, C_T_prev[idx] }); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_prev_evals[idx] }, T_prev_commitments[idx] }); } for (size_t idx = 0; idx < NUM_WIRES; ++idx) { T_current_evals[idx] = transcript->template receive_from_prover("T_current_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, C_T[idx] }); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, T_commitments[idx] }); } // Check the identity T_j(\kappa) = t_j(\kappa) + \kappa^m * T_{j,prev}(\kappa) From 8ba616488ba10ed2153b855d8db05b80c4a1048b Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 21:04:55 +0000 Subject: [PATCH 23/33] name update to eccvm ops from raw ops --- .../eccvm/eccvm_circuit_builder.hpp | 8 ++-- .../eccvm/eccvm_circuit_builder.test.cpp | 2 +- .../src/barretenberg/eccvm/eccvm_flavor.hpp | 4 +- .../cpp/src/barretenberg/goblin/goblin.hpp | 2 +- .../op_queue/ecc_op_queue.hpp | 39 ++++++++++--------- .../op_queue/ecc_op_queue.test.cpp | 6 +-- .../op_queue/ecc_ops_table.hpp | 2 +- .../op_queue/ecc_ops_table.test.cpp | 29 +++++++------- .../translator_vm/translator.fuzzer.hpp | 14 +++---- .../translator_circuit_builder.cpp | 15 ++++--- .../translator_circuit_builder.fuzzer.cpp | 6 +-- .../translator_circuit_builder.test.cpp | 6 +-- .../ultra_honk/mega_honk.test.cpp | 11 ------ 13 files changed, 69 insertions(+), 75 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp index 7d472685f165..ead7e0ad55c2 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.hpp @@ -113,10 +113,10 @@ class ECCVMCircuitBuilder { std::vector> msm_mul_index; std::vector msm_sizes; - const auto& raw_ops = op_queue->get_raw_ops(); + const auto& eccvm_ops = op_queue->get_eccvm_ops(); size_t op_idx = 0; // populate opqueue and mul indices - for (const auto& op : raw_ops) { + for (const auto& op : eccvm_ops) { if (op.mul) { if ((op.z1 != 0 || op.z2 != 0) && !op.base_point.is_point_at_infinity()) { msm_opqueue_index.push_back(op_idx); @@ -131,7 +131,7 @@ class ECCVMCircuitBuilder { op_idx++; } // if last op is a mul we have not correctly computed the total number of msms - if (raw_ops.back().mul && active_mul_count > 0) { + if (eccvm_ops.back().mul && active_mul_count > 0) { msm_sizes.push_back(active_mul_count); msm_count++; } @@ -143,7 +143,7 @@ class ECCVMCircuitBuilder { parallel_for_range(msm_opqueue_index.size(), [&](size_t start, size_t end) { for (size_t i = start; i < end; i++) { - const auto& op = raw_ops[msm_opqueue_index[i]]; + const auto& op = eccvm_ops[msm_opqueue_index[i]]; auto [msm_index, mul_index] = msm_mul_index[i]; if (op.z1 != 0 && !op.base_point.is_point_at_infinity()) { ASSERT(result.size() > msm_index); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp index 0ee34da7aa74..6178c0c923c5 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp @@ -482,7 +482,7 @@ TEST(ECCVMCircuitBuilderTests, InfinityFailure) auto eccvm_builder = ECCVMCircuitBuilder(op_queue); - auto transcript_rows = ECCVMTranscriptBuilder::compute_rows(op_queue->get_raw_ops(), 1); + auto transcript_rows = ECCVMTranscriptBuilder::compute_rows(op_queue->get_eccvm_ops(), 1); // check that the corresponding op is mul bool row_op_code_correct = transcript_rows[1].opcode == 4; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp index d8fc7ca34feb..d189d5efb53e 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_flavor.hpp @@ -533,7 +533,7 @@ class ECCVMFlavor { { // compute rows for the three different sections of the ECCVM execution trace const auto transcript_rows = - ECCVMTranscriptBuilder::compute_rows(builder.op_queue->get_raw_ops(), builder.get_number_of_muls()); + ECCVMTranscriptBuilder::compute_rows(builder.op_queue->get_eccvm_ops(), builder.get_number_of_muls()); const std::vector msms = builder.get_msms(); const auto point_table_rows = ECCVMPointTablePrecomputationBuilder::compute_rows(CircuitBuilder::get_flattened_scalar_muls(msms)); @@ -1461,4 +1461,4 @@ class ECCVMFlavor { // NOLINTEND(cppcoreguidelines-avoid-const-or-ref-data-members) -} // namespace bb \ No newline at end of file +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp index e7e89185d583..785e9fcc4c5f 100644 --- a/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp +++ b/barretenberg/cpp/src/barretenberg/goblin/goblin.hpp @@ -75,7 +75,7 @@ class GoblinProver { // commitments (https://github.com/AztecProtocol/barretenberg/issues/871) which would otherwise appear in the // first round of the merge protocol. To be removed once the issue has been resolved. commitment_key = bn254_commitment_key ? bn254_commitment_key : nullptr; - GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue, commitment_key); + GoblinMockCircuits::perform_op_queue_interactions_for_mock_first_circuit(op_queue); } /** * @brief Construct a MegaHonk proof and a merge proof for the present circuit. diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index b8b9ad826fcc..2e126b6119cb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -28,11 +28,11 @@ class ECCOpQueue { static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = stdlib::NUM_LIMB_BITS_IN_FIELD_SIMULATION; - RawEccOpsTable raw_ops_table; - UltraEccOpsTable ultra_ops_table; + EccvmOpsTable eccvm_ops_table; // table of ops in the ECCVM format + UltraEccOpsTable ultra_ops_table; // table of ops in the Ultra-arithmetization format // Storage for the reconstructed raw ops table in contiguous memory - std::vector> raw_ops_reconstructed; + std::vector> eccvm_ops_reconstructed; // Tracks numer of muls and size of eccvm in real time as the op queue is updated EccvmRowTracker eccvm_row_tracker; @@ -42,7 +42,7 @@ class ECCOpQueue { void initialize_new_subtable() { - raw_ops_table.create_new_subtable(); + eccvm_ops_table.create_new_subtable(); ultra_ops_table.create_new_subtable(); } @@ -62,17 +62,17 @@ class ECCOpQueue { } // Reconstruct the full table of raw ops in contiguous memory from the independent subtables - void construct_full_raw_ops_table() { raw_ops_reconstructed = raw_ops_table.get_reconstructed(); } + void construct_full_eccvm_ops_table() { eccvm_ops_reconstructed = eccvm_ops_table.get_reconstructed(); } size_t get_ultra_ops_table_size() const { return ultra_ops_table.ultra_table_size(); } size_t get_current_ultra_ops_subtable_size() const { return ultra_ops_table.current_ultra_subtable_size(); } - std::vector& get_raw_ops() + std::vector& get_eccvm_ops() { - if (raw_ops_reconstructed.empty()) { - construct_full_raw_ops_table(); + if (eccvm_ops_reconstructed.empty()) { + construct_full_eccvm_ops_table(); } - return raw_ops_reconstructed; + return eccvm_ops_reconstructed; } /** @@ -107,7 +107,10 @@ class ECCOpQueue { * @brief A fuzzing only method for setting raw ops directly * */ - void set_raw_ops_for_fuzzing(std::vector& raw_ops_in) { raw_ops_reconstructed = raw_ops_in; } + void set_eccvm_ops_for_fuzzing(std::vector& eccvm_ops_in) + { + eccvm_ops_reconstructed = eccvm_ops_in; + } /** * @brief A testing only method that adds an erroneous equality op to the raw ops @@ -116,7 +119,7 @@ class ECCOpQueue { */ void add_erroneous_equality_op_for_testing() { - append_raw_op(ECCVMOperation{ .eq = true, .reset = true, .base_point = Point::random_element() }); + append_eccvm_op(ECCVMOperation{ .eq = true, .reset = true, .base_point = Point::random_element() }); } /** @@ -124,7 +127,7 @@ class ECCOpQueue { * @warning This is for testing purposes only. Currently no valid use case. * */ - void empty_row_for_testing() { append_raw_op(ECCVMOperation{ .base_point = point_at_infinity }); } + void empty_row_for_testing() { append_eccvm_op(ECCVMOperation{ .base_point = point_at_infinity }); } Point get_accumulator() { return accumulator; } @@ -139,7 +142,7 @@ class ECCOpQueue { accumulator = accumulator + to_add; // Store the raw operation - append_raw_op(ECCVMOperation{ .add = true, .base_point = to_add }); + append_eccvm_op(ECCVMOperation{ .add = true, .base_point = to_add }); // Construct and store the operation in the ultra op format return construct_and_populate_ultra_ops(ADD_ACCUM, to_add); @@ -159,7 +162,7 @@ class ECCOpQueue { UltraOp ultra_op = construct_and_populate_ultra_ops(MUL_ACCUM, to_mul, scalar); // Store the raw operation - append_raw_op(ECCVMOperation{ + append_eccvm_op(ECCVMOperation{ .mul = true, .base_point = to_mul, .z1 = ultra_op.z_1, @@ -177,7 +180,7 @@ class ECCOpQueue { UltraOp no_op() { // Store raw operation - append_raw_op(ECCVMOperation{}); + append_eccvm_op(ECCVMOperation{}); // Construct and store the operation in the ultra op format return construct_and_populate_ultra_ops(NULL_OP, accumulator); @@ -194,17 +197,17 @@ class ECCOpQueue { accumulator.self_set_infinity(); // Store raw operation - append_raw_op(ECCVMOperation{ .eq = true, .reset = true, .base_point = expected }); + append_eccvm_op(ECCVMOperation{ .eq = true, .reset = true, .base_point = expected }); // Construct and store the operation in the ultra op format return construct_and_populate_ultra_ops(EQUALITY, expected); } private: - void append_raw_op(const ECCVMOperation& op) + void append_eccvm_op(const ECCVMOperation& op) { eccvm_row_tracker.update_cached_msms(op); - raw_ops_table.push(op); + eccvm_ops_table.push(op); } /** * @brief Given an ecc operation and its inputs, decompose into ultra format and populate ultra_ops diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index 5ebfaa473b9a..199b5d114acd 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -31,9 +31,9 @@ TEST(ECCOpQueueTest, Basic) op_queue.initialize_new_subtable(); op_queue.add_accumulate(bb::g1::affine_one); op_queue.empty_row_for_testing(); - const auto& raw_ops = op_queue.get_raw_ops(); - EXPECT_EQ(raw_ops[0].base_point, G1::one()); - EXPECT_EQ(raw_ops[1].add, false); + const auto& eccvm_ops = op_queue.get_eccvm_ops(); + EXPECT_EQ(eccvm_ops[0].base_point, G1::one()); + EXPECT_EQ(eccvm_ops[1].add, false); } TEST(ECCOpQueueTest, InternalAccumulatorCorrectness) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index 273519b73e17..a64c5e9f3f12 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -85,7 +85,7 @@ template class EccOpsTable { } }; -using RawEccOpsTable = EccOpsTable>; +using EccvmOpsTable = EccOpsTable>; /** * @brief Stores a table of elliptic curve operations represented in the Ultra format diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp index 3d6369ac01ba..25b6004a040c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp @@ -45,14 +45,13 @@ class EccOpsTableTest : public ::testing::Test { // Mock raw ops table that constructs a concatenated table from successively prepended subtables struct MockRawOpsTable { - std::vector raw_ops; - void append(const ECCVMOperation& op) { raw_ops.push_back(op); } + std::vector eccvm_ops; MockRawOpsTable(const auto& subtable_ops) { for (auto& ops : std::ranges::reverse_view(subtable_ops)) { for (const auto& op : ops) { - append(op); + eccvm_ops.push_back(op); } } } @@ -73,7 +72,7 @@ class EccOpsTableTest : public ::testing::Test { return op; } - static ECCVMOperation random_raw_op() + static ECCVMOperation random_eccvm_op() { return ECCVMOperation{ .mul = true, .base_point = curve::BN254::Group::affine_element::random_element(), @@ -132,35 +131,35 @@ TEST(EccOpsTableTest, RawOpsTable) // Construct sets of raw ops, each representing those added by a single circuit const size_t NUM_SUBTABLES = 3; - std::array, NUM_SUBTABLES> subtable_raw_ops; + std::array, NUM_SUBTABLES> subtable_eccvm_ops; std::array subtable_op_counts = { 4, 2, 7 }; - for (auto [subtable_ops, op_count] : zip_view(subtable_raw_ops, subtable_op_counts)) { + for (auto [subtable_ops, op_count] : zip_view(subtable_eccvm_ops, subtable_op_counts)) { for (size_t i = 0; i < op_count; ++i) { - subtable_ops.push_back(EccOpsTableTest::random_raw_op()); + subtable_ops.push_back(EccOpsTableTest::random_eccvm_op()); } } // Construct the mock raw ops table which contains the subtables ordered in reverse (as if prepended) - EccOpsTableTest::MockRawOpsTable expected_raw_ops_table(subtable_raw_ops); + EccOpsTableTest::MockRawOpsTable expected_eccvm_ops_table(subtable_eccvm_ops); // Construct the concatenated raw ops table - RawEccOpsTable raw_ops_table; - for (const auto& subtable_ops : subtable_raw_ops) { - raw_ops_table.create_new_subtable(); + EccvmOpsTable eccvm_ops_table; + for (const auto& subtable_ops : subtable_eccvm_ops) { + eccvm_ops_table.create_new_subtable(); for (const auto& op : subtable_ops) { - raw_ops_table.push(op); + eccvm_ops_table.push(op); } } // Check that the table has the correct size auto expected_num_ops = std::accumulate(subtable_op_counts.begin(), subtable_op_counts.end(), size_t(0)); - EXPECT_EQ(raw_ops_table.size(), expected_num_ops); + EXPECT_EQ(eccvm_ops_table.size(), expected_num_ops); // Check that accessing the table values via operator[] matches the manually constructed mock table for (size_t i = 0; i < expected_num_ops; ++i) { - EXPECT_EQ(expected_raw_ops_table.raw_ops[i], raw_ops_table[i]); + EXPECT_EQ(expected_eccvm_ops_table.eccvm_ops[i], eccvm_ops_table[i]); } // Check that the copy-based reconstruction of the raw ops table matches the expected table - EXPECT_EQ(expected_raw_ops_table.raw_ops, raw_ops_table.get_reconstructed()); + EXPECT_EQ(expected_eccvm_ops_table.eccvm_ops, eccvm_ops_table.get_reconstructed()); } diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.fuzzer.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.fuzzer.hpp index eb54ebb99880..a3d747a10323 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.fuzzer.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.fuzzer.hpp @@ -23,15 +23,15 @@ using G1 = curve::BN254::AffineElement; */ std::vector parse_operations(const unsigned char* data, size_t size) { - std::vector raw_ops; + std::vector eccvm_ops; size_t size_left = size; // Just iterate and parse until there's no data left while (size_left >= sizeof(ECCOpQueue::ECCVMOperation)) { - raw_ops.emplace_back((ECCOpQueue::ECCVMOperation*)(data + (size - size_left))); + eccvm_ops.emplace_back((ECCOpQueue::ECCVMOperation*)(data + (size - size_left))); size_left -= sizeof(ECCOpQueue::ECCVMOperation); } - return raw_ops; + return eccvm_ops; } /** @@ -44,7 +44,7 @@ std::vector parse_operations(const unsigned char* da std::optional>> parse_and_construct_opqueue(const unsigned char* data, size_t size) { - std::vector raw_ops; + std::vector eccvm_ops; // Try to parse batching challenge size_t size_left = size; @@ -65,8 +65,8 @@ std::optional>> parse_and_constru size_left -= sizeof(uint256_t); // Try to parse operations - raw_ops = parse_operations(data + (size - size_left), size_left); - if (raw_ops.empty()) { + eccvm_ops = parse_operations(data + (size - size_left), size_left); + if (eccvm_ops.empty()) { return {}; } @@ -76,7 +76,7 @@ std::optional>> parse_and_constru auto padding_element = G1(p_x, p_y); auto padding_scalar = -Fr::one(); auto ecc_op_queue = std::make_shared(); - ecc_op_queue->set_raw_ops_for_fuzzing(raw_ops); + ecc_op_queue->set_eccvm_ops_for_fuzzing(eccvm_ops); ecc_op_queue->mul_accumulate(padding_element, padding_scalar); // Return the batching challenge, evaluation challenge and the constructed queue diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp index ba66e1311284..05417477b9a5 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.cpp @@ -588,13 +588,16 @@ TranslatorCircuitBuilder::AccumulationInput TranslatorCircuitBuilder::compute_wi batching_challenge_v, evaluation_input_x); } + +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1266): Evaluate whether this method can reuse existing data +// in the op queue for improved efficiency void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ptr ecc_op_queue) { using Fq = bb::fq; - const auto& raw_ops = ecc_op_queue->get_raw_ops(); + const auto& eccvm_ops = ecc_op_queue->get_eccvm_ops(); std::vector accumulator_trace; Fq current_accumulator(0); - if (raw_ops.empty()) { + if (eccvm_ops.empty()) { return; } // Rename for ease of use @@ -603,8 +606,8 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // We need to precompute the accumulators at each step, because in the actual circuit we compute the values starting // from the later indices. We need to know the previous accumulator to create the gate - for (size_t i = 0; i < raw_ops.size(); i++) { - const auto& ecc_op = raw_ops[raw_ops.size() - 1 - i]; + for (size_t i = 0; i < eccvm_ops.size(); i++) { + const auto& ecc_op = eccvm_ops[eccvm_ops.size() - 1 - i]; current_accumulator *= x; const auto [x_256, y_256] = ecc_op.get_base_point_standard_form(); current_accumulator += @@ -615,7 +618,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ // We don't care about the last value since we'll recompute it during witness generation anyway accumulator_trace.pop_back(); - for (const auto& raw_op : raw_ops) { + for (const auto& eccvm_op : eccvm_ops) { Fq previous_accumulator = 0; // Pop the last value from accumulator trace and use it as previous accumulator if (!accumulator_trace.empty()) { @@ -623,7 +626,7 @@ void TranslatorCircuitBuilder::feed_ecc_op_queue_into_circuit(const std::shared_ accumulator_trace.pop_back(); } // Compute witness values - auto one_accumulation_step = compute_witness_values_for_one_ecc_op(raw_op, previous_accumulator, v, x); + auto one_accumulation_step = compute_witness_values_for_one_ecc_op(eccvm_op, previous_accumulator, v, x); // And put them into the wires create_accumulation_gate(one_accumulation_step); diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp index 6b558421b2b0..52f5d4d46d72 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.fuzzer.cpp @@ -23,15 +23,15 @@ extern "C" int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size) auto z_1_accumulator = Fq(0); auto z_2_accumulator = Fq(0); // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - const auto& raw_ops = op_queue->get_raw_ops(); - for (const auto& ecc_op : raw_ops) { + const auto& eccvm_ops = op_queue->get_eccvm_ops(); + for (const auto& ecc_op : eccvm_ops) { op_accumulator = op_accumulator * x_inv + ecc_op.get_opcode_value(); p_x_accumulator = p_x_accumulator * x_inv + ecc_op.base_point.x; p_y_accumulator = p_y_accumulator * x_inv + ecc_op.base_point.y; z_1_accumulator = z_1_accumulator * x_inv + ecc_op.z1; z_2_accumulator = z_2_accumulator * x_inv + ecc_op.z2; } - Fq x_pow = x.pow(raw_ops.size() - 1); + Fq x_pow = x.pow(eccvm_ops.size() - 1); // Multiply by an appropriate power of x to get rid of the inverses Fq result = ((((z_2_accumulator * batching_challenge + z_1_accumulator) * batching_challenge + p_y_accumulator) * diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 3589a8bb0c25..e214a5fe5672 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -105,8 +105,8 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) // Get an inverse Fq x_inv = x.invert(); // Compute the batched evaluation of polynomials (multiplying by inverse to go from lower to higher) - const auto& raw_ops = op_queue->get_raw_ops(); - for (const auto& ecc_op : raw_ops) { + const auto& eccvm_ops = op_queue->get_eccvm_ops(); + for (const auto& ecc_op : eccvm_ops) { op_accumulator = op_accumulator * x_inv + ecc_op.get_opcode_value(); const auto [x_u256, y_u256] = ecc_op.get_base_point_standard_form(); p_x_accumulator = p_x_accumulator * x_inv + x_u256; @@ -114,7 +114,7 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) z_1_accumulator = z_1_accumulator * x_inv + ecc_op.z1; z_2_accumulator = z_2_accumulator * x_inv + ecc_op.z2; } - Fq x_pow = x.pow(raw_ops.size() - 1); + Fq x_pow = x.pow(eccvm_ops.size() - 1); // Multiply by an appropriate power of x to get rid of the inverses Fq result = ((((z_2_accumulator * batching_challenge + z_1_accumulator) * batching_challenge + p_y_accumulator) * diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp index c2b59479425d..50e6d68793e8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_honk.test.cpp @@ -333,17 +333,6 @@ TYPED_TEST(MegaHonkTests, MultipleCircuitsHonkAndMerge) auto merge_verified = this->construct_and_verify_merge_proof(op_queue); EXPECT_TRUE(merge_verified); } - - // // Compute the commitments to the aggregate op queue directly and check that they match those that were computed - // // iteratively during transcript aggregation by the provers and stored in the op queue. - // size_t aggregate_op_queue_size = op_queue->get_current_size(); - // auto ultra_ops = op_queue->get_aggregate_transcript(); - // auto commitment_key = std::make_shared(aggregate_op_queue_size); - // size_t idx = 0; - // for (const auto& result : op_queue->get_ultra_ops_commitments()) { - // auto expected = commitment_key->commit({ /* start index */ 0, ultra_ops[idx++] }); - // EXPECT_EQ(result, expected); - // } } /** From b52fd66192b44e4d1e45604f5cf63558d4fcd778 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 21:26:09 +0000 Subject: [PATCH 24/33] link issue with possible improvements --- .../op_queue/ecc_op_queue.hpp | 14 ++++++++------ .../src/barretenberg/ultra_honk/merge_prover.cpp | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index 2e126b6119cb..a790d554089e 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -10,11 +10,12 @@ namespace bb { /** * @brief Used to construct execution trace representations of elliptic curve operations. - * - * @details Currently the targets in execution traces are: four advice wires in UltraCircuitBuilder and 5 wires in the - * ECCVM. In each case, the variable values are stored in this class, since the same values will need to be used later - * by the TranslationVMCircuitBuilder. The circuit builders will store witness indices which are indices in the - * ultra (resp. eccvm) ops members of this class (rather than in the builder's variables array). + * @details Constrcuts and stores tables of ECC operations in two formats: the ECCVM format and the + * Ultra-arithmetization (width-4) format. The ECCVM format is used to construct the execution trace for the ECCVM + * circuit, while the Ultra-arithmetization is used in the Mega circuits and the Translator VM. Both tables are + * constructed via successive pre-pending of subtables of the same format, where each subtable represents the operations + * of a single circuit. + * TODO(https://github.com/AztecProtocol/barretenberg/issues/1267): consider possible efficiency improvements */ class ECCOpQueue { using Curve = curve::BN254; @@ -31,7 +32,8 @@ class ECCOpQueue { EccvmOpsTable eccvm_ops_table; // table of ops in the ECCVM format UltraEccOpsTable ultra_ops_table; // table of ops in the Ultra-arithmetization format - // Storage for the reconstructed raw ops table in contiguous memory + // Storage for the reconstructed raw ops table in contiguous memory. (Intended to be constructed once and for all + // prior to ECCVM constrcution to avoid repeated prepending of subtables in physical memory). std::vector> eccvm_ops_reconstructed; // Tracks numer of muls and size of eccvm in real time as the op queue is updated diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 9ee454fd7112..a591050c773d 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -6,7 +6,7 @@ namespace bb { /** * @brief Create MergeProver * @details We require an SRS at least as large as the current ultra ecc ops table - * + * TODO(https://github.com/AztecProtocol/barretenberg/issues/1267): consider possible efficiency improvements */ template MergeProver_::MergeProver_(const std::shared_ptr& op_queue, From d00c55f39535328caeb6113327bc091bbd2f1330 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 21:26:41 +0000 Subject: [PATCH 25/33] uncomment vanilla --- .../ultra_vanilla_client_ivc.test.cpp | 156 +++++++++--------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp index 92a2d825d299..21656305671b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.test.cpp @@ -1,93 +1,93 @@ -// #include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp" -// #include "barretenberg/goblin/goblin.hpp" -// #include "barretenberg/goblin/mock_circuits.hpp" -// #include "barretenberg/protogalaxy/folding_test_utils.hpp" -// #include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" -// #include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" -// #include +#include "barretenberg/ultra_vanilla_client_ivc/ultra_vanilla_client_ivc.hpp" +#include "barretenberg/goblin/goblin.hpp" +#include "barretenberg/goblin/mock_circuits.hpp" +#include "barretenberg/protogalaxy/folding_test_utils.hpp" +#include "barretenberg/stdlib_circuit_builders/mega_circuit_builder.hpp" +#include "barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp" +#include -// using namespace bb; +using namespace bb; -// class UltraVanillaClientIVCTests : public ::testing::Test { -// protected: -// static void SetUpTestSuite() -// { -// srs::init_crs_factory("../srs_db/ignition"); -// srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); -// } +class UltraVanillaClientIVCTests : public ::testing::Test { + protected: + static void SetUpTestSuite() + { + srs::init_crs_factory("../srs_db/ignition"); + srs::init_grumpkin_crs_factory("../srs_db/grumpkin"); + } -// using Flavor = UltraVanillaClientIVC::Flavor; -// using Builder = UltraCircuitBuilder; -// using FF = typename Flavor::FF; -// using VK = Flavor::VerificationKey; -// using PK = DeciderProvingKey_; + using Flavor = UltraVanillaClientIVC::Flavor; + using Builder = UltraCircuitBuilder; + using FF = typename Flavor::FF; + using VK = Flavor::VerificationKey; + using PK = DeciderProvingKey_; -// class MockCircuitSource : public CircuitSource { -// std::vector _sizes; -// std::vector> _vks; -// uint32_t step{ 0 }; + class MockCircuitSource : public CircuitSource { + std::vector _sizes; + std::vector> _vks; + uint32_t step{ 0 }; -// public: -// MockCircuitSource(const std::vector& sizes) -// : _sizes(sizes) -// { -// std::fill_n(std::back_inserter(_vks), sizes.size(), nullptr); -// } + public: + MockCircuitSource(const std::vector& sizes) + : _sizes(sizes) + { + std::fill_n(std::back_inserter(_vks), sizes.size(), nullptr); + } -// MockCircuitSource(const MockCircuitSource& source_without_sizes, std::vector> vks) -// : _sizes(source_without_sizes._sizes) -// , _vks(vks) -// {} + MockCircuitSource(const MockCircuitSource& source_without_sizes, std::vector> vks) + : _sizes(source_without_sizes._sizes) + , _vks(vks) + {} -// Output next() override -// { -// Builder circuit; -// MockCircuits::construct_arithmetic_circuit(circuit, _sizes[step]); -// const auto& vk = _vks[step]; -// ++step; -// return { circuit, vk }; -// } + Output next() override + { + Builder circuit; + MockCircuits::construct_arithmetic_circuit(circuit, _sizes[step]); + const auto& vk = _vks[step]; + ++step; + return { circuit, vk }; + } -// size_t num_circuits() const override -// { -// ASSERT(_sizes.size() == _vks.size()); -// return _sizes.size(); -// } -// }; -// }; + size_t num_circuits() const override + { + ASSERT(_sizes.size() == _vks.size()); + return _sizes.size(); + } + }; +}; -// TEST_F(UltraVanillaClientIVCTests, TwoCircuits) -// { -// static constexpr size_t LOG_SIZE = 10; -// UltraVanillaClientIVC ivc(1 << LOG_SIZE); -// MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE } }; -// EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); -// }; +TEST_F(UltraVanillaClientIVCTests, TwoCircuits) +{ + static constexpr size_t LOG_SIZE = 10; + UltraVanillaClientIVC ivc(1 << LOG_SIZE); + MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE } }; + EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); +}; -// TEST_F(UltraVanillaClientIVCTests, ThreeCircuits) -// { -// static constexpr size_t LOG_SIZE = 10; -// UltraVanillaClientIVC ivc(1 << LOG_SIZE); -// MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE, LOG_SIZE } }; -// EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); -// }; +TEST_F(UltraVanillaClientIVCTests, ThreeCircuits) +{ + static constexpr size_t LOG_SIZE = 10; + UltraVanillaClientIVC ivc(1 << LOG_SIZE); + MockCircuitSource circuit_source{ { LOG_SIZE, LOG_SIZE, LOG_SIZE } }; + EXPECT_TRUE(ivc.prove_and_verify(circuit_source)); +}; -// /** -// * @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys -// * @details The test precomputes the keys via one pass of the ivc prover, then it uses them in a second pass. -// */ -// TEST_F(UltraVanillaClientIVCTests, PrecomputedVerificationKeys) -// { +/** + * @brief Prove and verify accumulation of an arbitrary set of circuits using precomputed verification keys + * @details The test precomputes the keys via one pass of the ivc prover, then it uses them in a second pass. + */ +TEST_F(UltraVanillaClientIVCTests, PrecomputedVerificationKeys) +{ -// static constexpr size_t LOG_SIZE = 10; + static constexpr size_t LOG_SIZE = 10; -// UltraVanillaClientIVC ivc_1(1 << LOG_SIZE); -// MockCircuitSource circuit_source_no_vks{ { LOG_SIZE, LOG_SIZE } }; -// auto vks = ivc_1.compute_vks(circuit_source_no_vks); + UltraVanillaClientIVC ivc_1(1 << LOG_SIZE); + MockCircuitSource circuit_source_no_vks{ { LOG_SIZE, LOG_SIZE } }; + auto vks = ivc_1.compute_vks(circuit_source_no_vks); -// UltraVanillaClientIVC ivc_2(1 << LOG_SIZE); // need to refactor accumulator_value use to reuse ivc_1 -// MockCircuitSource circuit_source_with_vks{ circuit_source_no_vks, vks }; -// EXPECT_TRUE(ivc_2.prove_and_verify(circuit_source_with_vks)); -// }; + UltraVanillaClientIVC ivc_2(1 << LOG_SIZE); // need to refactor accumulator_value use to reuse ivc_1 + MockCircuitSource circuit_source_with_vks{ circuit_source_no_vks, vks }; + EXPECT_TRUE(ivc_2.prove_and_verify(circuit_source_with_vks)); +}; -// // TODO(https://github.com/AztecProtocol/barretenberg/issues/1177) Implement failure tests +// TODO(https://github.com/AztecProtocol/barretenberg/issues/1177) Implement failure tests From 44a4fd751e34d20f5d7595b703be60d7d5e6f6a2 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 22:16:57 +0000 Subject: [PATCH 26/33] init subtable in a few places --- .../stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp | 3 ++- .../barretenberg/translator_vm/relation_correctness.test.cpp | 1 + .../cpp/src/barretenberg/translator_vm/translator.test.cpp | 1 + .../translator_vm/translator_circuit_builder.test.cpp | 1 + 4 files changed, 5 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp index 76ec71551ad8..d17b0f5feaad 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp @@ -52,6 +52,7 @@ template class ECCVMRecursiveTests : public ::testing using Fr = Curve::ScalarField; std::shared_ptr op_queue = std::make_shared(); + op_queue->initialize_new_subtable(); G1 a = G1::random_element(engine); G1 b = G1::random_element(engine); G1 c = G1::random_element(engine); @@ -199,4 +200,4 @@ TYPED_TEST(ECCVMRecursiveTests, IndependentVKHash) { TestFixture::test_independent_vk_hash(); }; -} // namespace bb \ No newline at end of file +} // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp index 119eedc5b9f9..c8dab9afdb9b 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -565,6 +565,7 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) auto& engine = numeric::get_debug_randomness(); auto op_queue = std::make_shared(); + op_queue->initialize_new_subtable(); // Generate random EccOpQueue actions for (size_t i = 0; i < ((mini_circuit_size >> 1) - 1); i++) { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index ed0503a82e81..5389d1ebfeb9 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -37,6 +37,7 @@ TEST_F(TranslatorTests, Basic) // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); + op_queue->initialize_new_subtable(); op_queue->append_nonzero_ops(); for (size_t i = 0; i < 500; i++) { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index e214a5fe5672..07a570f7ce5c 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -88,6 +88,7 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); + op_queue->initialize_new_subtable(); op_queue->add_accumulate(P1); op_queue->mul_accumulate(P2, z); Fq op_accumulator = 0; From 7c3a337dbd1c3d3d85a57070ac257256ecd5d839 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Mon, 24 Feb 2025 23:29:26 +0000 Subject: [PATCH 27/33] fix more tests --- .../eccvm/eccvm_circuit_builder.test.cpp | 56 +++++++++++-------- .../eccvm/eccvm_composer.test.cpp | 1 + .../eccvm/eccvm_transcript.test.cpp | 3 +- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp index 6178c0c923c5..eac5de538bbe 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp @@ -12,6 +12,16 @@ namespace { auto& engine = numeric::get_debug_randomness(); } // namespace +class ECCVMCircuitBuilderTests : public ::testing::Test { + public: + static std::shared_ptr create_op_queue() + { + std::shared_ptr op_queue = std::make_shared(); + op_queue->initialize_new_subtable(); + return op_queue; + } +}; + TEST(ECCVMCircuitBuilderTests, BaseCase) { auto generators = G1::derive_generators("test generators", 3); @@ -23,7 +33,7 @@ TEST(ECCVMCircuitBuilderTests, BaseCase) Fr y = Fr::random_element(&engine); Fr zero_scalar = 0; - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); op_queue->add_accumulate(a); op_queue->mul_accumulate(a, x); @@ -71,7 +81,7 @@ TEST(ECCVMCircuitBuilderTests, BaseCase) TEST(ECCVMCircuitBuilderTests, NoOp) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); op_queue->no_op(); @@ -82,7 +92,7 @@ TEST(ECCVMCircuitBuilderTests, NoOp) TEST(ECCVMCircuitBuilderTests, Add) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -96,7 +106,7 @@ TEST(ECCVMCircuitBuilderTests, Add) TEST(ECCVMCircuitBuilderTests, Mul) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -111,7 +121,7 @@ TEST(ECCVMCircuitBuilderTests, Mul) TEST(ECCVMCircuitBuilderTests, MulInfinity) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -129,7 +139,7 @@ TEST(ECCVMCircuitBuilderTests, MulInfinity) // Validate we do not trigger edge cases of addition formulae when we have identical mul inputs TEST(ECCVMCircuitBuilderTests, MulOverIdenticalInputs) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -144,7 +154,7 @@ TEST(ECCVMCircuitBuilderTests, MulOverIdenticalInputs) TEST(ECCVMCircuitBuilderTests, MSMProducesInfinity) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -160,7 +170,7 @@ TEST(ECCVMCircuitBuilderTests, MSMProducesInfinity) TEST(ECCVMCircuitBuilderTests, MSMOverPointAtInfinity) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element point_at_infinity = G1::point_at_infinity; @@ -214,7 +224,7 @@ TEST(ECCVMCircuitBuilderTests, MSMOverPointAtInfinity) TEST(ECCVMCircuitBuilderTests, ShortMul) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); @@ -235,7 +245,7 @@ TEST(ECCVMCircuitBuilderTests, ShortMul) TEST(ECCVMCircuitBuilderTests, EqFails) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -252,7 +262,7 @@ TEST(ECCVMCircuitBuilderTests, EqFails) TEST(ECCVMCircuitBuilderTests, EmptyRow) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); op_queue->empty_row_for_testing(); @@ -263,7 +273,7 @@ TEST(ECCVMCircuitBuilderTests, EmptyRow) TEST(ECCVMCircuitBuilderTests, EmptyRowBetweenOps) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -280,7 +290,7 @@ TEST(ECCVMCircuitBuilderTests, EmptyRowBetweenOps) TEST(ECCVMCircuitBuilderTests, EndWithEq) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -296,7 +306,7 @@ TEST(ECCVMCircuitBuilderTests, EndWithEq) TEST(ECCVMCircuitBuilderTests, EndWithAdd) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -313,7 +323,7 @@ TEST(ECCVMCircuitBuilderTests, EndWithAdd) TEST(ECCVMCircuitBuilderTests, EndWithMul) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -330,7 +340,7 @@ TEST(ECCVMCircuitBuilderTests, EndWithMul) TEST(ECCVMCircuitBuilderTests, EndWithNoop) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -366,7 +376,7 @@ TEST(ECCVMCircuitBuilderTests, MSM) // single msms for (size_t j = 1; j < max_num_msms; ++j) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); compute_msms(j, op_queue); ECCVMCircuitBuilder circuit{ op_queue }; @@ -374,7 +384,7 @@ TEST(ECCVMCircuitBuilderTests, MSM) EXPECT_EQ(result, true); } // chain msms - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); for (size_t j = 1; j < 9; ++j) { compute_msms(j, op_queue); @@ -386,7 +396,7 @@ TEST(ECCVMCircuitBuilderTests, MSM) TEST(ECCVMCircuitBuilderTests, EqAgainstPointAtInfinity) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -402,7 +412,7 @@ TEST(ECCVMCircuitBuilderTests, EqAgainstPointAtInfinity) TEST(ECCVMCircuitBuilderTests, AddPointAtInfinity) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -420,7 +430,7 @@ TEST(ECCVMCircuitBuilderTests, AddPointAtInfinity) TEST(ECCVMCircuitBuilderTests, AddProducesPointAtInfinity) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -435,7 +445,7 @@ TEST(ECCVMCircuitBuilderTests, AddProducesPointAtInfinity) TEST(ECCVMCircuitBuilderTests, AddProducesDouble) { - std::shared_ptr op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -474,7 +484,7 @@ TEST(ECCVMCircuitBuilderTests, InfinityFailure) bb::srs::init_grumpkin_crs_factory(bb::srs::get_grumpkin_crs_path()); // Add the same operations to the ECC op queue; the native computation is performed under the hood. - auto op_queue = std::make_shared(); + std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); for (size_t i = 0; i < 1; i++) { op_queue->mul_accumulate(P1, Fr(0)); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp index d0ab2746f5d0..1eacf6046ce7 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp @@ -37,6 +37,7 @@ ECCVMCircuitBuilder generate_circuit(numeric::RNG* engine = nullptr) using Fr = Curve::ScalarField; std::shared_ptr op_queue = std::make_shared(); + op_queue->initialize_new_subtable(); G1 a = G1::random_element(engine); G1 b = G1::random_element(engine); G1 c = G1::random_element(engine); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index 8eef6b58e482..bd5e416ca910 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -235,6 +235,7 @@ class ECCVMTranscriptTests : public ::testing::Test { ECCVMCircuitBuilder generate_trace(numeric::RNG* engine = nullptr) { std::shared_ptr op_queue = std::make_shared(); + op_queue->initialize_new_subtable(); using G1 = typename Flavor::CycleGroup; using Fr = typename G1::Fr; @@ -405,4 +406,4 @@ TEST_F(ECCVMTranscriptTests, StructureTest) prover.transcript->deserialize_full_transcript(); EXPECT_EQ(static_cast(prover.transcript->transcript_Px_comm), one_group_val * rand_val); -} \ No newline at end of file +} From 28329b8a2095a2efaa1e22da0e1eba8befdf4f3d Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 25 Feb 2025 03:33:05 +0000 Subject: [PATCH 28/33] one more fix --- .../translator_recursive_verifier.test.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index abe273f388c5..0b2d0b895d53 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -48,6 +48,7 @@ template class TranslatorRecursiveTests : public ::te // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); + op_queue->initialize_new_subtable(); op_queue->append_nonzero_ops(); for (size_t i = 0; i < num_ops; i++) { @@ -199,4 +200,4 @@ TYPED_TEST(TranslatorRecursiveTests, IndependentVKHash) GTEST_SKIP() << "Not built for this parameter"; } }; -} // namespace bb \ No newline at end of file +} // namespace bb From f5ac135a296d5a9b61c39515649cacd33d8dd698 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 25 Feb 2025 18:44:42 +0000 Subject: [PATCH 29/33] WiP init a subtable in the op queue constructor --- .../stdlib_circuit_builders/op_queue/ecc_op_queue.hpp | 3 +++ .../stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp | 2 -- .../stdlib_circuit_builders/op_queue/ecc_ops_table.hpp | 4 ++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index a790d554089e..65bba73abd2f 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -42,6 +42,9 @@ class ECCOpQueue { public: using ECCVMOperation = bb::eccvm::VMOperation; + // Constructor simply prepares the first subtable to be written to + ECCOpQueue() { initialize_new_subtable(); } + void initialize_new_subtable() { eccvm_ops_table.create_new_subtable(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index 199b5d114acd..be41d912a118 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -28,7 +28,6 @@ TEST(ECCOpQueueTest, Basic) using G1 = ECCOpQueueTest::G1; ECCOpQueue op_queue; - op_queue.initialize_new_subtable(); op_queue.add_accumulate(bb::g1::affine_one); op_queue.empty_row_for_testing(); const auto& eccvm_ops = op_queue.get_eccvm_ops(); @@ -49,7 +48,6 @@ TEST(ECCOpQueueTest, InternalAccumulatorCorrectness) // Add the same operations to the ECC op queue; the native computation is performed under the hood. ECCOpQueue op_queue; - op_queue.initialize_new_subtable(); op_queue.add_accumulate(P1); op_queue.mul_accumulate(P2, z); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index a64c5e9f3f12..fc73fc95bbf4 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -52,6 +52,10 @@ template class EccOpsTable { void create_new_subtable(size_t size_hint = 0) { + // If there is a single subtable and it is empty, dont create a new one + if (table.size() == 1 && table.front().empty()) { + return; + } Subtable new_subtable; new_subtable.reserve(size_hint); table.insert(table.begin(), std::move(new_subtable)); From 78efafc952429d289cd64ebec4f9e669b21846a9 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 25 Feb 2025 19:44:41 +0000 Subject: [PATCH 30/33] utilize default initial subtable --- .../eccvm/eccvm_circuit_builder.test.cpp | 56 ++++++++----------- .../eccvm/eccvm_composer.test.cpp | 1 - .../eccvm/eccvm_transcript.test.cpp | 1 - .../eccvm_recursive_verifier.test.cpp | 1 - .../translator_recursive_verifier.test.cpp | 1 - .../relation_correctness.test.cpp | 1 - .../translator_vm/translator.test.cpp | 1 - .../translator_circuit_builder.test.cpp | 1 - 8 files changed, 23 insertions(+), 40 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp index eac5de538bbe..49235695d07c 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp @@ -12,16 +12,6 @@ namespace { auto& engine = numeric::get_debug_randomness(); } // namespace -class ECCVMCircuitBuilderTests : public ::testing::Test { - public: - static std::shared_ptr create_op_queue() - { - std::shared_ptr op_queue = std::make_shared(); - op_queue->initialize_new_subtable(); - return op_queue; - } -}; - TEST(ECCVMCircuitBuilderTests, BaseCase) { auto generators = G1::derive_generators("test generators", 3); @@ -33,7 +23,7 @@ TEST(ECCVMCircuitBuilderTests, BaseCase) Fr y = Fr::random_element(&engine); Fr zero_scalar = 0; - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); op_queue->add_accumulate(a); op_queue->mul_accumulate(a, x); @@ -81,7 +71,7 @@ TEST(ECCVMCircuitBuilderTests, BaseCase) TEST(ECCVMCircuitBuilderTests, NoOp) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); op_queue->no_op(); @@ -92,7 +82,7 @@ TEST(ECCVMCircuitBuilderTests, NoOp) TEST(ECCVMCircuitBuilderTests, Add) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -106,7 +96,7 @@ TEST(ECCVMCircuitBuilderTests, Add) TEST(ECCVMCircuitBuilderTests, Mul) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -121,7 +111,7 @@ TEST(ECCVMCircuitBuilderTests, Mul) TEST(ECCVMCircuitBuilderTests, MulInfinity) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -139,7 +129,7 @@ TEST(ECCVMCircuitBuilderTests, MulInfinity) // Validate we do not trigger edge cases of addition formulae when we have identical mul inputs TEST(ECCVMCircuitBuilderTests, MulOverIdenticalInputs) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -154,7 +144,7 @@ TEST(ECCVMCircuitBuilderTests, MulOverIdenticalInputs) TEST(ECCVMCircuitBuilderTests, MSMProducesInfinity) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -170,7 +160,7 @@ TEST(ECCVMCircuitBuilderTests, MSMProducesInfinity) TEST(ECCVMCircuitBuilderTests, MSMOverPointAtInfinity) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element point_at_infinity = G1::point_at_infinity; @@ -224,7 +214,7 @@ TEST(ECCVMCircuitBuilderTests, MSMOverPointAtInfinity) TEST(ECCVMCircuitBuilderTests, ShortMul) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); @@ -245,7 +235,7 @@ TEST(ECCVMCircuitBuilderTests, ShortMul) TEST(ECCVMCircuitBuilderTests, EqFails) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -262,7 +252,7 @@ TEST(ECCVMCircuitBuilderTests, EqFails) TEST(ECCVMCircuitBuilderTests, EmptyRow) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); op_queue->empty_row_for_testing(); @@ -273,7 +263,7 @@ TEST(ECCVMCircuitBuilderTests, EmptyRow) TEST(ECCVMCircuitBuilderTests, EmptyRowBetweenOps) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -290,7 +280,7 @@ TEST(ECCVMCircuitBuilderTests, EmptyRowBetweenOps) TEST(ECCVMCircuitBuilderTests, EndWithEq) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -306,7 +296,7 @@ TEST(ECCVMCircuitBuilderTests, EndWithEq) TEST(ECCVMCircuitBuilderTests, EndWithAdd) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -323,7 +313,7 @@ TEST(ECCVMCircuitBuilderTests, EndWithAdd) TEST(ECCVMCircuitBuilderTests, EndWithMul) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -340,7 +330,7 @@ TEST(ECCVMCircuitBuilderTests, EndWithMul) TEST(ECCVMCircuitBuilderTests, EndWithNoop) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -376,7 +366,7 @@ TEST(ECCVMCircuitBuilderTests, MSM) // single msms for (size_t j = 1; j < max_num_msms; ++j) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); compute_msms(j, op_queue); ECCVMCircuitBuilder circuit{ op_queue }; @@ -384,7 +374,7 @@ TEST(ECCVMCircuitBuilderTests, MSM) EXPECT_EQ(result, true); } // chain msms - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); for (size_t j = 1; j < 9; ++j) { compute_msms(j, op_queue); @@ -396,7 +386,7 @@ TEST(ECCVMCircuitBuilderTests, MSM) TEST(ECCVMCircuitBuilderTests, EqAgainstPointAtInfinity) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -412,7 +402,7 @@ TEST(ECCVMCircuitBuilderTests, EqAgainstPointAtInfinity) TEST(ECCVMCircuitBuilderTests, AddPointAtInfinity) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -430,7 +420,7 @@ TEST(ECCVMCircuitBuilderTests, AddPointAtInfinity) TEST(ECCVMCircuitBuilderTests, AddProducesPointAtInfinity) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -445,7 +435,7 @@ TEST(ECCVMCircuitBuilderTests, AddProducesPointAtInfinity) TEST(ECCVMCircuitBuilderTests, AddProducesDouble) { - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); auto generators = G1::derive_generators("test generators", 3); typename G1::element a = generators[0]; @@ -484,7 +474,7 @@ TEST(ECCVMCircuitBuilderTests, InfinityFailure) bb::srs::init_grumpkin_crs_factory(bb::srs::get_grumpkin_crs_path()); // Add the same operations to the ECC op queue; the native computation is performed under the hood. - std::shared_ptr op_queue = ECCVMCircuitBuilderTests::create_op_queue(); + std::shared_ptr op_queue = std::make_shared(); for (size_t i = 0; i < 1; i++) { op_queue->mul_accumulate(P1, Fr(0)); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp index 1eacf6046ce7..d0ab2746f5d0 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_composer.test.cpp @@ -37,7 +37,6 @@ ECCVMCircuitBuilder generate_circuit(numeric::RNG* engine = nullptr) using Fr = Curve::ScalarField; std::shared_ptr op_queue = std::make_shared(); - op_queue->initialize_new_subtable(); G1 a = G1::random_element(engine); G1 b = G1::random_element(engine); G1 c = G1::random_element(engine); diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp index bd5e416ca910..3adb4631676c 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_transcript.test.cpp @@ -235,7 +235,6 @@ class ECCVMTranscriptTests : public ::testing::Test { ECCVMCircuitBuilder generate_trace(numeric::RNG* engine = nullptr) { std::shared_ptr op_queue = std::make_shared(); - op_queue->initialize_new_subtable(); using G1 = typename Flavor::CycleGroup; using Fr = typename G1::Fr; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp index d17b0f5feaad..462ea1bd4d28 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/eccvm_verifier/eccvm_recursive_verifier.test.cpp @@ -52,7 +52,6 @@ template class ECCVMRecursiveTests : public ::testing using Fr = Curve::ScalarField; std::shared_ptr op_queue = std::make_shared(); - op_queue->initialize_new_subtable(); G1 a = G1::random_element(engine); G1 b = G1::random_element(engine); G1 c = G1::random_element(engine); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp index 0b2d0b895d53..6e6780293d99 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/translator_vm_verifier/translator_recursive_verifier.test.cpp @@ -48,7 +48,6 @@ template class TranslatorRecursiveTests : public ::te // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); - op_queue->initialize_new_subtable(); op_queue->append_nonzero_ops(); for (size_t i = 0; i < num_ops; i++) { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp index c8dab9afdb9b..119eedc5b9f9 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/relation_correctness.test.cpp @@ -565,7 +565,6 @@ TEST_F(TranslatorRelationCorrectnessTests, NonNative) auto& engine = numeric::get_debug_randomness(); auto op_queue = std::make_shared(); - op_queue->initialize_new_subtable(); // Generate random EccOpQueue actions for (size_t i = 0; i < ((mini_circuit_size >> 1) - 1); i++) { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp index 5389d1ebfeb9..ed0503a82e81 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator.test.cpp @@ -37,7 +37,6 @@ TEST_F(TranslatorTests, Basic) // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); - op_queue->initialize_new_subtable(); op_queue->append_nonzero_ops(); for (size_t i = 0; i < 500; i++) { diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp index 07a570f7ce5c..e214a5fe5672 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_circuit_builder.test.cpp @@ -88,7 +88,6 @@ TEST(TranslatorCircuitBuilder, SeveralOperationCorrectness) // Add the same operations to the ECC op queue; the native computation is performed under the hood. auto op_queue = std::make_shared(); - op_queue->initialize_new_subtable(); op_queue->add_accumulate(P1); op_queue->mul_accumulate(P2, z); Fq op_accumulator = 0; From d5f9188b824ed19244c90096d87f5fa4c6addbc0 Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 25 Feb 2025 20:26:26 +0000 Subject: [PATCH 31/33] comments and naming fixes --- .../mega_circuit_builder.test.cpp | 2 +- .../eccvm/eccvm_circuit_builder.test.cpp | 2 +- .../op_queue/ecc_op_queue.hpp | 35 +++++++++++-------- .../op_queue/ecc_op_queue.test.cpp | 6 ++-- .../op_queue/ecc_ops_table.hpp | 2 +- .../op_queue/ecc_ops_table.test.cpp | 20 +++++------ .../barretenberg/ultra_honk/merge_prover.cpp | 6 ++-- 7 files changed, 39 insertions(+), 34 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp index 9f2b93714a7e..3c4cad8dac43 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/mega_circuit_builder.test.cpp @@ -149,7 +149,7 @@ TEST(MegaCircuitBuilder, GoblinEccOpQueueUltraOps) builder.queue_ecc_eq(); // Check that the ultra ops recorded in the EccOpQueue match the ops recorded in the wires - auto ultra_ops = builder.op_queue->get_current_subtable_columns(); + auto ultra_ops = builder.op_queue->construct_current_ultra_ops_subtable_columns(); for (size_t i = 1; i < 4; ++i) { for (size_t j = 0; j < builder.blocks.ecc_op.size(); ++j) { auto op_wire_val = builder.variables[builder.blocks.ecc_op.wires[i][j]]; diff --git a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp index 49235695d07c..fd31725893ea 100644 --- a/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/eccvm/eccvm_circuit_builder.test.cpp @@ -454,7 +454,7 @@ TEST(ECCVMCircuitBuilderTests, AddProducesDouble) * @details Currently, Goblin does not support clean initialization, which means that we have to create mock ECCOpQueue * to avoid commiting to zero polynomials. This test localizes the issue to the problem with populating ECCVM Transcript * rows in the method \ref bb::ECCVMTranscriptBuilder::compute_rows "compute rows". Namely, we are loosing the point at - * infinity contribution to the 'transcipt_Px' polynomials while parsing the raw ops of ECCOpQueue. + * infinity contribution to the 'transcipt_Px' polynomials while parsing the eccvm ops of ECCOpQueue. * * More specifically, in this test we add a simple MSM with the point at infinity multiplied by \f$0\f$. While the ECCVM * computes the result of this op correctly, i.e. outputs the point at infinity, the computation of 'transcript_Px' is diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index 65bba73abd2f..d896fa6e82c0 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -10,7 +10,7 @@ namespace bb { /** * @brief Used to construct execution trace representations of elliptic curve operations. - * @details Constrcuts and stores tables of ECC operations in two formats: the ECCVM format and the + * @details Constructs and stores tables of ECC operations in two formats: the ECCVM format and the * Ultra-arithmetization (width-4) format. The ECCVM format is used to construct the execution trace for the ECCVM * circuit, while the Ultra-arithmetization is used in the Mega circuits and the Translator VM. Both tables are * constructed via successive pre-pending of subtables of the same format, where each subtable represents the operations @@ -32,11 +32,11 @@ class ECCOpQueue { EccvmOpsTable eccvm_ops_table; // table of ops in the ECCVM format UltraEccOpsTable ultra_ops_table; // table of ops in the Ultra-arithmetization format - // Storage for the reconstructed raw ops table in contiguous memory. (Intended to be constructed once and for all - // prior to ECCVM constrcution to avoid repeated prepending of subtables in physical memory). + // Storage for the reconstructed eccvm ops table in contiguous memory. (Intended to be constructed once and for all + // prior to ECCVM construction to avoid repeated prepending of subtables in physical memory). std::vector> eccvm_ops_reconstructed; - // Tracks numer of muls and size of eccvm in real time as the op queue is updated + // Tracks number of muls and size of eccvm in real time as the op queue is updated EccvmRowTracker eccvm_row_tracker; public: @@ -45,33 +45,38 @@ class ECCOpQueue { // Constructor simply prepares the first subtable to be written to ECCOpQueue() { initialize_new_subtable(); } + // Initialize a new subtable of ECCVM ops and Ultra ops corresponding to an individual circuit void initialize_new_subtable() { eccvm_ops_table.create_new_subtable(); ultra_ops_table.create_new_subtable(); } - std::array, 4> get_ultra_ops_table_columns() const + // Construct polynomials corresponding to the columns of the full aggregate ultra ecc ops table + std::array, 4> construct_ultra_ops_table_columns() const { return ultra_ops_table.construct_table_columns(); } - std::array, 4> get_previous_ultra_ops_table_columns() const + // Construct polynomials corresponding to columns of the aggregate ultra ops table excluding most recent subtable + std::array, 4> construct_previous_ultra_ops_table_columns() const { return ultra_ops_table.construct_previous_table_columns(); } - std::array, 4> get_current_subtable_columns() const + // Construct polynomials corresponding to the columns of the current subtable of ultra ecc ops + std::array, 4> construct_current_ultra_ops_subtable_columns() const { - return ultra_ops_table.construct_current_subtable_columns(); + return ultra_ops_table.construct_current_ultra_ops_subtable_columns(); } - // Reconstruct the full table of raw ops in contiguous memory from the independent subtables + // Reconstruct the full table of eccvm ops in contiguous memory from the independent subtables void construct_full_eccvm_ops_table() { eccvm_ops_reconstructed = eccvm_ops_table.get_reconstructed(); } size_t get_ultra_ops_table_size() const { return ultra_ops_table.ultra_table_size(); } size_t get_current_ultra_ops_subtable_size() const { return ultra_ops_table.current_ultra_subtable_size(); } + // Get the full table of ECCVM ops in contiguous memory; construct it if it has not been constructed already std::vector& get_eccvm_ops() { if (eccvm_ops_reconstructed.empty()) { @@ -109,7 +114,7 @@ class ECCOpQueue { } /** - * @brief A fuzzing only method for setting raw ops directly + * @brief A fuzzing only method for setting eccvm ops directly * */ void set_eccvm_ops_for_fuzzing(std::vector& eccvm_ops_in) @@ -118,7 +123,7 @@ class ECCOpQueue { } /** - * @brief A testing only method that adds an erroneous equality op to the raw ops + * @brief A testing only method that adds an erroneous equality op to the eccvm ops * @brief May be used to ensure that ECCVM responds as expected when encountering a bad op * */ @@ -146,7 +151,7 @@ class ECCOpQueue { // Update the accumulator natively accumulator = accumulator + to_add; - // Store the raw operation + // Store the eccvm operation append_eccvm_op(ECCVMOperation{ .add = true, .base_point = to_add }); // Construct and store the operation in the ultra op format @@ -166,7 +171,7 @@ class ECCOpQueue { // Construct and store the operation in the ultra op format UltraOp ultra_op = construct_and_populate_ultra_ops(MUL_ACCUM, to_mul, scalar); - // Store the raw operation + // Store the eccvm operation append_eccvm_op(ECCVMOperation{ .mul = true, .base_point = to_mul, @@ -184,7 +189,7 @@ class ECCOpQueue { */ UltraOp no_op() { - // Store raw operation + // Store eccvm operation append_eccvm_op(ECCVMOperation{}); // Construct and store the operation in the ultra op format @@ -201,7 +206,7 @@ class ECCOpQueue { auto expected = accumulator; accumulator.self_set_infinity(); - // Store raw operation + // Store eccvm operation append_eccvm_op(ECCVMOperation{ .eq = true, .reset = true, .base_point = expected }); // Construct and store the operation in the ultra op format diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index be41d912a118..1f051af8b31a 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -75,9 +75,9 @@ TEST(ECCOpQueueTest, ColumnPolynomialConstruction) // Construct column polynomials corresponding to the full table (T), the previous table (T_prev), and the current // subtable (t_current) - std::array, 4> table_polynomials = op_queue->get_ultra_ops_table_columns(); - std::array, 4> previous_table_polynomials = op_queue->get_previous_ultra_ops_table_columns(); - std::array, 4> subtable_polynomials = op_queue->get_current_subtable_columns(); + std::array, 4> table_polynomials = op_queue->construct_ultra_ops_table_columns(); + std::array, 4> previous_table_polynomials = op_queue->construct_previous_ultra_ops_table_columns(); + std::array, 4> subtable_polynomials = op_queue->construct_current_ultra_ops_subtable_columns(); // Check that the table polynomials are constructed correctly by checking the following identity at a single point: // T(x) = t_current(x) + x^k * T_prev(x), where k is the size of the current subtable diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index fc73fc95bbf4..59fe4fd8c714 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -176,7 +176,7 @@ class UltraEccOpsTable { return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); } - ColumnPolynomials construct_current_subtable_columns() const + ColumnPolynomials construct_current_ultra_ops_subtable_columns() const { const size_t poly_size = current_ultra_subtable_size(); const size_t subtable_start_idx = 0; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp index 25b6004a040c..748d224500aa 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.test.cpp @@ -43,11 +43,11 @@ class EccOpsTableTest : public ::testing::Test { size_t size() const { return columns[0].size(); } }; - // Mock raw ops table that constructs a concatenated table from successively prepended subtables - struct MockRawOpsTable { + // Mock eccvm ops table that constructs a concatenated table from successively prepended subtables + struct MockEccvmOpsTable { std::vector eccvm_ops; - MockRawOpsTable(const auto& subtable_ops) + MockEccvmOpsTable(const auto& subtable_ops) { for (auto& ops : std::ranges::reverse_view(subtable_ops)) { for (const auto& op : ops) { @@ -124,12 +124,12 @@ TEST(EccOpsTableTest, UltraOpsTable) } } -// Ensure RawOpsTable correctly constructs a concatenated table from successively prepended subtables -TEST(EccOpsTableTest, RawOpsTable) +// Ensure EccvmOpsTable correctly constructs a concatenated table from successively prepended subtables +TEST(EccOpsTableTest, EccvmOpsTable) { using ECCVMOperation = bb::eccvm::VMOperation; - // Construct sets of raw ops, each representing those added by a single circuit + // Construct sets of eccvm ops, each representing those added by a single circuit const size_t NUM_SUBTABLES = 3; std::array, NUM_SUBTABLES> subtable_eccvm_ops; std::array subtable_op_counts = { 4, 2, 7 }; @@ -139,10 +139,10 @@ TEST(EccOpsTableTest, RawOpsTable) } } - // Construct the mock raw ops table which contains the subtables ordered in reverse (as if prepended) - EccOpsTableTest::MockRawOpsTable expected_eccvm_ops_table(subtable_eccvm_ops); + // Construct the mock eccvm ops table which contains the subtables ordered in reverse (as if prepended) + EccOpsTableTest::MockEccvmOpsTable expected_eccvm_ops_table(subtable_eccvm_ops); - // Construct the concatenated raw ops table + // Construct the concatenated eccvm ops table EccvmOpsTable eccvm_ops_table; for (const auto& subtable_ops : subtable_eccvm_ops) { eccvm_ops_table.create_new_subtable(); @@ -160,6 +160,6 @@ TEST(EccOpsTableTest, RawOpsTable) EXPECT_EQ(expected_eccvm_ops_table.eccvm_ops[i], eccvm_ops_table[i]); } - // Check that the copy-based reconstruction of the raw ops table matches the expected table + // Check that the copy-based reconstruction of the eccvm ops table matches the expected table EXPECT_EQ(expected_eccvm_ops_table.eccvm_ops, eccvm_ops_table.get_reconstructed()); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index a591050c773d..edfacc980903 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -38,9 +38,9 @@ template HonkProof MergeProver_::construct_proof() transcript = std::make_shared(); // Extract columns of the full table T_j, the previous table T_{j,prev}, and the current subtable t_j - std::array T_current = op_queue->get_ultra_ops_table_columns(); - std::array T_prev = op_queue->get_previous_ultra_ops_table_columns(); - std::array t_current = op_queue->get_current_subtable_columns(); + std::array T_current = op_queue->construct_ultra_ops_table_columns(); + std::array T_prev = op_queue->construct_previous_ultra_ops_table_columns(); + std::array t_current = op_queue->construct_current_ultra_ops_subtable_columns(); // TODO(#723): Cannot currently support an empty T_prev. Need to be able to properly handle zero commitment. ASSERT(T_prev[0].size() > 0); From 292fe035f49735ac128d1aa25d30051bf973079f Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Tue, 25 Feb 2025 22:23:11 +0000 Subject: [PATCH 32/33] cleann --- .../merge_recursive_verifier.cpp | 6 +- .../op_queue/ecc_op_queue.hpp | 12 ++-- .../op_queue/ecc_op_queue.test.cpp | 57 ++++++++----------- .../op_queue/ecc_ops_table.hpp | 15 +++-- .../barretenberg/ultra_honk/merge_prover.cpp | 5 +- .../ultra_honk/merge_verifier.cpp | 2 +- 6 files changed, 48 insertions(+), 49 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp index 2fca18dd68e6..727b304385d9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp @@ -8,10 +8,10 @@ MergeRecursiveVerifier_::MergeRecursiveVerifier_(CircuitBuilder* {} /** - * @brief Reduce verification of proper construction of the aggregate Goblin ECC op queue polynomials T_j, j = 1,2,3,4 - * to a set of inputs to a pairing check. + * @brief Computes inputs to a pairing check that, if verified, establishes proper construction of the aggregate Goblin + * ECC op queue polynomials T_j, j = 1,2,3,4. * @details Let T_j be the jth column of the aggregate ecc op table after prepending the subtable columns t_j containing - * the contribution from the present circuit. T_{j,prev} corresponds to the columns of the aggregate table at the + * the contribution from a single circuit. T_{j,prev} corresponds to the columns of the aggregate table at the * previous stage. For each column we have the relationship T_j = t_j + right_shift(T_{j,prev}, k), where k is the * length of the subtable columns t_j. This protocol demonstrates, assuming the length of t is at most k, that the * aggregate ecc op table has been constructed correctly via the simple Schwartz-Zippel check: diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index d896fa6e82c0..cedd02db70a4 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -42,7 +42,7 @@ class ECCOpQueue { public: using ECCVMOperation = bb::eccvm::VMOperation; - // Constructor simply prepares the first subtable to be written to + // Constructor that instantiates an initial ECC op subtable ECCOpQueue() { initialize_new_subtable(); } // Initialize a new subtable of ECCVM ops and Ultra ops corresponding to an individual circuit @@ -58,7 +58,7 @@ class ECCOpQueue { return ultra_ops_table.construct_table_columns(); } - // Construct polynomials corresponding to columns of the aggregate ultra ops table excluding most recent subtable + // Construct polys corresponding to the columns of the aggregate ultra ops table, excluding the most recent subtable std::array, 4> construct_previous_ultra_ops_table_columns() const { return ultra_ops_table.construct_previous_table_columns(); @@ -73,8 +73,8 @@ class ECCOpQueue { // Reconstruct the full table of eccvm ops in contiguous memory from the independent subtables void construct_full_eccvm_ops_table() { eccvm_ops_reconstructed = eccvm_ops_table.get_reconstructed(); } - size_t get_ultra_ops_table_size() const { return ultra_ops_table.ultra_table_size(); } - size_t get_current_ultra_ops_subtable_size() const { return ultra_ops_table.current_ultra_subtable_size(); } + size_t get_ultra_ops_table_num_rows() const { return ultra_ops_table.ultra_table_size(); } + size_t get_current_ultra_ops_subtable_num_rows() const { return ultra_ops_table.current_ultra_subtable_size(); } // Get the full table of ECCVM ops in contiguous memory; construct it if it has not been constructed already std::vector& get_eccvm_ops() @@ -214,6 +214,10 @@ class ECCOpQueue { } private: + /** + * @brief Append an eccvm operation to the eccvm ops table; update the eccvm row tracker + * + */ void append_eccvm_op(const ECCVMOperation& op) { eccvm_row_tracker.update_cached_msms(op); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index 1f051af8b31a..bfcecbd7fbdc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -68,40 +68,33 @@ TEST(ECCOpQueueTest, ColumnPolynomialConstruction) // Instantiate and EccOpQueue and populate it with several subtables of ECC ops auto op_queue = std::make_shared(); + // Lambda for checking that the table column polynomials reconstructed by the op queue have the correct relationship + auto check_table_column_polynomials = [&](const std::shared_ptr& op_queue) { + // Construct column polynomials corresponding to the full table (T), the previous table (T_prev), and the + // current subtable (t_current) + std::array, 4> table_polynomials = op_queue->construct_ultra_ops_table_columns(); + std::array, 4> prev_table_polynomials = op_queue->construct_previous_ultra_ops_table_columns(); + std::array, 4> subtable_polynomials = op_queue->construct_current_ultra_ops_subtable_columns(); + // Check that the table polynomials are constructed correctly by checking the following identity at a single + // point: T(x) = t_current(x) + x^k * T_prev(x), where k is the size of the current subtable + const size_t current_subtable_size = op_queue->get_current_ultra_ops_subtable_num_rows(); + + // Check T(x) = t_current(x) + x^k * T_prev(x) at a single random challenge point + Fr eval_challenge = Fr::random_element(); + for (auto [table_poly, prev_table_poly, subtable_poly] : + zip_view(table_polynomials, prev_table_polynomials, subtable_polynomials)) { + Fr table_eval = table_poly.evaluate(eval_challenge); // T(x) + Fr subtable_eval = subtable_poly.evaluate(eval_challenge); // t_current(x) + Fr shifted_previous_table_eval = + prev_table_poly.evaluate(eval_challenge) * eval_challenge.pow(current_subtable_size); // x^k * T_prev(x) + EXPECT_EQ(table_eval, subtable_eval + shifted_previous_table_eval); + } + }; + + // Check that the table polynomials have the correct form after each subtable concatenation const size_t NUM_SUBTABLES = 5; for (size_t i = 0; i < NUM_SUBTABLES; ++i) { ECCOpQueueTest::populate_an_arbitrary_subtable_of_ops(op_queue); - } - - // Construct column polynomials corresponding to the full table (T), the previous table (T_prev), and the current - // subtable (t_current) - std::array, 4> table_polynomials = op_queue->construct_ultra_ops_table_columns(); - std::array, 4> previous_table_polynomials = op_queue->construct_previous_ultra_ops_table_columns(); - std::array, 4> subtable_polynomials = op_queue->construct_current_ultra_ops_subtable_columns(); - - // Check that the table polynomials are constructed correctly by checking the following identity at a single point: - // T(x) = t_current(x) + x^k * T_prev(x), where k is the size of the current subtable - const size_t current_subtable_size = op_queue->get_current_ultra_ops_subtable_size(); - - Fr eval_challenge = Fr::random_element(); - - std::array table_evals; - std::array shifted_previous_table_evals; - std::array subtable_evals; - for (auto [eval, poly] : zip_view(table_evals, table_polynomials)) { - eval = poly.evaluate(eval_challenge); // T(x) - } - for (auto [eval, poly] : zip_view(shifted_previous_table_evals, previous_table_polynomials)) { - eval = poly.evaluate(eval_challenge); - eval *= eval_challenge.pow(current_subtable_size); // x^k * T_prev(x) - } - for (auto [eval, poly] : zip_view(subtable_evals, subtable_polynomials)) { - eval = poly.evaluate(eval_challenge); // t_current(x) - } - - // Check T(x) = t_current(x) + x^k * T_prev(x) - for (auto [table_eval, shifted_previous_table_eval, subtable_eval] : - zip_view(table_evals, shifted_previous_table_evals, subtable_evals)) { - EXPECT_EQ(table_eval, subtable_eval + shifted_previous_table_eval); + check_table_column_polynomials(op_queue); } } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index 59fe4fd8c714..7deff03cd1c9 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -105,8 +105,8 @@ using EccvmOpsTable = EccOpsTable>; * polynomials in the proving system. */ class UltraEccOpsTable { - static constexpr size_t TABLE_WIDTH = 4; - static constexpr size_t NUM_ROWS_PER_OP = 2; + static constexpr size_t TABLE_WIDTH = 4; // dictated by the number of wires in the Ultra arithmetization + static constexpr size_t NUM_ROWS_PER_OP = 2; // A single ECC op is split across two width-4 rows using Curve = curve::BN254; using Fr = Curve::ScalarField; @@ -127,7 +127,7 @@ class UltraEccOpsTable { /** * @brief Construct polynomials corresponding to the columns of the reconstructed ultra ops table for the given * range of subtables - * @todo multithreaded this functionality + * TODO(https://github.com/AztecProtocol/barretenberg/issues/1267): multithreaded this functionality * @param target_columns */ ColumnPolynomials construct_column_polynomials_from_subtables(const size_t poly_size, @@ -158,29 +158,32 @@ class UltraEccOpsTable { return column_polynomials; } + // Construct the columns of the full ultra ecc ops table ColumnPolynomials construct_table_columns() const { const size_t poly_size = ultra_table_size(); - const size_t subtable_start_idx = 0; + const size_t subtable_start_idx = 0; // include all subtables const size_t subtable_end_idx = table.num_subtables(); return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); } + // Construct the columns of the previous full ultra ecc ops table ColumnPolynomials construct_previous_table_columns() const { const size_t poly_size = previous_ultra_table_size(); - const size_t subtable_start_idx = 1; + const size_t subtable_start_idx = 1; // exclude the 0th subtable const size_t subtable_end_idx = table.num_subtables(); return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); } + // Construct the columns of the current ultra ecc ops subtable ColumnPolynomials construct_current_ultra_ops_subtable_columns() const { const size_t poly_size = current_ultra_subtable_size(); const size_t subtable_start_idx = 0; - const size_t subtable_end_idx = 1; + const size_t subtable_end_idx = 1; // include only the 0th subtable return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); } diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index edfacc980903..3d92b61daad4 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -15,7 +15,7 @@ MergeProver_::MergeProver_(const std::shared_ptr& op_queue, { // Update internal size data in the op queue that allows for extraction of e.g. previous aggregate transcript pcs_commitment_key = - commitment_key ? commitment_key : std::make_shared(op_queue->get_ultra_ops_table_size()); + commitment_key ? commitment_key : std::make_shared(op_queue->get_ultra_ops_table_num_rows()); } /** @@ -28,8 +28,7 @@ MergeProver_::MergeProver_(const std::shared_ptr& op_queue, * * T_j(\kappa) = t_j(\kappa) + \kappa^k * (T_{j,prev}(\kappa)). * - * TODO(#746): Prove connection between t^{shift}, committed to herein, and t, used in the main protocol. See issue - * for details (https://github.com/AztecProtocol/barretenberg/issues/746). + * TODO(https://github.com/AztecProtocol/barretenberg/issues/1270): connect [t_j] used herein those used in PG verifier * * @return honk::proof */ diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp index 1d636abf30c3..9569d44038d8 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_verifier.cpp @@ -12,7 +12,7 @@ MergeVerifier_::MergeVerifier_() /** * @brief Verify proper construction of the aggregate Goblin ECC op queue polynomials T_j, j = 1,2,3,4. * @details Let T_j be the jth column of the aggregate ecc op table after prepending the subtable columns t_j containing - * the contribution from the present circuit. T_{j,prev} corresponds to the columns of the aggregate table at the + * the contribution from a single circuit. T_{j,prev} corresponds to the columns of the aggregate table at the * previous stage. For each column we have the relationship T_j = t_j + right_shift(T_{j,prev}, k), where k is the * length of the subtable columns t_j. This protocol demonstrates, assuming the length of t is at most k, that the * aggregate ecc op table has been constructed correctly via the simple Schwartz-Zippel check: From fe835998257af215fe10264eea2e803532cee1dc Mon Sep 17 00:00:00 2001 From: ledwards2225 Date: Wed, 26 Feb 2025 14:48:28 +0000 Subject: [PATCH 33/33] cleanup based on review comments --- .../merge_recursive_verifier.cpp | 9 ++- .../op_queue/ecc_op_queue.hpp | 7 +- .../op_queue/ecc_op_queue.test.cpp | 8 +-- .../op_queue/ecc_ops_table.hpp | 65 ++++++++++--------- .../barretenberg/ultra_honk/merge_prover.cpp | 8 +-- 5 files changed, 50 insertions(+), 47 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp index 727b304385d9..41fa0356b542 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/goblin_verifier/merge_recursive_verifier.cpp @@ -48,7 +48,7 @@ std::array::Element, 2> MergeRecursiveVerifier_ t_evals; std::array T_prev_evals; - std::array T_current_evals; + std::array T_evals; std::vector opening_claims; for (size_t idx = 0; idx < NUM_WIRES; ++idx) { t_evals[idx] = transcript->template receive_from_prover("t_eval_" + std::to_string(idx + 1)); @@ -59,15 +59,14 @@ std::array::Element, 2> MergeRecursiveVerifier_template receive_from_prover("T_current_eval_" + std::to_string(idx + 1)); - opening_claims.emplace_back(OpeningClaim{ { kappa, T_current_evals[idx] }, T_commitments[idx] }); + T_evals[idx] = transcript->template receive_from_prover("T_eval_" + std::to_string(idx + 1)); + opening_claims.emplace_back(OpeningClaim{ { kappa, T_evals[idx] }, T_commitments[idx] }); } // Check the identity T_j(\kappa) = t_j(\kappa) + \kappa^m * T_{j,prev}(\kappa) for (size_t idx = 0; idx < NUM_WIRES; ++idx) { FF T_prev_shifted_eval_reconstructed = T_prev_evals[idx] * kappa.pow(subtable_size); - T_current_evals[idx].assert_equal(t_evals[idx] + T_prev_shifted_eval_reconstructed); + T_evals[idx].assert_equal(t_evals[idx] + T_prev_shifted_eval_reconstructed); } FF alpha = transcript->template get_challenge("alpha"); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp index cedd02db70a4..2f2634c180b5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp @@ -22,6 +22,7 @@ class ECCOpQueue { using Point = Curve::AffineElement; using Fr = Curve::ScalarField; using Fq = Curve::BaseField; // Grumpkin's scalar field + static constexpr size_t ULTRA_TABLE_WIDTH = UltraEccOpsTable::TABLE_WIDTH; Point point_at_infinity = Curve::Group::affine_point_at_infinity; // The operations written to the queue are also performed natively; the result is stored in accumulator @@ -53,19 +54,19 @@ class ECCOpQueue { } // Construct polynomials corresponding to the columns of the full aggregate ultra ecc ops table - std::array, 4> construct_ultra_ops_table_columns() const + std::array, ULTRA_TABLE_WIDTH> construct_ultra_ops_table_columns() const { return ultra_ops_table.construct_table_columns(); } // Construct polys corresponding to the columns of the aggregate ultra ops table, excluding the most recent subtable - std::array, 4> construct_previous_ultra_ops_table_columns() const + std::array, ULTRA_TABLE_WIDTH> construct_previous_ultra_ops_table_columns() const { return ultra_ops_table.construct_previous_table_columns(); } // Construct polynomials corresponding to the columns of the current subtable of ultra ecc ops - std::array, 4> construct_current_ultra_ops_subtable_columns() const + std::array, ULTRA_TABLE_WIDTH> construct_current_ultra_ops_subtable_columns() const { return ultra_ops_table.construct_current_ultra_ops_subtable_columns(); } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp index bfcecbd7fbdc..213713b6773d 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.test.cpp @@ -65,16 +65,16 @@ TEST(ECCOpQueueTest, ColumnPolynomialConstruction) { using Fr = fr; - // Instantiate and EccOpQueue and populate it with several subtables of ECC ops + // Instantiate an EccOpQueue and populate it with several subtables of ECC ops auto op_queue = std::make_shared(); // Lambda for checking that the table column polynomials reconstructed by the op queue have the correct relationship auto check_table_column_polynomials = [&](const std::shared_ptr& op_queue) { // Construct column polynomials corresponding to the full table (T), the previous table (T_prev), and the // current subtable (t_current) - std::array, 4> table_polynomials = op_queue->construct_ultra_ops_table_columns(); - std::array, 4> prev_table_polynomials = op_queue->construct_previous_ultra_ops_table_columns(); - std::array, 4> subtable_polynomials = op_queue->construct_current_ultra_ops_subtable_columns(); + auto table_polynomials = op_queue->construct_ultra_ops_table_columns(); + auto prev_table_polynomials = op_queue->construct_previous_ultra_ops_table_columns(); + auto subtable_polynomials = op_queue->construct_current_ultra_ops_subtable_columns(); // Check that the table polynomials are constructed correctly by checking the following identity at a single // point: T(x) = t_current(x) + x^k * T_prev(x), where k is the size of the current subtable const size_t current_subtable_size = op_queue->get_current_ultra_ops_subtable_num_rows(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp index 7deff03cd1c9..f8db7c381465 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/op_queue/ecc_ops_table.hpp @@ -105,9 +105,11 @@ using EccvmOpsTable = EccOpsTable>; * polynomials in the proving system. */ class UltraEccOpsTable { + public: static constexpr size_t TABLE_WIDTH = 4; // dictated by the number of wires in the Ultra arithmetization static constexpr size_t NUM_ROWS_PER_OP = 2; // A single ECC op is split across two width-4 rows + private: using Curve = curve::BN254; using Fr = Curve::ScalarField; using UltraOpsTable = EccOpsTable; @@ -124,10 +126,41 @@ class UltraEccOpsTable { void create_new_subtable(size_t size_hint = 0) { table.create_new_subtable(size_hint); } void push(const UltraOp& op) { table.push(op); } + // Construct the columns of the full ultra ecc ops table + ColumnPolynomials construct_table_columns() const + { + const size_t poly_size = ultra_table_size(); + const size_t subtable_start_idx = 0; // include all subtables + const size_t subtable_end_idx = table.num_subtables(); + + return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); + } + + // Construct the columns of the previous full ultra ecc ops table + ColumnPolynomials construct_previous_table_columns() const + { + const size_t poly_size = previous_ultra_table_size(); + const size_t subtable_start_idx = 1; // exclude the 0th subtable + const size_t subtable_end_idx = table.num_subtables(); + + return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); + } + + // Construct the columns of the current ultra ecc ops subtable + ColumnPolynomials construct_current_ultra_ops_subtable_columns() const + { + const size_t poly_size = current_ultra_subtable_size(); + const size_t subtable_start_idx = 0; + const size_t subtable_end_idx = 1; // include only the 0th subtable + + return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); + } + + private: /** * @brief Construct polynomials corresponding to the columns of the reconstructed ultra ops table for the given * range of subtables - * TODO(https://github.com/AztecProtocol/barretenberg/issues/1267): multithreaded this functionality + * TODO(https://github.com/AztecProtocol/barretenberg/issues/1267): multithread this functionality * @param target_columns */ ColumnPolynomials construct_column_polynomials_from_subtables(const size_t poly_size, @@ -157,36 +190,6 @@ class UltraEccOpsTable { } return column_polynomials; } - - // Construct the columns of the full ultra ecc ops table - ColumnPolynomials construct_table_columns() const - { - const size_t poly_size = ultra_table_size(); - const size_t subtable_start_idx = 0; // include all subtables - const size_t subtable_end_idx = table.num_subtables(); - - return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); - } - - // Construct the columns of the previous full ultra ecc ops table - ColumnPolynomials construct_previous_table_columns() const - { - const size_t poly_size = previous_ultra_table_size(); - const size_t subtable_start_idx = 1; // exclude the 0th subtable - const size_t subtable_end_idx = table.num_subtables(); - - return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); - } - - // Construct the columns of the current ultra ecc ops subtable - ColumnPolynomials construct_current_ultra_ops_subtable_columns() const - { - const size_t poly_size = current_ultra_subtable_size(); - const size_t subtable_start_idx = 0; - const size_t subtable_end_idx = 1; // include only the 0th subtable - - return construct_column_polynomials_from_subtables(poly_size, subtable_start_idx, subtable_end_idx); - } }; } // namespace bb diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp index 3d92b61daad4..7d872aec97f3 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/merge_prover.cpp @@ -37,9 +37,9 @@ template HonkProof MergeProver_::construct_proof() transcript = std::make_shared(); // Extract columns of the full table T_j, the previous table T_{j,prev}, and the current subtable t_j - std::array T_current = op_queue->construct_ultra_ops_table_columns(); - std::array T_prev = op_queue->construct_previous_ultra_ops_table_columns(); - std::array t_current = op_queue->construct_current_ultra_ops_subtable_columns(); + std::array T_current = op_queue->construct_ultra_ops_table_columns(); + std::array T_prev = op_queue->construct_previous_ultra_ops_table_columns(); + std::array t_current = op_queue->construct_current_ultra_ops_subtable_columns(); // TODO(#723): Cannot currently support an empty T_prev. Need to be able to properly handle zero commitment. ASSERT(T_prev[0].size() > 0); @@ -90,7 +90,7 @@ template HonkProof MergeProver_::construct_proof() FF alpha = transcript->template get_challenge("alpha"); - // Construct batched polynomial to opened via KZG + // Construct batched polynomial to be opened via KZG Polynomial batched_polynomial(current_table_size); FF batched_eval(0); FF alpha_pow(1);