diff --git a/barretenberg/cpp/bootstrap.sh b/barretenberg/cpp/bootstrap.sh index a323eb601cc..bd82cc67e1c 100755 --- a/barretenberg/cpp/bootstrap.sh +++ b/barretenberg/cpp/bootstrap.sh @@ -106,6 +106,7 @@ fi if [ ! -d ./srs_db/grumpkin ]; then # The Grumpkin SRS is generated manually at the moment, only up to a large enough size for tests - # If tests require more points, the parameter can be increased here. - cd ./build && cmake --build . --parallel --target grumpkin_srs_gen && ./bin/grumpkin_srs_gen 8192 + # If tests require more points, the parameter can be increased here. Note: IPA requires + # dyadic_circuit_size + 1 points so in general this number will be a power of two plus 1 + cd ./build && cmake --build . --parallel --target grumpkin_srs_gen && ./bin/grumpkin_srs_gen 8193 fi diff --git a/barretenberg/cpp/src/barretenberg/bb/main.cpp b/barretenberg/cpp/src/barretenberg/bb/main.cpp index f1814970b3a..265c402bdcc 100644 --- a/barretenberg/cpp/src/barretenberg/bb/main.cpp +++ b/barretenberg/cpp/src/barretenberg/bb/main.cpp @@ -347,7 +347,8 @@ void client_ivc_prove_output_all_msgpack(const std::string& bytecodePath, } // TODO(#7371) dedupe this with the rest of the similar code ClientIVC ivc; - ivc.structured_flag = true; + ivc.trace_structure = TraceStructure::E2E_FULL_TEST; + // Accumulate the entire program stack into the IVC for (Program& program : folding_stack) { // auto& stack_item = program_stack.witness_stack[i]; @@ -390,7 +391,7 @@ bool foldAndVerifyProgram(const std::string& bytecodePath, const std::string& wi init_grumpkin_crs(1 << 16); ClientIVC ivc; - ivc.structured_flag = true; + ivc.trace_structure = TraceStructure::SMALL_TEST; auto program_stack = acir_format::get_acir_program_stack( bytecodePath, witnessPath, false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): this @@ -432,7 +433,7 @@ void client_ivc_prove_output_all(const std::string& bytecodePath, init_grumpkin_crs(1 << 16); ClientIVC ivc; - ivc.structured_flag = true; + ivc.trace_structure = TraceStructure::E2E_FULL_TEST; auto program_stack = acir_format::get_acir_program_stack( bytecodePath, witnessPath, false); // TODO(https://github.com/AztecProtocol/barretenberg/issues/1013): this diff --git a/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp b/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp index 8877cf7b0a7..00eb07d7549 100644 --- a/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp +++ b/barretenberg/cpp/src/barretenberg/benchmark/client_ivc_bench/client_ivc.bench.cpp @@ -172,7 +172,7 @@ BENCHMARK_DEFINE_F(ClientIVCBench, Full)(benchmark::State& state) BENCHMARK_DEFINE_F(ClientIVCBench, FullStructured)(benchmark::State& state) { ClientIVC ivc; - ivc.structured_flag = true; + ivc.trace_structure = TraceStructure::CLIENT_IVC_BENCH; auto num_circuits = static_cast(state.range(0)); auto precomputed_vks = precompute_verification_keys(ivc, num_circuits); diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp index 20447026342..2cea607effc 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.cpp @@ -26,7 +26,7 @@ void ClientIVC::accumulate(ClientCircuit& circuit, const std::shared_ptr(circuit, structured_flag); + prover_instance = std::make_shared(circuit, trace_structure); // Track the maximum size of each block for all circuits porcessed (for debugging purposes only) max_block_sizes.update(circuit); @@ -116,10 +116,10 @@ std::vector> ClientIVC::precompute_f vkeys.emplace_back(instance_vk); } - // Reset the scheme so it can be reused for actual accumulation, maintaining the structured trace flag as is - bool structured = structured_flag; + // Reset the scheme so it can be reused for actual accumulation, maintaining the trace structure setting as is + TraceStructure structure = trace_structure; *this = ClientIVC(); - this->structured_flag = structured; + this->trace_structure = structure; return vkeys; } diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp index 115bf6ef55a..c002816dd7a 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.hpp @@ -112,7 +112,7 @@ class ClientIVC { std::shared_ptr instance_vk; // A flag indicating whether or not to construct a structured trace in the ProverInstance - bool structured_flag = false; + TraceStructure trace_structure = TraceStructure::NONE; // A flag indicating whether the IVC has been initialized with an initial instance bool initialized = false; diff --git a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp index 5443fb76a27..5a977dd75bf 100644 --- a/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp +++ b/barretenberg/cpp/src/barretenberg/client_ivc/client_ivc.test.cpp @@ -146,12 +146,12 @@ TEST_F(ClientIVCTests, BasicLarge) TEST_F(ClientIVCTests, BasicStructured) { ClientIVC ivc; - ivc.structured_flag = true; + ivc.trace_structure = TraceStructure::SMALL_TEST; // Construct some circuits of varying size Builder circuit_0 = create_mock_circuit(ivc, /*log2_num_gates=*/5); - Builder circuit_1 = create_mock_circuit(ivc, /*log2_num_gates=*/10); - Builder circuit_2 = create_mock_circuit(ivc, /*log2_num_gates=*/15); + Builder circuit_1 = create_mock_circuit(ivc, /*log2_num_gates=*/8); + Builder circuit_2 = create_mock_circuit(ivc, /*log2_num_gates=*/11); // The circuits can be accumulated as normal due to the structured trace ivc.accumulate(circuit_0); @@ -194,13 +194,13 @@ TEST_F(ClientIVCTests, PrecomputedVerificationKeys) TEST_F(ClientIVCTests, StructuredPrecomputedVKs) { ClientIVC ivc; - ivc.structured_flag = true; + ivc.trace_structure = TraceStructure::SMALL_TEST; // Construct a set of arbitrary circuits size_t NUM_CIRCUITS = 3; std::vector circuits; for (size_t idx = 0; idx < NUM_CIRCUITS; ++idx) { - circuits.emplace_back(create_mock_circuit(ivc)); + circuits.emplace_back(create_mock_circuit(ivc, /*log2_num_gates=*/5)); } // Precompute the (structured) verification keys that will be needed for the IVC diff --git a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp index 934b6dae9de..61a3be1d93f 100644 --- a/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp +++ b/barretenberg/cpp/src/barretenberg/commitment_schemes/commitment_key.hpp @@ -71,7 +71,13 @@ template class CommitmentKey { { BB_OP_COUNT_TIME(); const size_t degree = polynomial.size(); - ASSERT(degree <= srs->get_monomial_size()); + if (degree > srs->get_monomial_size()) { + info("Attempting to commit to a polynomial of degree ", + degree, + " with an SRS of size ", + srs->get_monomial_size()); + ASSERT(false); + } return scalar_multiplication::pippenger_unsafe( const_cast(polynomial.data()), srs->get_monomial_points(), degree, pippenger_runtime_state); }; diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp index 2842056f848..c0f889b432f 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_format/acir_integration.test.cpp @@ -405,7 +405,7 @@ TEST_P(AcirIntegrationFoldingTest, DISABLED_FoldAndVerifyProgramStack) // Assumes Flavor is not UltraHonk ClientIVC ivc; - ivc.structured_flag = true; + ivc.trace_structure = TraceStructure::SMALL_TEST; while (!program_stack.empty()) { auto program = program_stack.back(); diff --git a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp index 3db10487480..460dd9c4471 100644 --- a/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp +++ b/barretenberg/cpp/src/barretenberg/dsl/acir_proofs/c_bind.cpp @@ -91,7 +91,7 @@ WASM_EXPORT void acir_fold_and_verify_program_stack(uint8_t const* acir_vec, uin ProgramStack program_stack{ constraint_systems, witness_stack }; ClientIVC ivc; - ivc.structured_flag = true; + ivc.trace_structure = TraceStructure::SMALL_TEST; while (!program_stack.empty()) { auto stack_item = program_stack.back(); diff --git a/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp b/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp index 0f0d5c96891..ecddaeef9cc 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/proof_system/types/prover_settings.hpp @@ -1,5 +1,5 @@ #pragma once -#include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" +#include "barretenberg/plonk_honk_shared/arithmetization/standard_arithmetization.hpp" #include "barretenberg/transcript/transcript.hpp" namespace bb::plonk { class settings_base { diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp index e31d31b871a..a32d7d83f09 100644 --- a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp @@ -1,40 +1,13 @@ #pragma once #include "barretenberg/common/ref_array.hpp" -#include "barretenberg/ecc/curves/bn254/bn254.hpp" -#include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" -#include -#include #include -#include + #ifdef CHECK_CIRCUIT_STACKTRACES #include #endif namespace bb { -/** - * @brief Specify the structure of a CircuitBuilder - * - * @details This is typically passed as a template argument specifying the structure of a circuit constructor. It - * should only ever contain circuit constructor data--it should not contain data that is particular to any - * proving system. - * - * @remark It may make sense to say this is only partial arithmetization data, with the full data being - * contained in the circuit constructor. We could change the name of this class if it conflicts with common usage. - * - * @note For even greater modularity, in each instantiation we could specify a list of components here, where a - * component is a meaningful collection of functions for creating gates, as in: - * - * struct Component { - * using Arithmetic = component::Arithmetic3Wires; - * using RangeConstraints = component::Base4Accumulators or component::DeltaRangeConstraint or... - * using LookupTables = component::Plookup4Wire or component::CQ8Wire or... - * ... - * }; - * - * We should only do this if it becomes necessary or convenient. - */ - #ifdef CHECK_CIRCUIT_STACKTRACES struct BbStackTrace : backward::StackTrace { BbStackTrace() { load_here(32); } @@ -52,6 +25,11 @@ struct StackTraces { }; #endif +// A set of fixed block size conigurations to be used with the structured execution trace. The actual block sizes +// corresponding to these settings are defined in the corresponding arithmetization classes (Ultra/Mega). For efficiency +// it is best to use the smallest possible block sizes to accommodate a given situation. +enum class TraceStructure { NONE, SMALL_TEST, CLIENT_IVC_BENCH, E2E_FULL_TEST }; + /** * @brief Basic structure for storing gate data in a builder * @@ -76,7 +54,7 @@ template class ExecutionTr bool has_ram_rom = false; // does the block contain RAM/ROM gates bool is_pub_inputs = false; // is this the public inputs block - uint32_t fixed_size; // Fixed size for use in structured trace + uint32_t fixed_size = 0; // Fixed size for use in structured trace bool operator==(const ExecutionTraceBlock& other) const = default; @@ -99,341 +77,10 @@ template class ExecutionTr void set_fixed_size(uint32_t size_in) { fixed_size = size_in; } }; -// These are not magic numbers and they should not be written with global constants. These parameters are not -// accessible through clearly named static class members. -template class StandardArith { - public: - static constexpr size_t NUM_WIRES = 3; - static constexpr size_t NUM_SELECTORS = 5; - using FF = FF_; - - class StandardTraceBlock : public ExecutionTraceBlock { - public: - void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3) - { -#ifdef CHECK_CIRCUIT_STACKTRACES - this->stack_traces.populate(); -#endif - this->wires[0].emplace_back(idx_1); - this->wires[1].emplace_back(idx_2); - this->wires[2].emplace_back(idx_3); - } - - auto& w_l() { return std::get<0>(this->wires); }; - auto& w_r() { return std::get<1>(this->wires); }; - auto& w_o() { return std::get<2>(this->wires); }; - const auto& w_l() const { return std::get<0>(this->wires); }; - const auto& w_r() const { return std::get<1>(this->wires); }; - const auto& w_o() const { return std::get<2>(this->wires); }; - - auto& q_m() { return this->selectors[0]; }; - auto& q_1() { return this->selectors[1]; }; - auto& q_2() { return this->selectors[2]; }; - auto& q_3() { return this->selectors[3]; }; - auto& q_c() { return this->selectors[4]; }; - const auto& q_m() const { return this->selectors[0]; }; - const auto& q_1() const { return this->selectors[1]; }; - const auto& q_2() const { return this->selectors[2]; }; - const auto& q_3() const { return this->selectors[3]; }; - const auto& q_c() const { return this->selectors[4]; }; - }; - - struct TraceBlocks { - StandardTraceBlock pub_inputs; - StandardTraceBlock arithmetic; - - auto get() { return RefArray{ pub_inputs, arithmetic }; } - - bool operator==(const TraceBlocks& other) const = default; - }; - - // Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct. - inline static const std::vector selector_names = { "q_m", "q_1", "q_2", "q_3", "q_c" }; -}; - -template class UltraArith { - public: - static constexpr size_t NUM_WIRES = 4; - static constexpr size_t NUM_SELECTORS = 11; - using FF = FF_; - - class UltraTraceBlock : public ExecutionTraceBlock { - public: - void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4) - { -#ifdef CHECK_CIRCUIT_STACKTRACES - this->stack_traces.populate(); -#endif - this->wires[0].emplace_back(idx_1); - this->wires[1].emplace_back(idx_2); - this->wires[2].emplace_back(idx_3); - this->wires[3].emplace_back(idx_4); - } - - auto& w_l() { return std::get<0>(this->wires); }; - auto& w_r() { return std::get<1>(this->wires); }; - auto& w_o() { return std::get<2>(this->wires); }; - auto& w_4() { return std::get<3>(this->wires); }; - - auto& q_m() { return this->selectors[0]; }; - auto& q_c() { return this->selectors[1]; }; - auto& q_1() { return this->selectors[2]; }; - auto& q_2() { return this->selectors[3]; }; - auto& q_3() { return this->selectors[4]; }; - auto& q_4() { return this->selectors[5]; }; - auto& q_arith() { return this->selectors[6]; }; - auto& q_delta_range() { return this->selectors[7]; }; - auto& q_elliptic() { return this->selectors[8]; }; - auto& q_aux() { return this->selectors[9]; }; - auto& q_lookup_type() { return this->selectors[10]; }; - }; - - struct TraceBlocks { - UltraTraceBlock pub_inputs; - UltraTraceBlock arithmetic; - UltraTraceBlock delta_range; - UltraTraceBlock elliptic; - UltraTraceBlock aux; - UltraTraceBlock lookup; - - static constexpr uint32_t FIXED_BLOCK_SIZE = 1 << 10; // (Arbitrary for now) - std::array fixed_block_sizes{ - 1 << 3, // pub_inputs; - FIXED_BLOCK_SIZE, // arithmetic; - FIXED_BLOCK_SIZE, // delta_range; - FIXED_BLOCK_SIZE, // elliptic; - FIXED_BLOCK_SIZE, // aux; - FIXED_BLOCK_SIZE // lookup; - }; - - TraceBlocks() - { - aux.has_ram_rom = true; - pub_inputs.is_pub_inputs = true; - // Set fixed block sizes for use in structured trace - for (auto [block, size] : zip_view(this->get(), fixed_block_sizes)) { - block.set_fixed_size(size); - } - } - - auto get() { return RefArray{ pub_inputs, arithmetic, delta_range, elliptic, aux, lookup }; } - - void summarize() const - { - info("Gate blocks summary:"); - info("pub inputs :\t", pub_inputs.size()); - info("arithmetic :\t", arithmetic.size()); - info("delta range:\t", delta_range.size()); - info("elliptic :\t", elliptic.size()); - info("auxiliary :\t", aux.size()); - info("lookups :\t", lookup.size()); - } - - size_t get_total_structured_size() - { - size_t total_size = 0; - for (auto block : this->get()) { - total_size += block.get_fixed_size(); - } - return total_size; - } - - /** - * @brief Check that the number of rows populated in each block does not exceed the specified fixed size - * @note This check is only applicable when utilizing a structured trace - * - */ - void check_within_fixed_sizes() - { - for (auto block : this->get()) { - if (block.size() > block.get_fixed_size()) { - info("WARNING: Num gates in circuit block exceeds the specified fixed size - execution trace will " - "not be constructed correctly!"); - ASSERT(false); - } - } - } - - bool operator==(const TraceBlocks& other) const = default; - }; - - // Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct. - inline static const std::vector selector_names = { "q_m", "q_c", "q_1", "q_2", - "q_3", "q_4", "q_arith", "q_sort", - "q_elliptic", "q_aux", "table_type" }; -}; - -/** - * @brief Ultra Honk arithmetization - * @details Extends the conventional Ultra arithmetization with a new selector related to databus lookups - * - * @tparam FF_ - */ -template class UltraHonkArith { - public: - static constexpr size_t NUM_WIRES = 4; - static constexpr size_t NUM_SELECTORS = 14; - - using FF = FF_; - - class UltraHonkTraceBlock : public ExecutionTraceBlock { - public: - void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4) - { -#ifdef CHECK_CIRCUIT_STACKTRACES - this->stack_traces.populate(); -#endif - this->wires[0].emplace_back(idx_1); - this->wires[1].emplace_back(idx_2); - this->wires[2].emplace_back(idx_3); - this->wires[3].emplace_back(idx_4); - } - - auto& w_l() { return std::get<0>(this->wires); }; - auto& w_r() { return std::get<1>(this->wires); }; - auto& w_o() { return std::get<2>(this->wires); }; - auto& w_4() { return std::get<3>(this->wires); }; - - auto& q_m() { return this->selectors[0]; }; - auto& q_c() { return this->selectors[1]; }; - auto& q_1() { return this->selectors[2]; }; - auto& q_2() { return this->selectors[3]; }; - auto& q_3() { return this->selectors[4]; }; - auto& q_4() { return this->selectors[5]; }; - auto& q_arith() { return this->selectors[6]; }; - auto& q_delta_range() { return this->selectors[7]; }; - auto& q_elliptic() { return this->selectors[8]; }; - auto& q_aux() { return this->selectors[9]; }; - auto& q_lookup_type() { return this->selectors[10]; }; - auto& q_busread() { return this->selectors[11]; }; - auto& q_poseidon2_external() { return this->selectors[12]; }; - auto& q_poseidon2_internal() { return this->selectors[13]; }; - - /** - * @brief Add zeros to all selectors which are not part of the conventional Ultra arithmetization - * @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the - * conventional Ultra arithmetization - * - */ - void pad_additional() - { - q_busread().emplace_back(0); - q_poseidon2_external().emplace_back(0); - q_poseidon2_internal().emplace_back(0); - }; - - /** - * @brief Resizes all selectors which are not part of the conventional Ultra arithmetization - * @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the - * conventional Ultra arithmetization - * @param new_size - */ - void resize_additional(size_t new_size) - { - q_busread().resize(new_size); - q_poseidon2_external().resize(new_size); - q_poseidon2_internal().resize(new_size); - }; - }; - - struct TraceBlocks { - UltraHonkTraceBlock ecc_op; - UltraHonkTraceBlock pub_inputs; - UltraHonkTraceBlock arithmetic; - UltraHonkTraceBlock delta_range; - UltraHonkTraceBlock elliptic; - UltraHonkTraceBlock aux; - UltraHonkTraceBlock lookup; - UltraHonkTraceBlock busread; - UltraHonkTraceBlock poseidon_external; - UltraHonkTraceBlock poseidon_internal; - - // The set of fixed block sizes used when the structured trace is turned on. - // TODO(https://github.com/AztecProtocol/barretenberg/issues/1047): For development and practical purposes this - // needs to be more dynamic. Sizes currently set to accommodate the full e2e test. - std::array fixed_block_sizes{ - 1 << 10, // ecc_op; - 30000, // pub_inputs; - 600000, // arithmetic; - 140000, // delta_range; - 600000, // elliptic; - 1400000, // aux; - 460000, // lookup; - 1 << 7, // busread; - 15000, // poseidon_external; - 85000 // poseidon_internal; - }; - - TraceBlocks() - { - aux.has_ram_rom = true; - pub_inputs.is_pub_inputs = true; - // Set fixed block sizes for use in structured trace - for (auto [block, size] : zip_view(this->get(), fixed_block_sizes)) { - block.set_fixed_size(size); - } - } - - auto get() - { - return RefArray{ ecc_op, pub_inputs, arithmetic, delta_range, elliptic, - aux, lookup, busread, poseidon_external, poseidon_internal }; - } - - void summarize() const - { - info("Gate blocks summary: (actual gates / fixed capacity)"); - info("goblin ecc op :\t", ecc_op.size(), "/", ecc_op.get_fixed_size()); - info("pub inputs :\t", pub_inputs.size(), "/", pub_inputs.get_fixed_size()); - info("arithmetic :\t", arithmetic.size(), "/", arithmetic.get_fixed_size()); - info("delta range :\t", delta_range.size(), "/", delta_range.get_fixed_size()); - info("elliptic :\t", elliptic.size(), "/", elliptic.get_fixed_size()); - info("auxiliary :\t", aux.size(), "/", aux.get_fixed_size()); - info("lookups :\t", lookup.size(), "/", lookup.get_fixed_size()); - info("busread :\t", busread.size(), "/", busread.get_fixed_size()); - info("poseidon ext :\t", poseidon_external.size(), "/", poseidon_external.get_fixed_size()); - info("poseidon int :\t", poseidon_internal.size(), "/", poseidon_internal.get_fixed_size()); - info(""); - } - - size_t get_total_structured_size() - { - size_t total_size = 0; - for (auto block : this->get()) { - total_size += block.get_fixed_size(); - } - return total_size; - } - - void check_within_fixed_sizes() - { - int i = 0; - for (auto block : this->get()) { - if (block.size() > block.get_fixed_size()) { - info("WARNING: Num gates in circuit block exceeds the specified fixed size - execution trace will " - "not be constructed correctly!"); - info("Block index: ", i); - info("Actual size: ", block.size()); - info("Fixed size: ", block.get_fixed_size()); - ASSERT(false); - } - i++; - } - } - - bool operator==(const TraceBlocks& other) const = default; - }; - - // Note: Unused. Needed only for consistency with Ultra arith (which is used by Plonk) - inline static const std::vector selector_names = {}; -}; - class TranslatorArith { public: static constexpr size_t NUM_WIRES = 81; static constexpr size_t NUM_SELECTORS = 0; }; -template -concept HasAdditionalSelectors = IsAnyOf>; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp new file mode 100644 index 00000000000..6ee5f10f25c --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp @@ -0,0 +1,240 @@ +#pragma once + +#include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" + +namespace bb { + +/** + * @brief Mega arithmetization + * + * @tparam FF_ + */ +template class MegaArith { + + /** + * @brief Defines the circuit block types for the Mega arithmetization + * @note Its useful to define this as a template since it is used to actually store gate data (T = MegaTraceBlock) + * but also to store corresponding block sizes (T = uint32_t) for the structured trace or dynamic block size + * tracking in ClientIvc. + * + * @tparam T + */ + template struct MegaTraceBlocks { + T ecc_op; + T pub_inputs; + T arithmetic; + T delta_range; + T elliptic; + T aux; + T lookup; + T busread; + T poseidon_external; + T poseidon_internal; + + auto get() + { + return RefArray{ ecc_op, pub_inputs, arithmetic, delta_range, elliptic, + aux, lookup, busread, poseidon_external, poseidon_internal }; + } + + bool operator==(const MegaTraceBlocks& other) const = default; + }; + + // An arbitrary but small-ish structuring that can be used for generic unit testing with non-trivial circuits + struct SmallTestStructuredBlockSizes : public MegaTraceBlocks { + SmallTestStructuredBlockSizes() + { + const uint32_t FIXED_SIZE = 1 << 14; + this->ecc_op = FIXED_SIZE; + this->pub_inputs = FIXED_SIZE; + this->arithmetic = FIXED_SIZE; + this->delta_range = FIXED_SIZE; + this->elliptic = FIXED_SIZE; + this->aux = FIXED_SIZE; + this->lookup = FIXED_SIZE; + this->busread = FIXED_SIZE; + this->poseidon_external = FIXED_SIZE; + this->poseidon_internal = FIXED_SIZE; + } + }; + + // A minimal structuring specifically tailored to the medium complexity transaction for the ClientIvc benchmark + struct ClientIvcBenchStructuredBlockSizes : public MegaTraceBlocks { + ClientIvcBenchStructuredBlockSizes() + { + this->ecc_op = 1 << 10; + this->pub_inputs = 1 << 7; + this->arithmetic = 1 << 16; + this->delta_range = 1 << 15; + this->elliptic = 1 << 14; + this->aux = 1 << 16; + this->lookup = 1 << 15; + this->busread = 1 << 7; + this->poseidon_external = 1 << 11; + this->poseidon_internal = 1 << 14; + } + }; + + // Structuring tailored to the full e2e TS test (TO BE UPDATED ACCORDINGLY) + struct E2eStructuredBlockSizes : public MegaTraceBlocks { + E2eStructuredBlockSizes() + { + this->ecc_op = 1 << 10; + this->pub_inputs = 30000; + this->arithmetic = 600000; + this->delta_range = 140000; + this->elliptic = 600000; + this->aux = 1400000; + this->lookup = 460000; + this->busread = 1 << 7; + this->poseidon_external = 15000; + this->poseidon_internal = 85000; + } + }; + + public: + static constexpr size_t NUM_WIRES = 4; + static constexpr size_t NUM_SELECTORS = 14; + + using FF = FF_; + + class MegaTraceBlock : public ExecutionTraceBlock { + public: + void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4) + { +#ifdef CHECK_CIRCUIT_STACKTRACES + this->stack_traces.populate(); +#endif + this->wires[0].emplace_back(idx_1); + this->wires[1].emplace_back(idx_2); + this->wires[2].emplace_back(idx_3); + this->wires[3].emplace_back(idx_4); + } + + auto& w_l() { return std::get<0>(this->wires); }; + auto& w_r() { return std::get<1>(this->wires); }; + auto& w_o() { return std::get<2>(this->wires); }; + auto& w_4() { return std::get<3>(this->wires); }; + + auto& q_m() { return this->selectors[0]; }; + auto& q_c() { return this->selectors[1]; }; + auto& q_1() { return this->selectors[2]; }; + auto& q_2() { return this->selectors[3]; }; + auto& q_3() { return this->selectors[4]; }; + auto& q_4() { return this->selectors[5]; }; + auto& q_arith() { return this->selectors[6]; }; + auto& q_delta_range() { return this->selectors[7]; }; + auto& q_elliptic() { return this->selectors[8]; }; + auto& q_aux() { return this->selectors[9]; }; + auto& q_lookup_type() { return this->selectors[10]; }; + auto& q_busread() { return this->selectors[11]; }; + auto& q_poseidon2_external() { return this->selectors[12]; }; + auto& q_poseidon2_internal() { return this->selectors[13]; }; + + /** + * @brief Add zeros to all selectors which are not part of the conventional Ultra arithmetization + * @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the + * conventional Ultra arithmetization + * + */ + void pad_additional() + { + q_busread().emplace_back(0); + q_poseidon2_external().emplace_back(0); + q_poseidon2_internal().emplace_back(0); + }; + + /** + * @brief Resizes all selectors which are not part of the conventional Ultra arithmetization + * @details Facilitates reuse of Ultra gate construction functions in arithmetizations which extend the + * conventional Ultra arithmetization + * @param new_size + */ + void resize_additional(size_t new_size) + { + q_busread().resize(new_size); + q_poseidon2_external().resize(new_size); + q_poseidon2_internal().resize(new_size); + }; + }; + + struct TraceBlocks : public MegaTraceBlocks { + + E2eStructuredBlockSizes fixed_block_sizes; + + // Set fixed block sizes for use in structured trace + void set_fixed_block_sizes(TraceStructure setting) + { + MegaTraceBlocks fixed_block_sizes{}; // zero initialized + + switch (setting) { + case TraceStructure::NONE: + break; + case TraceStructure::SMALL_TEST: + fixed_block_sizes = SmallTestStructuredBlockSizes(); + break; + case TraceStructure::CLIENT_IVC_BENCH: + fixed_block_sizes = ClientIvcBenchStructuredBlockSizes(); + break; + case TraceStructure::E2E_FULL_TEST: + fixed_block_sizes = E2eStructuredBlockSizes(); + break; + } + for (auto [block, size] : zip_view(this->get(), fixed_block_sizes.get())) { + block.set_fixed_size(size); + } + } + + TraceBlocks() + { + this->aux.has_ram_rom = true; + this->pub_inputs.is_pub_inputs = true; + } + + void summarize() const + { + info("Gate blocks summary: (actual gates / fixed capacity)"); + info("goblin ecc op :\t", this->ecc_op.size(), "/", this->ecc_op.get_fixed_size()); + info("pub inputs :\t", this->pub_inputs.size(), "/", this->pub_inputs.get_fixed_size()); + info("arithmetic :\t", this->arithmetic.size(), "/", this->arithmetic.get_fixed_size()); + info("delta range :\t", this->delta_range.size(), "/", this->delta_range.get_fixed_size()); + info("elliptic :\t", this->elliptic.size(), "/", this->elliptic.get_fixed_size()); + info("auxiliary :\t", this->aux.size(), "/", this->aux.get_fixed_size()); + info("lookups :\t", this->lookup.size(), "/", this->lookup.get_fixed_size()); + info("busread :\t", this->busread.size(), "/", this->busread.get_fixed_size()); + info("poseidon ext :\t", this->poseidon_external.size(), "/", this->poseidon_external.get_fixed_size()); + info("poseidon int :\t", this->poseidon_internal.size(), "/", this->poseidon_internal.get_fixed_size()); + info(""); + } + + size_t get_total_structured_size() + { + size_t total_size = 0; + for (auto block : this->get()) { + total_size += block.get_fixed_size(); + } + return total_size; + } + + void check_within_fixed_sizes() + { + for (auto block : this->get()) { + if (block.size() > block.get_fixed_size()) { + info("WARNING: Num gates in circuit block exceeds the specified fixed size - execution trace will " + "not be constructed correctly!"); + summarize(); + ASSERT(false); + } + } + } + + bool operator==(const TraceBlocks& other) const = default; + }; + + // Note: Unused. Needed only for consistency with Ultra arith (which is used by Plonk) + inline static const std::vector selector_names = {}; +}; + +template +concept HasAdditionalSelectors = IsAnyOf>; +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/standard_arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/standard_arithmetization.hpp new file mode 100644 index 00000000000..e4cb58ea8a1 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/standard_arithmetization.hpp @@ -0,0 +1,57 @@ +#pragma once + +#include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" + +namespace bb { + +template class StandardArith { + public: + static constexpr size_t NUM_WIRES = 3; + static constexpr size_t NUM_SELECTORS = 5; + using FF = FF_; + + class StandardTraceBlock : public ExecutionTraceBlock { + public: + void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3) + { +#ifdef CHECK_CIRCUIT_STACKTRACES + this->stack_traces.populate(); +#endif + this->wires[0].emplace_back(idx_1); + this->wires[1].emplace_back(idx_2); + this->wires[2].emplace_back(idx_3); + } + + auto& w_l() { return std::get<0>(this->wires); }; + auto& w_r() { return std::get<1>(this->wires); }; + auto& w_o() { return std::get<2>(this->wires); }; + const auto& w_l() const { return std::get<0>(this->wires); }; + const auto& w_r() const { return std::get<1>(this->wires); }; + const auto& w_o() const { return std::get<2>(this->wires); }; + + auto& q_m() { return this->selectors[0]; }; + auto& q_1() { return this->selectors[1]; }; + auto& q_2() { return this->selectors[2]; }; + auto& q_3() { return this->selectors[3]; }; + auto& q_c() { return this->selectors[4]; }; + const auto& q_m() const { return this->selectors[0]; }; + const auto& q_1() const { return this->selectors[1]; }; + const auto& q_2() const { return this->selectors[2]; }; + const auto& q_3() const { return this->selectors[3]; }; + const auto& q_c() const { return this->selectors[4]; }; + }; + + struct TraceBlocks { + StandardTraceBlock pub_inputs; + StandardTraceBlock arithmetic; + + auto get() { return RefArray{ pub_inputs, arithmetic }; } + + bool operator==(const TraceBlocks& other) const = default; + }; + + // Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct. + inline static const std::vector selector_names = { "q_m", "q_1", "q_2", "q_3", "q_c" }; +}; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp new file mode 100644 index 00000000000..402ce07f9e0 --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp @@ -0,0 +1,159 @@ +#pragma once + +#include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" + +namespace bb { + +template class UltraArith { + + /** + * @brief Defines the circuit block types for the Ultra arithmetization + * @note Its useful to define this as a template since it is used to actually store gate data (T = UltraTraceBlock) + * but also to store corresponding block sizes (T = uint32_t) for the structured trace or dynamic block size + * tracking in ClientIvc. + * + * @tparam T + */ + template struct UltraTraceBlocks { + T pub_inputs; + T arithmetic; + T delta_range; + T elliptic; + T aux; + T lookup; + + auto get() { return RefArray{ pub_inputs, arithmetic, delta_range, elliptic, aux, lookup }; } + + bool operator==(const UltraTraceBlocks& other) const = default; + }; + + // An arbitrary but small-ish structuring that can be used for generic unit testing with non-trivial circuits + struct SmallTestStructuredBlockSizes : public UltraTraceBlocks { + SmallTestStructuredBlockSizes() + { + const uint32_t FIXED_SIZE = 1 << 10; + this->pub_inputs = FIXED_SIZE; + this->arithmetic = FIXED_SIZE; + this->delta_range = FIXED_SIZE; + this->elliptic = FIXED_SIZE; + this->aux = FIXED_SIZE; + this->lookup = FIXED_SIZE; + } + }; + + public: + static constexpr size_t NUM_WIRES = 4; + static constexpr size_t NUM_SELECTORS = 11; + using FF = FF_; + + class UltraTraceBlock : public ExecutionTraceBlock { + public: + void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3, const uint32_t& idx_4) + { +#ifdef CHECK_CIRCUIT_STACKTRACES + this->stack_traces.populate(); +#endif + this->wires[0].emplace_back(idx_1); + this->wires[1].emplace_back(idx_2); + this->wires[2].emplace_back(idx_3); + this->wires[3].emplace_back(idx_4); + } + + auto& w_l() { return std::get<0>(this->wires); }; + auto& w_r() { return std::get<1>(this->wires); }; + auto& w_o() { return std::get<2>(this->wires); }; + auto& w_4() { return std::get<3>(this->wires); }; + + auto& q_m() { return this->selectors[0]; }; + auto& q_c() { return this->selectors[1]; }; + auto& q_1() { return this->selectors[2]; }; + auto& q_2() { return this->selectors[3]; }; + auto& q_3() { return this->selectors[4]; }; + auto& q_4() { return this->selectors[5]; }; + auto& q_arith() { return this->selectors[6]; }; + auto& q_delta_range() { return this->selectors[7]; }; + auto& q_elliptic() { return this->selectors[8]; }; + auto& q_aux() { return this->selectors[9]; }; + auto& q_lookup_type() { return this->selectors[10]; }; + }; + + struct TraceBlocks : public UltraTraceBlocks { + + // Set fixed block sizes for use in structured trace + void set_fixed_block_sizes(TraceStructure setting) + { + UltraTraceBlocks fixed_block_sizes{}; // zero initialized + + switch (setting) { + case TraceStructure::NONE: + break; + // We don't use Ultra in ClientIvc so no need for anything other than sizing for simple unit tests + case TraceStructure::SMALL_TEST: + case TraceStructure::CLIENT_IVC_BENCH: + case TraceStructure::E2E_FULL_TEST: + fixed_block_sizes = SmallTestStructuredBlockSizes(); + break; + } + for (auto [block, size] : zip_view(this->get(), fixed_block_sizes.get())) { + block.set_fixed_size(size); + } + } + + TraceBlocks() + { + this->aux.has_ram_rom = true; + this->pub_inputs.is_pub_inputs = true; + } + + auto get() + { + return RefArray{ this->pub_inputs, this->arithmetic, this->delta_range, + this->elliptic, this->aux, this->lookup }; + } + + void summarize() const + { + info("Gate blocks summary:"); + info("pub inputs :\t", this->pub_inputs.size()); + info("arithmetic :\t", this->arithmetic.size()); + info("delta range:\t", this->delta_range.size()); + info("elliptic :\t", this->elliptic.size()); + info("auxiliary :\t", this->aux.size()); + info("lookups :\t", this->lookup.size()); + } + + size_t get_total_structured_size() + { + size_t total_size = 0; + for (auto block : this->get()) { + total_size += block.get_fixed_size(); + } + return total_size; + } + + /** + * @brief Check that the number of rows populated in each block does not exceed the specified fixed size + * @note This check is only applicable when utilizing a structured trace + * + */ + void check_within_fixed_sizes() + { + for (auto block : this->get()) { + if (block.size() > block.get_fixed_size()) { + info("WARNING: Num gates in circuit block exceeds the specified fixed size - execution trace will " + "not be constructed correctly!"); + ASSERT(false); + } + } + } + + bool operator==(const TraceBlocks& other) const = default; + }; + + // Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct. + inline static const std::vector selector_names = { "q_m", "q_c", "q_1", "q_2", + "q_3", "q_4", "q_arith", "q_sort", + "q_elliptic", "q_aux", "table_type" }; +}; + +} // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index da09210655f..474391a6f19 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -53,10 +53,10 @@ template class ProtoGalaxyTests : public testing::Test { // Construct prover and verifier instance for a provided circuit and add to tuple static void construct_prover_and_verifier_instance(TupleOfInstances& instances, Builder& builder, - bool structured = false) + TraceStructure structure = TraceStructure::NONE) { - auto prover_instance = std::make_shared(builder, structured); + auto prover_instance = std::make_shared(builder, structure); auto verification_key = std::make_shared(prover_instance->proving_key); auto verifier_instance = std::make_shared(verification_key); get<0>(instances).emplace_back(prover_instance); @@ -64,7 +64,7 @@ template class ProtoGalaxyTests : public testing::Test { } // constructs num_insts number of prover and verifier instances - static TupleOfInstances construct_instances(size_t num_insts, bool structured = false) + static TupleOfInstances construct_instances(size_t num_insts, TraceStructure structure = TraceStructure::NONE) { TupleOfInstances instances; // TODO(https://github.com/AztecProtocol/barretenberg/issues/938): Parallelize this loop @@ -72,7 +72,7 @@ template class ProtoGalaxyTests : public testing::Test { auto builder = typename Flavor::CircuitBuilder(); construct_circuit(builder); - construct_prover_and_verifier_instance(instances, builder, structured); + construct_prover_and_verifier_instance(instances, builder, structure); } return instances; } @@ -435,13 +435,14 @@ template class ProtoGalaxyTests : public testing::Test { */ static void test_full_protogalaxy_structured_trace() { - bool structured = true; - TupleOfInstances instances = construct_instances(2, structured); + TraceStructure trace_structure = TraceStructure::SMALL_TEST; + TupleOfInstances instances = construct_instances(2, trace_structure); auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(instances), get<1>(instances)); check_accumulator_target_sum_manual(prover_accumulator, true); - TupleOfInstances instances_2 = construct_instances(1, structured); // just one set of prover/verifier instances + TupleOfInstances instances_2 = + construct_instances(1, trace_structure); // just one set of prover/verifier instances auto [prover_accumulator_2, verifier_accumulator_2] = fold_and_verify( { prover_accumulator, get<0>(instances_2)[0] }, { verifier_accumulator, get<1>(instances_2)[0] }); @@ -458,7 +459,7 @@ template class ProtoGalaxyTests : public testing::Test { */ static void test_full_protogalaxy_structured_trace_inhomogeneous_circuits() { - bool structured = true; + TraceStructure trace_structure = TraceStructure::SMALL_TEST; // Construct three circuits to be folded, each with a different number of constraints Builder builder1; @@ -475,8 +476,8 @@ template class ProtoGalaxyTests : public testing::Test { // Construct the Prover/Verifier instances for the first two circuits TupleOfInstances instances; - construct_prover_and_verifier_instance(instances, builder1, structured); - construct_prover_and_verifier_instance(instances, builder2, structured); + construct_prover_and_verifier_instance(instances, builder1, trace_structure); + construct_prover_and_verifier_instance(instances, builder2, trace_structure); // Fold the first two instances auto [prover_accumulator, verifier_accumulator] = fold_and_verify(get<0>(instances), get<1>(instances)); @@ -484,7 +485,7 @@ template class ProtoGalaxyTests : public testing::Test { // Construct the Prover/Verifier instance for the third circuit TupleOfInstances instances_2; - construct_prover_and_verifier_instance(instances_2, builder3, structured); + construct_prover_and_verifier_instance(instances_2, builder3, trace_structure); // Fold 3rd instance into accumulator auto [prover_accumulator_2, verifier_accumulator_2] = fold_and_verify( diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/merge_recursive_verifier.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/merge_recursive_verifier.hpp index 17c3f0df6bb..2cd864ebe38 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/merge_recursive_verifier.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/merge_recursive_verifier.hpp @@ -19,7 +19,7 @@ template class MergeRecursiveVerifier_ { CircuitBuilder* builder; std::shared_ptr transcript; - static constexpr size_t NUM_WIRES = UltraHonkArith::NUM_WIRES; + static constexpr size_t NUM_WIRES = MegaArith::NUM_WIRES; explicit MergeRecursiveVerifier_(CircuitBuilder* builder); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_builder_base.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_builder_base.hpp index c99ebcc0f39..61677ff0501 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_builder_base.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/circuit_builder_base.hpp @@ -1,7 +1,7 @@ #pragma once +#include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" -#include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" #include "barretenberg/plonk_honk_shared/arithmetization/gate_data.hpp" #include #include diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp index 1c1397898c0..7d49629ebcb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/mega_circuit_builder.cpp @@ -13,7 +13,7 @@ namespace bb { template void MegaCircuitBuilder_::finalize_circuit() { // All of the gates involved in finalization are part of the Ultra arithmetization - UltraCircuitBuilder_>::finalize_circuit(); + UltraCircuitBuilder_>::finalize_circuit(); } /** @@ -29,7 +29,7 @@ template void MegaCircuitBuilder_::finalize_circuit() template void MegaCircuitBuilder_::add_gates_to_ensure_all_polys_are_non_zero() { // Most polynomials are handled via the conventional Ultra method - UltraCircuitBuilder_>::add_gates_to_ensure_all_polys_are_non_zero(); + UltraCircuitBuilder_>::add_gates_to_ensure_all_polys_are_non_zero(); // All that remains is to handle databus related and poseidon2 related polynomials. In what follows we populate the // calldata with some mock data then constuct a single calldata read gate 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 7cb00055547..1c4f87862f5 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 @@ -1,23 +1,23 @@ #pragma once #include "barretenberg/execution_trace/execution_trace.hpp" -#include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" +#include "barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp" #include "barretenberg/stdlib_circuit_builders/op_queue/ecc_op_queue.hpp" #include "databus.hpp" #include "ultra_circuit_builder.hpp" namespace bb { -template class MegaCircuitBuilder_ : public UltraCircuitBuilder_> { +template class MegaCircuitBuilder_ : public UltraCircuitBuilder_> { private: DataBus databus; // Container for public calldata/returndata public: - using Arithmetization = UltraHonkArith; + using Arithmetization = MegaArith; static constexpr std::string_view NAME_STRING = "MegaArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::ULTRA; static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = - UltraCircuitBuilder_>::DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; + UltraCircuitBuilder_>::DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; // Stores record of ecc operations and performs corresponding native operations internally std::shared_ptr op_queue; @@ -42,7 +42,7 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_ op_queue_in = std::make_shared()) - : UltraCircuitBuilder_>(size_hint) + : UltraCircuitBuilder_>(size_hint) , op_queue(op_queue_in) { // Set indices to constants corresponding to Goblin ECC op codes @@ -70,7 +70,7 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_& public_inputs, size_t varnum) - : UltraCircuitBuilder_>(/*size_hint=*/0, witness_values, public_inputs, varnum) + : UltraCircuitBuilder_>(/*size_hint=*/0, witness_values, public_inputs, varnum) , op_queue(op_queue_in) { // Set indices to constants corresponding to Goblin ECC op codes @@ -123,7 +123,7 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_>::get_num_gates(); + auto num_ultra_gates = UltraCircuitBuilder_>::get_num_gates(); auto num_goblin_ecc_op_gates = this->blocks.ecc_op.size(); return num_ultra_gates + num_goblin_ecc_op_gates; } @@ -155,7 +155,7 @@ template class MegaCircuitBuilder_ : public UltraCircuitBuilder_>::get_num_gates_split_into_components( + UltraCircuitBuilder_>::get_num_gates_split_into_components( count, rangecount, romcount, ramcount, nnfcount); auto num_goblin_ecc_op_gates = this->blocks.ecc_op.size(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp index d2ce11c094a..b25fc8d34ab 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/standard_circuit_builder.hpp @@ -2,6 +2,7 @@ #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/execution_trace/execution_trace.hpp" +#include "barretenberg/plonk_honk_shared/arithmetization/standard_arithmetization.hpp" #include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" #include "barretenberg/plonk_honk_shared/types/merkle_hash_type.hpp" #include "barretenberg/plonk_honk_shared/types/pedersen_commitment_type.hpp" diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp index 4325a52985f..2797c1b8fcf 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.cpp @@ -2827,7 +2827,7 @@ template msgpack::sbuffer UltraCircuitBuilder_>; -template class UltraCircuitBuilder_>; +template class UltraCircuitBuilder_>; // To enable this we need to template plookup // template class UltraCircuitBuilder_; diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp index ce1a8b8aebf..46657b10a09 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_circuit_builder.hpp @@ -1,5 +1,7 @@ #pragma once #include "barretenberg/execution_trace/execution_trace.hpp" +#include "barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp" +#include "barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp" #include "barretenberg/plonk_honk_shared/types/circuit_type.hpp" #include "barretenberg/plonk_honk_shared/types/merkle_hash_type.hpp" #include "barretenberg/plonk_honk_shared/types/pedersen_commitment_type.hpp" diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp index d3a9d0bf8ee..ca17fd3c610 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp @@ -1,6 +1,8 @@ #pragma once #include "barretenberg/execution_trace/execution_trace.hpp" #include "barretenberg/flavor/flavor.hpp" +#include "barretenberg/plonk_honk_shared/arithmetization/mega_arithmetization.hpp" +#include "barretenberg/plonk_honk_shared/arithmetization/ultra_arithmetization.hpp" #include "barretenberg/plonk_honk_shared/composer/composer_lib.hpp" #include "barretenberg/plonk_honk_shared/composer/permutation_lib.hpp" #include "barretenberg/relations/relation_parameters.hpp" @@ -41,15 +43,22 @@ template class ProverInstance_ { std::vector gate_challenges; FF target_sum; - ProverInstance_(Circuit& circuit, bool is_structured = false) + ProverInstance_(Circuit& circuit, TraceStructure trace_structure = TraceStructure::NONE) { BB_OP_COUNT_TIME_NAME("ProverInstance(Circuit&)"); circuit.add_gates_to_ensure_all_polys_are_non_zero(); circuit.finalize_circuit(); - // If using a structured trace, ensure that no block exceeds the fixed size + // Set flag indicating whether the polynomials will be constructed with fixed block sizes for each gate type + const bool is_structured = (trace_structure != TraceStructure::NONE); + + // If using a structured trace, set fixed block sizes, check their validity, and set the dyadic circuit size if (is_structured) { - circuit.blocks.check_within_fixed_sizes(); + circuit.blocks.set_fixed_block_sizes(trace_structure); // set the fixed sizes for each block + circuit.blocks.check_within_fixed_sizes(); // ensure that no block exceeds its fixed size + dyadic_circuit_size = compute_structured_dyadic_size(circuit); // set the dyadic size accordingly + } else { + dyadic_circuit_size = compute_dyadic_size(circuit); // set dyadic size directly from circuit block sizes } // TODO(https://github.com/AztecProtocol/barretenberg/issues/905): This is adding ops to the op queue but NOT to @@ -59,12 +68,6 @@ template class ProverInstance_ { circuit.op_queue->append_nonzero_ops(); } - if (is_structured) { // Compute dyadic size based on a structured trace with fixed block size - dyadic_circuit_size = compute_structured_dyadic_size(circuit); - } else { // Otherwise, compute conventional dyadic circuit size - dyadic_circuit_size = compute_dyadic_size(circuit); - } - proving_key = ProvingKey(dyadic_circuit_size, circuit.public_inputs.size()); // Construct and add to proving key the wire, selector and copy constraint polynomials diff --git a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp index fb3515ecd8e..a8d4d709100 100644 --- a/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/translator_vm/translator_flavor.hpp @@ -7,7 +7,6 @@ #include "barretenberg/flavor/flavor_macros.hpp" #include "barretenberg/flavor/relation_definitions.hpp" #include "barretenberg/honk/proof_system/permutation_library.hpp" -#include "barretenberg/plonk_honk_shared/arithmetization/arithmetization.hpp" #include "barretenberg/polynomials/univariate.hpp" #include "barretenberg/relations/relation_parameters.hpp" #include "barretenberg/relations/translator_vm/translator_decomposition_relation.hpp" diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_composer.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_composer.test.cpp index 9cff9113cde..dcc4caef74c 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/mega_composer.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/mega_composer.test.cpp @@ -86,8 +86,8 @@ TEST_F(MegaHonkComposerTests, BasicStructured) GoblinMockCircuits::construct_simple_circuit(builder); // Construct and verify Honk proof using a structured trace - bool structured = true; - auto instance = std::make_shared>(builder, structured); + TraceStructure trace_structure = TraceStructure::SMALL_TEST; + auto instance = std::make_shared>(builder, trace_structure); MegaProver prover(instance); auto verification_key = std::make_shared(instance->proving_key); MegaVerifier verifier(verification_key); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp index 31d0423fd99..68b3bb7c484 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_honk.test.cpp @@ -95,8 +95,8 @@ TEST_F(UltraHonkTests, StructuredTrace) MockCircuits::add_arithmetic_gates_with_public_inputs(builder, num_gates); // Construct an instance with a structured execution trace - bool structured = true; - auto instance = std::make_shared(builder, structured); + TraceStructure trace_structure = TraceStructure::SMALL_TEST; + auto instance = std::make_shared(builder, trace_structure); info(instance->proving_key.circuit_size); UltraProver prover(instance); auto verification_key = std::make_shared(instance->proving_key);