diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/standard_composer.cpp b/barretenberg/cpp/src/barretenberg/plonk/composer/standard_composer.cpp index 42c713ca291..3620fb540c3 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/standard_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/standard_composer.cpp @@ -25,7 +25,7 @@ namespace bb::plonk { * * @return Pointer to the initialized proving key updated with selector polynomials. * */ -std::shared_ptr StandardComposer::compute_proving_key(const CircuitBuilder& circuit_constructor) +std::shared_ptr StandardComposer::compute_proving_key(CircuitBuilder& circuit_constructor) { if (circuit_proving_key) { return circuit_proving_key; @@ -41,7 +41,7 @@ std::shared_ptr StandardComposer::compute_proving_key(const subgroup_size, circuit_constructor.public_inputs.size(), crs, CircuitType::STANDARD); // Construct and add to proving key the wire, selector and copy constraint polynomials - Trace::generate(circuit_constructor, circuit_proving_key); + Trace::populate(circuit_constructor, circuit_proving_key); // Make all selectors nonzero enforce_nonzero_selector_polynomials(circuit_constructor, circuit_proving_key.get()); @@ -62,8 +62,7 @@ std::shared_ptr StandardComposer::compute_proving_key(const * * @return Pointer to created circuit verification key. * */ -std::shared_ptr StandardComposer::compute_verification_key( - const CircuitBuilder& circuit_constructor) +std::shared_ptr StandardComposer::compute_verification_key(CircuitBuilder& circuit_constructor) { if (circuit_verification_key) { return circuit_verification_key; @@ -89,7 +88,7 @@ std::shared_ptr StandardComposer::compute_verification_ * * @return The verifier. * */ -plonk::Verifier StandardComposer::create_verifier(const CircuitBuilder& circuit_constructor) +plonk::Verifier StandardComposer::create_verifier(CircuitBuilder& circuit_constructor) { auto verification_key = compute_verification_key(circuit_constructor); @@ -112,7 +111,7 @@ plonk::Verifier StandardComposer::create_verifier(const CircuitBuilder& circuit_ * * @return Initialized prover. * */ -plonk::Prover StandardComposer::create_prover(const CircuitBuilder& circuit_constructor) +plonk::Prover StandardComposer::create_prover(CircuitBuilder& circuit_constructor) { compute_proving_key(circuit_constructor); diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/standard_composer.hpp b/barretenberg/cpp/src/barretenberg/plonk/composer/standard_composer.hpp index 84b6632fa77..63016750973 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/standard_composer.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/standard_composer.hpp @@ -56,11 +56,11 @@ class StandardComposer { }; return result; } - std::shared_ptr compute_proving_key(const CircuitBuilder& circuit_constructor); - std::shared_ptr compute_verification_key(const CircuitBuilder& circuit_constructor); + std::shared_ptr compute_proving_key(CircuitBuilder& circuit_constructor); + std::shared_ptr compute_verification_key(CircuitBuilder& circuit_constructor); - plonk::Verifier create_verifier(const CircuitBuilder& circuit_constructor); - plonk::Prover create_prover(const CircuitBuilder& circuit_constructor); + plonk::Verifier create_verifier(CircuitBuilder& circuit_constructor); + plonk::Prover create_prover(CircuitBuilder& circuit_constructor); /** * Create a manifest, which specifies proof rounds, elements and who supplies them. diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp b/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp index f42c1780807..80b0e886c5b 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/ultra_composer.cpp @@ -166,7 +166,7 @@ std::shared_ptr UltraComposer::compute_proving_key(CircuitBuilder& std::make_shared(subgroup_size, circuit.public_inputs.size(), crs, CircuitType::ULTRA); // Construct and add to proving key the wire, selector and copy constraint polynomials - Trace::generate(circuit, circuit_proving_key); + Trace::populate(circuit, circuit_proving_key); enforce_nonzero_selector_polynomials(circuit, circuit_proving_key.get()); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp index 9001beef281..47e6545b9c5 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp @@ -1,4 +1,5 @@ #pragma once +#include "barretenberg/common/ref_array.hpp" #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/proof_system/types/circuit_type.hpp" #include @@ -31,6 +32,36 @@ namespace bb { * We should only do this if it becomes necessary or convenient. */ +/** + * @brief Basic structure for storing gate data in a builder + * + * @tparam FF + * @tparam NUM_WIRES + * @tparam NUM_SELECTORS + */ +template class ExecutionTraceBlock { + public: + using SelectorType = std::vector>; + using WireType = std::vector>; + using Selectors = std::array; + using Wires = std::array; + + Wires wires; // vectors of indices into a witness variables array + Selectors selectors; + + bool operator==(const ExecutionTraceBlock& other) const = default; + + void reserve(size_t size_hint) + { + for (auto& w : wires) { + w.reserve(size_hint); + } + for (auto& p : selectors) { + p.reserve(size_hint); + } + } +}; + // 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 { @@ -38,30 +69,35 @@ template class StandardArith { static constexpr size_t NUM_WIRES = 3; static constexpr size_t NUM_SELECTORS = 5; using FF = FF_; - using SelectorType = std::vector>; - std::array selectors; + class StandardTraceBlock : public ExecutionTraceBlock { + public: + void populate_wires(const uint32_t& idx_1, const uint32_t& idx_2, const uint32_t& idx_3) + { + this->wires[0].emplace_back(idx_1); + this->wires[1].emplace_back(idx_2); + this->wires[2].emplace_back(idx_3); + } - SelectorType& q_m() { return selectors[0]; }; - SelectorType& q_1() { return selectors[1]; }; - SelectorType& q_2() { return selectors[2]; }; - SelectorType& q_3() { return selectors[3]; }; - SelectorType& q_c() { return selectors[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); }; - const SelectorType& q_m() const { return selectors[0]; }; - const SelectorType& q_1() const { return selectors[1]; }; - const SelectorType& q_2() const { return selectors[2]; }; - const SelectorType& q_3() const { return selectors[3]; }; - const SelectorType& q_c() const { return selectors[4]; }; + 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]; }; + }; - auto& get() { return selectors; }; + struct TraceBlocks { + StandardTraceBlock pub_inputs; + StandardTraceBlock arithmetic; - void reserve(size_t size_hint) - { - for (auto& p : selectors) { - p.reserve(size_hint); - } - } + 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" }; @@ -72,44 +108,43 @@ template class UltraArith { static constexpr size_t NUM_WIRES = 4; static constexpr size_t NUM_SELECTORS = 11; using FF = FF_; - using SelectorType = std::vector>; - private: - std::array selectors; + 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) + { + 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); + } - public: - SelectorType& q_m() { return selectors[0]; }; - SelectorType& q_c() { return selectors[1]; }; - SelectorType& q_1() { return selectors[2]; }; - SelectorType& q_2() { return selectors[3]; }; - SelectorType& q_3() { return selectors[4]; }; - SelectorType& q_4() { return selectors[5]; }; - SelectorType& q_arith() { return selectors[6]; }; - SelectorType& q_sort() { return selectors[7]; }; - SelectorType& q_elliptic() { return selectors[8]; }; - SelectorType& q_aux() { return selectors[9]; }; - SelectorType& q_lookup_type() { return selectors[10]; }; - - const SelectorType& q_m() const { return selectors[0]; }; - const SelectorType& q_c() const { return selectors[1]; }; - const SelectorType& q_1() const { return selectors[2]; }; - const SelectorType& q_2() const { return selectors[3]; }; - const SelectorType& q_3() const { return selectors[4]; }; - const SelectorType& q_4() const { return selectors[5]; }; - const SelectorType& q_arith() const { return selectors[6]; }; - const SelectorType& q_sort() const { return selectors[7]; }; - const SelectorType& q_elliptic() const { return selectors[8]; }; - const SelectorType& q_aux() const { return selectors[9]; }; - const SelectorType& q_lookup_type() const { return selectors[10]; }; - - auto& get() { return selectors; }; + 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_sort() { 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]; }; + }; - void reserve(size_t size_hint) - { - for (auto& vec : selectors) { - vec.reserve(size_hint); - } - } + struct TraceBlocks { + UltraTraceBlock pub_inputs; + UltraTraceBlock main; + + auto get() { return RefArray{ pub_inputs, main }; } + + 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", @@ -128,75 +163,72 @@ template class UltraHonkArith { static constexpr size_t NUM_WIRES = 4; static constexpr size_t NUM_SELECTORS = 14; using FF = FF_; - using SelectorType = std::vector>; - - private: - std::array selectors; - public: - SelectorType& q_m() { return selectors[0]; }; - SelectorType& q_c() { return selectors[1]; }; - SelectorType& q_1() { return selectors[2]; }; - SelectorType& q_2() { return selectors[3]; }; - SelectorType& q_3() { return selectors[4]; }; - SelectorType& q_4() { return selectors[5]; }; - SelectorType& q_arith() { return selectors[6]; }; - SelectorType& q_sort() { return selectors[7]; }; - SelectorType& q_elliptic() { return selectors[8]; }; - SelectorType& q_aux() { return selectors[9]; }; - SelectorType& q_lookup_type() { return selectors[10]; }; - SelectorType& q_busread() { return selectors[11]; }; - SelectorType& q_poseidon2_external() { return this->selectors[12]; }; - SelectorType& q_poseidon2_internal() { return this->selectors[13]; }; - - const SelectorType& q_m() const { return selectors[0]; }; - const SelectorType& q_c() const { return selectors[1]; }; - const SelectorType& q_1() const { return selectors[2]; }; - const SelectorType& q_2() const { return selectors[3]; }; - const SelectorType& q_3() const { return selectors[4]; }; - const SelectorType& q_4() const { return selectors[5]; }; - const SelectorType& q_arith() const { return selectors[6]; }; - const SelectorType& q_sort() const { return selectors[7]; }; - const SelectorType& q_elliptic() const { return selectors[8]; }; - const SelectorType& q_aux() const { return selectors[9]; }; - const SelectorType& q_lookup_type() const { return selectors[10]; }; - const SelectorType& q_busread() const { return selectors[11]; }; - const SelectorType& q_poseidon2_external() const { return this->selectors[12]; }; - const SelectorType& q_poseidon2_internal() const { return this->selectors[13]; }; - - auto& get() { return selectors; }; - - void reserve(size_t size_hint) - { - for (auto& vec : selectors) { - vec.reserve(size_hint); + 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) + { + 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); } - } - /** - * @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); + 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_sort() { 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); + }; }; - /** - * @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 main; + + auto get() { return RefArray{ ecc_op, pub_inputs, main }; } + + bool operator==(const TraceBlocks& other) const = default; }; // Note: Unused. Needed only for consistency with Ultra arith (which is used by Plonk) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp index 5231f1cad23..b4b188ee856 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp @@ -67,6 +67,8 @@ template class CircuitBuilderBase { CircuitBuilderBase& operator=(CircuitBuilderBase&& other) noexcept = default; virtual ~CircuitBuilderBase() = default; + bool operator==(const CircuitBuilderBase& other) const = default; + virtual size_t get_num_gates() const { return num_gates; } virtual void print_num_gates() const { std::cout << num_gates << std::endl; } virtual size_t get_num_variables() const { return variables.size(); } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp index be0aa89d1b1..8bb941d88ca 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.cpp @@ -42,47 +42,41 @@ template void GoblinUltraCircuitBuilder_::add_gates_to_ensure_ calldata_read_counts[raw_read_idx]++; // mock gates that use poseidon selectors, with all zeros as input - this->w_l().emplace_back(this->zero_idx); - this->w_r().emplace_back(this->zero_idx); - this->w_o().emplace_back(this->zero_idx); - this->w_4().emplace_back(this->zero_idx); - this->q_m().emplace_back(0); - this->q_1().emplace_back(0); - this->q_2().emplace_back(0); - this->q_3().emplace_back(0); - this->q_c().emplace_back(0); - this->q_arith().emplace_back(0); - this->q_4().emplace_back(0); - this->q_sort().emplace_back(0); - this->q_lookup_type().emplace_back(0); - this->q_elliptic().emplace_back(0); - this->q_aux().emplace_back(0); - this->q_busread().emplace_back(0); - this->q_poseidon2_external().emplace_back(1); - this->q_poseidon2_internal().emplace_back(1); + this->blocks.main.populate_wires(this->zero_idx, this->zero_idx, this->zero_idx, this->zero_idx); + this->blocks.main.q_m().emplace_back(0); + this->blocks.main.q_1().emplace_back(0); + this->blocks.main.q_2().emplace_back(0); + this->blocks.main.q_3().emplace_back(0); + this->blocks.main.q_c().emplace_back(0); + this->blocks.main.q_arith().emplace_back(0); + this->blocks.main.q_4().emplace_back(0); + this->blocks.main.q_sort().emplace_back(0); + this->blocks.main.q_lookup_type().emplace_back(0); + this->blocks.main.q_elliptic().emplace_back(0); + this->blocks.main.q_aux().emplace_back(0); + this->blocks.main.q_busread().emplace_back(0); + this->blocks.main.q_poseidon2_external().emplace_back(1); + this->blocks.main.q_poseidon2_internal().emplace_back(1); this->check_selector_length_consistency(); ++this->num_gates; // second gate that stores the output of all zeros of the poseidon gates - this->w_l().emplace_back(this->zero_idx); - this->w_r().emplace_back(this->zero_idx); - this->w_o().emplace_back(this->zero_idx); - this->w_4().emplace_back(this->zero_idx); - this->q_m().emplace_back(0); - this->q_1().emplace_back(0); - this->q_2().emplace_back(0); - this->q_3().emplace_back(0); - this->q_c().emplace_back(0); - this->q_arith().emplace_back(0); - this->q_4().emplace_back(0); - this->q_sort().emplace_back(0); - this->q_lookup_type().emplace_back(0); - this->q_elliptic().emplace_back(0); - this->q_aux().emplace_back(0); - this->q_busread().emplace_back(0); - this->q_poseidon2_external().emplace_back(0); - this->q_poseidon2_internal().emplace_back(0); + this->blocks.main.populate_wires(this->zero_idx, this->zero_idx, this->zero_idx, this->zero_idx); + this->blocks.main.q_m().emplace_back(0); + this->blocks.main.q_1().emplace_back(0); + this->blocks.main.q_2().emplace_back(0); + this->blocks.main.q_3().emplace_back(0); + this->blocks.main.q_c().emplace_back(0); + this->blocks.main.q_arith().emplace_back(0); + this->blocks.main.q_4().emplace_back(0); + this->blocks.main.q_sort().emplace_back(0); + this->blocks.main.q_lookup_type().emplace_back(0); + this->blocks.main.q_elliptic().emplace_back(0); + this->blocks.main.q_aux().emplace_back(0); + this->blocks.main.q_busread().emplace_back(0); + this->blocks.main.q_poseidon2_external().emplace_back(0); + this->blocks.main.q_poseidon2_internal().emplace_back(0); this->check_selector_length_consistency(); ++this->num_gates; @@ -207,19 +201,13 @@ ecc_op_tuple GoblinUltraCircuitBuilder_::decompose_ecc_operands(uint32_t op_ */ template void GoblinUltraCircuitBuilder_::populate_ecc_op_wires(const ecc_op_tuple& in) { - ecc_op_wire_1().emplace_back(in.op); - ecc_op_wire_2().emplace_back(in.x_lo); - ecc_op_wire_3().emplace_back(in.x_hi); - ecc_op_wire_4().emplace_back(in.y_lo); - for (auto& selector : ecc_op_block.selectors.get()) { + this->blocks.ecc_op.populate_wires(in.op, in.x_lo, in.x_hi, in.y_lo); + for (auto& selector : this->blocks.ecc_op.selectors) { selector.emplace_back(0); } - ecc_op_wire_1().emplace_back(this->zero_idx); - ecc_op_wire_2().emplace_back(in.y_hi); - ecc_op_wire_3().emplace_back(in.z_1); - ecc_op_wire_4().emplace_back(in.z_2); - for (auto& selector : ecc_op_block.selectors.get()) { + this->blocks.ecc_op.populate_wires(this->zero_idx, in.y_hi, in.z_1, in.z_2); + for (auto& selector : this->blocks.ecc_op.selectors) { selector.emplace_back(0); } @@ -243,26 +231,23 @@ template void GoblinUltraCircuitBuilder_::set_goblin_ecc_op_co template void GoblinUltraCircuitBuilder_::create_calldata_lookup_gate(const databus_lookup_gate_& in) { - this->w_l().emplace_back(in.value); - this->w_r().emplace_back(in.index); - q_busread().emplace_back(1); + this->blocks.main.populate_wires(in.value, in.index, this->zero_idx, this->zero_idx); + this->blocks.main.q_busread().emplace_back(1); // populate all other components with zero - this->w_o().emplace_back(this->zero_idx); - this->w_4().emplace_back(this->zero_idx); - this->q_m().emplace_back(0); - this->q_1().emplace_back(0); - this->q_2().emplace_back(0); - this->q_3().emplace_back(0); - this->q_c().emplace_back(0); - this->q_sort().emplace_back(0); - this->q_arith().emplace_back(0); - this->q_4().emplace_back(0); - this->q_lookup_type().emplace_back(0); - this->q_elliptic().emplace_back(0); - this->q_aux().emplace_back(0); - this->q_poseidon2_external().emplace_back(0); - this->q_poseidon2_internal().emplace_back(0); + this->blocks.main.q_m().emplace_back(0); + this->blocks.main.q_1().emplace_back(0); + this->blocks.main.q_2().emplace_back(0); + this->blocks.main.q_3().emplace_back(0); + this->blocks.main.q_c().emplace_back(0); + this->blocks.main.q_sort().emplace_back(0); + this->blocks.main.q_arith().emplace_back(0); + this->blocks.main.q_4().emplace_back(0); + this->blocks.main.q_lookup_type().emplace_back(0); + this->blocks.main.q_elliptic().emplace_back(0); + this->blocks.main.q_aux().emplace_back(0); + this->blocks.main.q_poseidon2_external().emplace_back(0); + this->blocks.main.q_poseidon2_internal().emplace_back(0); this->check_selector_length_consistency(); ++this->num_gates; @@ -274,24 +259,21 @@ void GoblinUltraCircuitBuilder_::create_calldata_lookup_gate(const databus_l template void GoblinUltraCircuitBuilder_::create_poseidon2_external_gate(const poseidon2_external_gate_& in) { - this->w_l().emplace_back(in.a); - this->w_r().emplace_back(in.b); - this->w_o().emplace_back(in.c); - this->w_4().emplace_back(in.d); - this->q_m().emplace_back(0); - this->q_1().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); - this->q_2().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][1]); - this->q_3().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][2]); - this->q_c().emplace_back(0); - this->q_arith().emplace_back(0); - this->q_4().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][3]); - this->q_sort().emplace_back(0); - this->q_lookup_type().emplace_back(0); - this->q_elliptic().emplace_back(0); - this->q_aux().emplace_back(0); - this->q_busread().emplace_back(0); - this->q_poseidon2_external().emplace_back(1); - this->q_poseidon2_internal().emplace_back(0); + this->blocks.main.populate_wires(in.a, in.b, in.c, in.d); + this->blocks.main.q_m().emplace_back(0); + this->blocks.main.q_1().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); + this->blocks.main.q_2().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][1]); + this->blocks.main.q_3().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][2]); + this->blocks.main.q_c().emplace_back(0); + this->blocks.main.q_arith().emplace_back(0); + this->blocks.main.q_4().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][3]); + this->blocks.main.q_sort().emplace_back(0); + this->blocks.main.q_lookup_type().emplace_back(0); + this->blocks.main.q_elliptic().emplace_back(0); + this->blocks.main.q_aux().emplace_back(0); + this->blocks.main.q_busread().emplace_back(0); + this->blocks.main.q_poseidon2_external().emplace_back(1); + this->blocks.main.q_poseidon2_internal().emplace_back(0); this->check_selector_length_consistency(); ++this->num_gates; } @@ -302,24 +284,21 @@ void GoblinUltraCircuitBuilder_::create_poseidon2_external_gate(const poseid template void GoblinUltraCircuitBuilder_::create_poseidon2_internal_gate(const poseidon2_internal_gate_& in) { - this->w_l().emplace_back(in.a); - this->w_r().emplace_back(in.b); - this->w_o().emplace_back(in.c); - this->w_4().emplace_back(in.d); - this->q_m().emplace_back(0); - this->q_1().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); - this->q_2().emplace_back(0); - this->q_3().emplace_back(0); - this->q_c().emplace_back(0); - this->q_arith().emplace_back(0); - this->q_4().emplace_back(0); - this->q_sort().emplace_back(0); - this->q_lookup_type().emplace_back(0); - this->q_elliptic().emplace_back(0); - this->q_aux().emplace_back(0); - this->q_busread().emplace_back(0); - this->q_poseidon2_external().emplace_back(0); - this->q_poseidon2_internal().emplace_back(1); + this->blocks.main.populate_wires(in.a, in.b, in.c, in.d); + this->blocks.main.q_m().emplace_back(0); + this->blocks.main.q_1().emplace_back(Poseidon2Bn254ScalarFieldParams::round_constants[in.round_idx][0]); + this->blocks.main.q_2().emplace_back(0); + this->blocks.main.q_3().emplace_back(0); + this->blocks.main.q_c().emplace_back(0); + this->blocks.main.q_arith().emplace_back(0); + this->blocks.main.q_4().emplace_back(0); + this->blocks.main.q_sort().emplace_back(0); + this->blocks.main.q_lookup_type().emplace_back(0); + this->blocks.main.q_elliptic().emplace_back(0); + this->blocks.main.q_aux().emplace_back(0); + this->blocks.main.q_busread().emplace_back(0); + this->blocks.main.q_poseidon2_external().emplace_back(0); + this->blocks.main.q_poseidon2_internal().emplace_back(1); this->check_selector_length_consistency(); ++this->num_gates; } @@ -333,24 +312,21 @@ void GoblinUltraCircuitBuilder_::create_poseidon2_internal_gate(const poseid */ template void GoblinUltraCircuitBuilder_::create_poseidon2_end_gate(const poseidon2_end_gate_& in) { - this->w_l().emplace_back(in.a); - this->w_r().emplace_back(in.b); - this->w_o().emplace_back(in.c); - this->w_4().emplace_back(in.d); - this->q_m().emplace_back(0); - this->q_1().emplace_back(0); - this->q_2().emplace_back(0); - this->q_3().emplace_back(0); - this->q_c().emplace_back(0); - this->q_arith().emplace_back(0); - this->q_4().emplace_back(0); - this->q_sort().emplace_back(0); - this->q_lookup_type().emplace_back(0); - this->q_elliptic().emplace_back(0); - this->q_aux().emplace_back(0); - this->q_busread().emplace_back(0); - this->q_poseidon2_external().emplace_back(0); - this->q_poseidon2_internal().emplace_back(0); + this->blocks.main.populate_wires(in.a, in.b, in.c, in.d); + this->blocks.main.q_m().emplace_back(0); + this->blocks.main.q_1().emplace_back(0); + this->blocks.main.q_2().emplace_back(0); + this->blocks.main.q_3().emplace_back(0); + this->blocks.main.q_c().emplace_back(0); + this->blocks.main.q_arith().emplace_back(0); + this->blocks.main.q_4().emplace_back(0); + this->blocks.main.q_sort().emplace_back(0); + this->blocks.main.q_lookup_type().emplace_back(0); + this->blocks.main.q_elliptic().emplace_back(0); + this->blocks.main.q_aux().emplace_back(0); + this->blocks.main.q_busread().emplace_back(0); + this->blocks.main.q_poseidon2_external().emplace_back(0); + this->blocks.main.q_poseidon2_internal().emplace_back(0); this->check_selector_length_consistency(); ++this->num_gates; } @@ -481,25 +457,25 @@ template bool GoblinUltraCircuitBuilder_::check_circuit() FF w_3_value; FF w_4_value; // Get the values of selectors and wires and update tag products along the way - q_poseidon2_external_value = this->q_poseidon2_external()[i]; - q_poseidon2_internal_value = this->q_poseidon2_internal()[i]; - q_1_value = this->q_1()[i]; - q_2_value = this->q_2()[i]; - q_3_value = this->q_3()[i]; - q_4_value = this->q_4()[i]; - w_1_value = this->get_variable(this->w_l()[i]); - w_2_value = this->get_variable(this->w_r()[i]); - w_3_value = this->get_variable(this->w_o()[i]); - w_4_value = this->get_variable(this->w_4()[i]); + q_poseidon2_external_value = this->blocks.main.q_poseidon2_external()[i]; + q_poseidon2_internal_value = this->blocks.main.q_poseidon2_internal()[i]; + q_1_value = this->blocks.main.q_1()[i]; + q_2_value = this->blocks.main.q_2()[i]; + q_3_value = this->blocks.main.q_3()[i]; + q_4_value = this->blocks.main.q_4()[i]; + w_1_value = this->get_variable(this->blocks.main.w_l()[i]); + w_2_value = this->get_variable(this->blocks.main.w_r()[i]); + w_3_value = this->get_variable(this->blocks.main.w_o()[i]); + w_4_value = this->get_variable(this->blocks.main.w_4()[i]); FF w_1_shifted_value; FF w_2_shifted_value; FF w_3_shifted_value; FF w_4_shifted_value; if (i < (this->num_gates - 1)) { - w_1_shifted_value = this->get_variable(this->w_l()[i + 1]); - w_2_shifted_value = this->get_variable(this->w_r()[i + 1]); - w_3_shifted_value = this->get_variable(this->w_o()[i + 1]); - w_4_shifted_value = this->get_variable(this->w_4()[i + 1]); + w_1_shifted_value = this->get_variable(this->blocks.main.w_l()[i + 1]); + w_2_shifted_value = this->get_variable(this->blocks.main.w_r()[i + 1]); + w_3_shifted_value = this->get_variable(this->blocks.main.w_o()[i + 1]); + w_4_shifted_value = this->get_variable(this->blocks.main.w_4()[i + 1]); } else { w_1_shifted_value = FF::zero(); w_2_shifted_value = FF::zero(); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp index 22e707f5b35..58f38dd6807 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.hpp @@ -11,7 +11,6 @@ using namespace bb; template class GoblinUltraCircuitBuilder_ : public UltraCircuitBuilder_> { public: using Arithmetization = UltraHonkArith; - using TraceBlock = ExecutionTraceBlock; static constexpr std::string_view NAME_STRING = "GoblinUltraArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::ULTRA; @@ -29,30 +28,6 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui uint32_t mul_accum_op_idx; uint32_t equality_op_idx; - using WireVector = std::vector>; - using SelectorVector = std::vector>; - - // Execution trace block for goblin ecc op gates - TraceBlock ecc_op_block; - - WireVector& ecc_op_wire_1() { return std::get<0>(ecc_op_block.wires); }; - WireVector& ecc_op_wire_2() { return std::get<1>(ecc_op_block.wires); }; - WireVector& ecc_op_wire_3() { return std::get<2>(ecc_op_block.wires); }; - WireVector& ecc_op_wire_4() { return std::get<3>(ecc_op_block.wires); }; - - const WireVector& ecc_op_wire_1() const { return std::get<0>(ecc_op_block.wires); }; - const WireVector& ecc_op_wire_2() const { return std::get<1>(ecc_op_block.wires); }; - const WireVector& ecc_op_wire_3() const { return std::get<2>(ecc_op_block.wires); }; - const WireVector& ecc_op_wire_4() const { return std::get<3>(ecc_op_block.wires); }; - - SelectorVector& q_busread() { return this->selectors.q_busread(); }; - SelectorVector& q_poseidon2_external() { return this->selectors.q_poseidon2_external(); }; - SelectorVector& q_poseidon2_internal() { return this->selectors.q_poseidon2_internal(); }; - - const SelectorVector& q_busread() const { return this->selectors.q_busread(); }; - const SelectorVector& q_poseidon2_external() const { return this->selectors.q_poseidon2_external(); }; - const SelectorVector& q_poseidon2_internal() const { return this->selectors.q_poseidon2_internal(); }; - // DataBus call/return data arrays std::vector public_calldata; std::vector calldata_read_counts; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp index 766686501ae..0c8db203f1d 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_ultra_circuit_builder.test.cpp @@ -44,8 +44,7 @@ TEST(GoblinUltraCircuitBuilder, CopyConstructor) GoblinUltraCircuitBuilder duplicate_circuit_constructor{ circuit_constructor }; - EXPECT_EQ(duplicate_circuit_constructor.get_num_gates(), circuit_constructor.get_num_gates()); - EXPECT_EQ(duplicate_circuit_constructor.selectors.get(), circuit_constructor.selectors.get()); + EXPECT_EQ(duplicate_circuit_constructor, circuit_constructor); EXPECT_TRUE(duplicate_circuit_constructor.check_circuit()); } @@ -102,27 +101,27 @@ TEST(GoblinUltraCircuitBuilder, GoblinSimple) EXPECT_EQ(builder.num_ecc_op_gates, 6); // Check that the expected op codes have been correctly recorded in the 1st op wire - EXPECT_EQ(builder.ecc_op_wire_1()[0], EccOpCode::ADD_ACCUM); - EXPECT_EQ(builder.ecc_op_wire_1()[2], EccOpCode::MUL_ACCUM); - EXPECT_EQ(builder.ecc_op_wire_1()[4], EccOpCode::EQUALITY); + EXPECT_EQ(builder.blocks.ecc_op.w_l()[0], EccOpCode::ADD_ACCUM); + EXPECT_EQ(builder.blocks.ecc_op.w_l()[2], EccOpCode::MUL_ACCUM); + EXPECT_EQ(builder.blocks.ecc_op.w_l()[4], EccOpCode::EQUALITY); // Check that we can reconstruct the coordinates of P1 from the op_wires - auto P1_x_lo = uint256_t(builder.variables[builder.ecc_op_wire_2()[0]]); - auto P1_x_hi = uint256_t(builder.variables[builder.ecc_op_wire_3()[0]]); + auto P1_x_lo = uint256_t(builder.variables[builder.blocks.ecc_op.w_r()[0]]); + auto P1_x_hi = uint256_t(builder.variables[builder.blocks.ecc_op.w_o()[0]]); auto P1_x = P1_x_lo + (P1_x_hi << CHUNK_SIZE); EXPECT_EQ(P1_x, uint256_t(P1.x)); - auto P1_y_lo = uint256_t(builder.variables[builder.ecc_op_wire_4()[0]]); - auto P1_y_hi = uint256_t(builder.variables[builder.ecc_op_wire_2()[1]]); + auto P1_y_lo = uint256_t(builder.variables[builder.blocks.ecc_op.w_4()[0]]); + auto P1_y_hi = uint256_t(builder.variables[builder.blocks.ecc_op.w_r()[1]]); auto P1_y = P1_y_lo + (P1_y_hi << CHUNK_SIZE); EXPECT_EQ(P1_y, uint256_t(P1.y)); // Check that we can reconstruct the coordinates of P2 from the op_wires - auto P2_x_lo = uint256_t(builder.variables[builder.ecc_op_wire_2()[2]]); - auto P2_x_hi = uint256_t(builder.variables[builder.ecc_op_wire_3()[2]]); + auto P2_x_lo = uint256_t(builder.variables[builder.blocks.ecc_op.w_r()[2]]); + auto P2_x_hi = uint256_t(builder.variables[builder.blocks.ecc_op.w_o()[2]]); auto P2_x = P2_x_lo + (P2_x_hi << CHUNK_SIZE); EXPECT_EQ(P2_x, uint256_t(P2.x)); - auto P2_y_lo = uint256_t(builder.variables[builder.ecc_op_wire_4()[2]]); - auto P2_y_hi = uint256_t(builder.variables[builder.ecc_op_wire_2()[3]]); + auto P2_y_lo = uint256_t(builder.variables[builder.blocks.ecc_op.w_4()[2]]); + auto P2_y_hi = uint256_t(builder.variables[builder.blocks.ecc_op.w_r()[3]]); auto P2_y = P2_y_lo + (P2_y_hi << CHUNK_SIZE); EXPECT_EQ(P2_y, uint256_t(P2.y)); } @@ -150,7 +149,7 @@ TEST(GoblinUltraCircuitBuilder, GoblinEccOpQueueUltraOps) auto ultra_ops = builder.op_queue->get_aggregate_transcript(); for (size_t i = 1; i < 4; ++i) { for (size_t j = 0; j < builder.num_ecc_op_gates; ++j) { - auto op_wire_val = builder.variables[builder.ecc_op_block.wires[i][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/proof_system/circuit_builder/standard_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp index e3a7478aa68..a3dcd7213bc 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp @@ -13,20 +13,18 @@ namespace bb { * Create an addition gate. * * @param in An add_triple containing the indexes of variables to be placed into the - * wires w_l, w_r, w_o and addition coefficients to be placed into q_1, q_2, q_3, q_c(). + * wires w_l, w_r, w_o and addition coefficients to be placed into q_1, q_2, q_3, q_c. */ template void StandardCircuitBuilder_::create_add_gate(const add_triple_& in) { this->assert_valid_variables({ in.a, in.b, in.c }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - q_m().emplace_back(FF::zero()); - q_1().emplace_back(in.a_scaling); - q_2().emplace_back(in.b_scaling); - q_3().emplace_back(in.c_scaling); - q_c().emplace_back(in.const_scaling); + blocks.arithmetic.populate_wires(in.a, in.b, in.c); + blocks.arithmetic.q_m().emplace_back(FF::zero()); + blocks.arithmetic.q_1().emplace_back(in.a_scaling); + blocks.arithmetic.q_2().emplace_back(in.b_scaling); + blocks.arithmetic.q_3().emplace_back(in.c_scaling); + blocks.arithmetic.q_c().emplace_back(in.const_scaling); ++this->num_gates; } @@ -70,25 +68,21 @@ template void StandardCircuitBuilder_::create_balanced_add_gat FF temp = t0 + t1; uint32_t temp_idx = this->add_variable(temp); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(temp_idx); - q_m().emplace_back(FF::zero()); - q_1().emplace_back(in.a_scaling); - q_2().emplace_back(in.b_scaling); - q_3().emplace_back(FF::neg_one()); - q_c().emplace_back(FF::zero()); + blocks.arithmetic.populate_wires(in.a, in.b, temp_idx); + blocks.arithmetic.q_m().emplace_back(FF::zero()); + blocks.arithmetic.q_1().emplace_back(in.a_scaling); + blocks.arithmetic.q_2().emplace_back(in.b_scaling); + blocks.arithmetic.q_3().emplace_back(FF::neg_one()); + blocks.arithmetic.q_c().emplace_back(FF::zero()); ++this->num_gates; - w_l().emplace_back(temp_idx); - w_r().emplace_back(in.c); - w_o().emplace_back(in.d); - q_m().emplace_back(FF::zero()); - q_1().emplace_back(FF::one()); - q_2().emplace_back(in.c_scaling); - q_3().emplace_back(in.d_scaling); - q_c().emplace_back(in.const_scaling); + blocks.arithmetic.populate_wires(temp_idx, in.c, in.d); + blocks.arithmetic.q_m().emplace_back(FF::zero()); + blocks.arithmetic.q_1().emplace_back(FF::one()); + blocks.arithmetic.q_2().emplace_back(in.c_scaling); + blocks.arithmetic.q_3().emplace_back(in.d_scaling); + blocks.arithmetic.q_c().emplace_back(in.const_scaling); ++this->num_gates; @@ -96,26 +90,22 @@ template void StandardCircuitBuilder_::create_balanced_add_gat // i.e. in.d * (in.d - 1) * (in.d - 2) = 0 FF temp_2 = this->get_variable(in.d).sqr() - this->get_variable(in.d); uint32_t temp_2_idx = this->add_variable(temp_2); - w_l().emplace_back(in.d); - w_r().emplace_back(in.d); - w_o().emplace_back(temp_2_idx); - q_m().emplace_back(FF::one()); - q_1().emplace_back(FF::neg_one()); - q_2().emplace_back(FF::zero()); - q_3().emplace_back(FF::neg_one()); - q_c().emplace_back(FF::zero()); + blocks.arithmetic.populate_wires(in.d, in.d, temp_2_idx); + blocks.arithmetic.q_m().emplace_back(FF::one()); + blocks.arithmetic.q_1().emplace_back(FF::neg_one()); + blocks.arithmetic.q_2().emplace_back(FF::zero()); + blocks.arithmetic.q_3().emplace_back(FF::neg_one()); + blocks.arithmetic.q_c().emplace_back(FF::zero()); ++this->num_gates; constexpr FF neg_two = -FF(2); - w_l().emplace_back(temp_2_idx); - w_r().emplace_back(in.d); - w_o().emplace_back(this->zero_idx); - q_m().emplace_back(FF::one()); - q_1().emplace_back(neg_two); - q_2().emplace_back(FF::zero()); - q_3().emplace_back(FF::zero()); - q_c().emplace_back(FF::zero()); + blocks.arithmetic.populate_wires(temp_2_idx, in.d, this->zero_idx); + blocks.arithmetic.q_m().emplace_back(FF::one()); + blocks.arithmetic.q_1().emplace_back(neg_two); + blocks.arithmetic.q_2().emplace_back(FF::zero()); + blocks.arithmetic.q_3().emplace_back(FF::zero()); + blocks.arithmetic.q_c().emplace_back(FF::zero()); ++this->num_gates; } @@ -179,20 +169,18 @@ template void StandardCircuitBuilder_::create_big_mul_gate(con * Create a multiplication gate. * * @param in A mul_tripple containing the indexes of variables to be placed into the - * wires w_l, w_r, w_o and scaling coefficients to be placed into q_m, q_3, q_c(). + * wires w_l, w_r, w_o and scaling coefficients to be placed into q_m, q_3, blocks.arithmetic.q_c(). */ template void StandardCircuitBuilder_::create_mul_gate(const mul_triple_& in) { this->assert_valid_variables({ in.a, in.b, in.c }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - q_m().emplace_back(in.mul_scaling); - q_1().emplace_back(FF::zero()); - q_2().emplace_back(FF::zero()); - q_3().emplace_back(in.c_scaling); - q_c().emplace_back(in.const_scaling); + blocks.arithmetic.populate_wires(in.a, in.b, in.c); + blocks.arithmetic.q_m().emplace_back(in.mul_scaling); + blocks.arithmetic.q_1().emplace_back(FF::zero()); + blocks.arithmetic.q_2().emplace_back(FF::zero()); + blocks.arithmetic.q_3().emplace_back(in.c_scaling); + blocks.arithmetic.q_c().emplace_back(in.const_scaling); ++this->num_gates; } @@ -207,15 +195,12 @@ template void StandardCircuitBuilder_::create_bool_gate(const { this->assert_valid_variables({ variable_index }); - w_l().emplace_back(variable_index); - w_r().emplace_back(variable_index); - w_o().emplace_back(variable_index); - - q_m().emplace_back(FF::one()); - q_1().emplace_back(FF::zero()); - q_2().emplace_back(FF::zero()); - q_3().emplace_back(FF::neg_one()); - q_c().emplace_back(FF::zero()); + blocks.arithmetic.populate_wires(variable_index, variable_index, variable_index); + blocks.arithmetic.q_m().emplace_back(FF::one()); + blocks.arithmetic.q_1().emplace_back(FF::zero()); + blocks.arithmetic.q_2().emplace_back(FF::zero()); + blocks.arithmetic.q_3().emplace_back(FF::neg_one()); + blocks.arithmetic.q_c().emplace_back(FF::zero()); ++this->num_gates; } @@ -229,14 +214,12 @@ template void StandardCircuitBuilder_::create_poly_gate(const { this->assert_valid_variables({ in.a, in.b, in.c }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - q_m().emplace_back(in.q_m); - q_1().emplace_back(in.q_l); - q_2().emplace_back(in.q_r); - q_3().emplace_back(in.q_o); - q_c().emplace_back(in.q_c); + blocks.arithmetic.populate_wires(in.a, in.b, in.c); + blocks.arithmetic.q_m().emplace_back(in.q_m); + blocks.arithmetic.q_1().emplace_back(in.q_l); + blocks.arithmetic.q_2().emplace_back(in.q_r); + blocks.arithmetic.q_3().emplace_back(in.q_o); + blocks.arithmetic.q_c().emplace_back(in.q_c); ++this->num_gates; } @@ -482,14 +465,12 @@ void StandardCircuitBuilder_::fix_witness(const uint32_t witness_index, cons { this->assert_valid_variables({ witness_index }); - w_l().emplace_back(witness_index); - w_r().emplace_back(this->zero_idx); - w_o().emplace_back(this->zero_idx); - q_m().emplace_back(FF::zero()); - q_1().emplace_back(FF::one()); - q_2().emplace_back(FF::zero()); - q_3().emplace_back(FF::zero()); - q_c().emplace_back(-witness_value); + blocks.arithmetic.populate_wires(witness_index, this->zero_idx, this->zero_idx); + blocks.arithmetic.q_m().emplace_back(FF::zero()); + blocks.arithmetic.q_1().emplace_back(FF::one()); + blocks.arithmetic.q_2().emplace_back(FF::zero()); + blocks.arithmetic.q_3().emplace_back(FF::zero()); + blocks.arithmetic.q_c().emplace_back(-witness_value); ++this->num_gates; } @@ -546,10 +527,12 @@ template bool StandardCircuitBuilder_::check_circuit() for (size_t i = 0; i < this->num_gates; i++) { gate_sum = FF::zero(); - left = this->get_variable(w_l()[i]); - right = this->get_variable(w_r()[i]); - output = this->get_variable(w_o()[i]); - gate_sum = q_m()[i] * left * right + q_1()[i] * left + q_2()[i] * right + q_3()[i] * output + q_c()[i]; + left = this->get_variable(blocks.arithmetic.w_l()[i]); + right = this->get_variable(blocks.arithmetic.w_r()[i]); + output = this->get_variable(blocks.arithmetic.w_o()[i]); + gate_sum = blocks.arithmetic.q_m()[i] * left * right + blocks.arithmetic.q_1()[i] * left + + blocks.arithmetic.q_2()[i] * right + blocks.arithmetic.q_3()[i] * output + + blocks.arithmetic.q_c()[i]; if (!gate_sum.is_zero()) { info("gate number", i); return false; @@ -590,11 +573,15 @@ template msgpack::sbuffer StandardCircuitBuilder_::export_circ } for (size_t i = 0; i < this->num_gates; i++) { - std::vector tmp_sel = { q_m()[i], q_1()[i], q_2()[i], q_3()[i], q_c()[i] }; + std::vector tmp_sel = { blocks.arithmetic.q_m()[i], + blocks.arithmetic.q_1()[i], + blocks.arithmetic.q_2()[i], + blocks.arithmetic.q_3()[i], + blocks.arithmetic.q_c()[i] }; std::vector tmp_w = { - this->real_variable_index[w_l()[i]], - this->real_variable_index[w_r()[i]], - this->real_variable_index[w_o()[i]], + this->real_variable_index[blocks.arithmetic.w_l()[i]], + this->real_variable_index[blocks.arithmetic.w_r()[i]], + this->real_variable_index[blocks.arithmetic.w_o()[i]], }; cir.selectors.push_back(tmp_sel); cir.wires.push_back(tmp_w); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp index 77c3e87e94a..32386b388a7 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp @@ -1,6 +1,7 @@ #pragma once #include "barretenberg/ecc/curves/bn254/bn254.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" +#include "barretenberg/proof_system/execution_trace/execution_trace.hpp" #include "barretenberg/proof_system/types/circuit_type.hpp" #include "barretenberg/proof_system/types/merkle_hash_type.hpp" #include "barretenberg/proof_system/types/pedersen_commitment_type.hpp" @@ -12,7 +13,7 @@ namespace bb { template class StandardCircuitBuilder_ : public CircuitBuilderBase { public: using Arithmetization = StandardArith; - using Selectors = Arithmetization; + using GateBlocks = typename Arithmetization::TraceBlocks; static constexpr size_t NUM_WIRES = Arithmetization::NUM_WIRES; // Keeping NUM_WIRES, at least temporarily, for backward compatibility static constexpr size_t program_width = Arithmetization::NUM_WIRES; @@ -24,31 +25,8 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase static constexpr merkle::HashType merkle_hash_type = merkle::HashType::FIXED_BASE_PEDERSEN; static constexpr pedersen::CommitmentType commitment_type = pedersen::CommitmentType::FIXED_BASE_PEDERSEN; - std::array>, NUM_WIRES> wires; - Arithmetization selectors; - - using WireVector = std::vector>; - using SelectorVector = std::vector>; - - WireVector& w_l() { return std::get<0>(wires); }; - WireVector& w_r() { return std::get<1>(wires); }; - WireVector& w_o() { return std::get<2>(wires); }; - - const WireVector& w_l() const { return std::get<0>(wires); }; - const WireVector& w_r() const { return std::get<1>(wires); }; - const WireVector& w_o() const { return std::get<2>(wires); }; - - SelectorVector& q_m() { return this->selectors.q_m(); }; - SelectorVector& q_1() { return this->selectors.q_1(); }; - SelectorVector& q_2() { return this->selectors.q_2(); }; - SelectorVector& q_3() { return this->selectors.q_3(); }; - SelectorVector& q_c() { return this->selectors.q_c(); }; - - const SelectorVector& q_m() const { return this->selectors.q_m(); }; - const SelectorVector& q_1() const { return this->selectors.q_1(); }; - const SelectorVector& q_2() const { return this->selectors.q_2(); }; - const SelectorVector& q_3() const { return this->selectors.q_3(); }; - const SelectorVector& q_c() const { return this->selectors.q_c(); }; + // Storage for wires and selectors for all gate types + GateBlocks blocks; static constexpr size_t UINT_LOG2_BASE = 2; @@ -60,10 +38,7 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase StandardCircuitBuilder_(const size_t size_hint = 0) : CircuitBuilderBase(size_hint) { - selectors.reserve(size_hint); - w_l().reserve(size_hint); - w_r().reserve(size_hint); - w_o().reserve(size_hint); + blocks.arithmetic.reserve(size_hint); // To effieciently constrain wires to zero, we set the first value of w_1 to be 0, and use copy constraints for // all future zero values. // (#216)(Adrian): This should be done in a constant way, maybe by initializing the constant_variable_indices @@ -82,8 +57,7 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase { CircuitBuilderBase::operator=(std::move(other)); constant_variable_indices = other.constant_variable_indices; - wires = other.wires; - selectors = other.selectors; + blocks = other.blocks; return *this; }; ~StandardCircuitBuilder_() override = default; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp index 21aa754edfe..c7c70b7adf0 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp @@ -61,24 +61,21 @@ void UltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_no { // First add a gate to simultaneously ensure first entries of all wires is zero and to add a non // zero value to all selectors aside from q_c and q_lookup - w_l().emplace_back(this->zero_idx); - w_r().emplace_back(this->zero_idx); - w_o().emplace_back(this->zero_idx); - w_4().emplace_back(this->zero_idx); - q_m().emplace_back(1); - q_1().emplace_back(1); - q_2().emplace_back(1); - q_3().emplace_back(1); - q_c().emplace_back(0); - q_sort().emplace_back(1); - - q_arith().emplace_back(1); - q_4().emplace_back(1); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(1); - q_aux().emplace_back(1); + blocks.main.populate_wires(this->zero_idx, this->zero_idx, this->zero_idx, this->zero_idx); + blocks.main.q_m().emplace_back(1); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(1); + blocks.main.q_3().emplace_back(1); + blocks.main.q_c().emplace_back(0); + blocks.main.q_sort().emplace_back(1); + + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(1); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(1); + blocks.main.q_aux().emplace_back(1); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -125,23 +122,20 @@ void UltraCircuitBuilder_::create_add_gate(const add_triple_assert_valid_variables({ in.a, in.b, in.c }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - w_4().emplace_back(this->zero_idx); - q_m().emplace_back(0); - q_1().emplace_back(in.a_scaling); - q_2().emplace_back(in.b_scaling); - q_3().emplace_back(in.c_scaling); - q_c().emplace_back(in.const_scaling); - q_arith().emplace_back(1); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(in.a, in.b, in.c, this->zero_idx); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(in.a_scaling); + blocks.main.q_2().emplace_back(in.b_scaling); + blocks.main.q_3().emplace_back(in.c_scaling); + blocks.main.q_c().emplace_back(in.const_scaling); + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -160,23 +154,20 @@ void UltraCircuitBuilder_::create_big_add_gate(const add_quad_< const bool include_next_gate_w_4) { this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - w_4().emplace_back(in.d); - q_m().emplace_back(0); - q_1().emplace_back(in.a_scaling); - q_2().emplace_back(in.b_scaling); - q_3().emplace_back(in.c_scaling); - q_c().emplace_back(in.const_scaling); - q_arith().emplace_back(include_next_gate_w_4 ? 2 : 1); - q_4().emplace_back(in.d_scaling); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(in.a, in.b, in.c, in.d); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(in.a_scaling); + blocks.main.q_2().emplace_back(in.b_scaling); + blocks.main.q_3().emplace_back(in.c_scaling); + blocks.main.q_c().emplace_back(in.const_scaling); + blocks.main.q_arith().emplace_back(include_next_gate_w_4 ? 2 : 1); + blocks.main.q_4().emplace_back(in.d_scaling); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -257,23 +248,20 @@ void UltraCircuitBuilder_::create_big_mul_gate(const mul_quad_< { this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - w_4().emplace_back(in.d); - q_m().emplace_back(in.mul_scaling); - q_1().emplace_back(in.a_scaling); - q_2().emplace_back(in.b_scaling); - q_3().emplace_back(in.c_scaling); - q_c().emplace_back(in.const_scaling); - q_arith().emplace_back(1); - q_4().emplace_back(in.d_scaling); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(in.a, in.b, in.c, in.d); + blocks.main.q_m().emplace_back(in.mul_scaling); + blocks.main.q_1().emplace_back(in.a_scaling); + blocks.main.q_2().emplace_back(in.b_scaling); + blocks.main.q_3().emplace_back(in.c_scaling); + blocks.main.q_c().emplace_back(in.const_scaling); + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(in.d_scaling); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -286,23 +274,20 @@ void UltraCircuitBuilder_::create_balanced_add_gate(const add_q { this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - w_4().emplace_back(in.d); - q_m().emplace_back(0); - q_1().emplace_back(in.a_scaling); - q_2().emplace_back(in.b_scaling); - q_3().emplace_back(in.c_scaling); - q_c().emplace_back(in.const_scaling); - q_arith().emplace_back(1); - q_4().emplace_back(in.d_scaling); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(in.a, in.b, in.c, in.d); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(in.a_scaling); + blocks.main.q_2().emplace_back(in.b_scaling); + blocks.main.q_3().emplace_back(in.c_scaling); + blocks.main.q_c().emplace_back(in.const_scaling); + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(in.d_scaling); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -331,23 +316,20 @@ void UltraCircuitBuilder_::create_mul_gate(const mul_triple_assert_valid_variables({ in.a, in.b, in.c }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - w_4().emplace_back(this->zero_idx); - q_m().emplace_back(in.mul_scaling); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(in.c_scaling); - q_c().emplace_back(in.const_scaling); - q_arith().emplace_back(1); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(in.a, in.b, in.c, this->zero_idx); + blocks.main.q_m().emplace_back(in.mul_scaling); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(in.c_scaling); + blocks.main.q_c().emplace_back(in.const_scaling); + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -362,24 +344,21 @@ void UltraCircuitBuilder_::create_bool_gate(const uint32_t vari { this->assert_valid_variables({ variable_index }); - w_l().emplace_back(variable_index); - w_r().emplace_back(variable_index); - w_o().emplace_back(this->zero_idx); - w_4().emplace_back(this->zero_idx); - q_m().emplace_back(1); - q_1().emplace_back(-1); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_sort().emplace_back(0); - - q_arith().emplace_back(1); - q_4().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(variable_index, variable_index, this->zero_idx, this->zero_idx); + blocks.main.q_m().emplace_back(1); + blocks.main.q_1().emplace_back(-1); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -396,24 +375,21 @@ void UltraCircuitBuilder_::create_poly_gate(const poly_triple_< { this->assert_valid_variables({ in.a, in.b, in.c }); - w_l().emplace_back(in.a); - w_r().emplace_back(in.b); - w_o().emplace_back(in.c); - w_4().emplace_back(this->zero_idx); - q_m().emplace_back(in.q_m); - q_1().emplace_back(in.q_l); - q_2().emplace_back(in.q_r); - q_3().emplace_back(in.q_o); - q_c().emplace_back(in.q_c); - q_sort().emplace_back(0); - - q_arith().emplace_back(1); - q_4().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(in.a, in.b, in.c, this->zero_idx); + blocks.main.q_m().emplace_back(in.q_m); + blocks.main.q_1().emplace_back(in.q_l); + blocks.main.q_2().emplace_back(in.q_r); + blocks.main.q_3().emplace_back(in.q_o); + blocks.main.q_c().emplace_back(in.q_c); + blocks.main.q_sort().emplace_back(0); + + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -441,57 +417,51 @@ void UltraCircuitBuilder_::create_ecc_add_gate(const ecc_add_ga this->assert_valid_variables({ in.x1, in.x2, in.x3, in.y1, in.y2, in.y3 }); bool can_fuse_into_previous_gate = true; - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_r()[this->num_gates - 1] == in.x1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_o()[this->num_gates - 1] == in.y1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_3()[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_4()[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_1()[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_arith()[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_m()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.w_r()[this->num_gates - 1] == in.x1); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.w_o()[this->num_gates - 1] == in.y1); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.q_3()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.q_4()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.q_1()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.q_arith()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.q_m()[this->num_gates - 1] == 0); if (can_fuse_into_previous_gate) { - q_1()[this->num_gates - 1] = in.sign_coefficient; - q_elliptic()[this->num_gates - 1] = 1; + blocks.main.q_1()[this->num_gates - 1] = in.sign_coefficient; + blocks.main.q_elliptic()[this->num_gates - 1] = 1; } else { - w_l().emplace_back(this->zero_idx); - w_r().emplace_back(in.x1); - w_o().emplace_back(in.y1); - w_4().emplace_back(this->zero_idx); - q_3().emplace_back(0); - q_4().emplace_back(0); - q_1().emplace_back(in.sign_coefficient); - - q_arith().emplace_back(0); - q_2().emplace_back(0); - q_m().emplace_back(0); - q_c().emplace_back(0); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(1); - q_aux().emplace_back(0); + blocks.main.populate_wires(this->zero_idx, in.x1, in.y1, this->zero_idx); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_1().emplace_back(in.sign_coefficient); + + blocks.main.q_arith().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(1); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; } - w_l().emplace_back(in.x2); - w_4().emplace_back(in.y2); - w_r().emplace_back(in.x3); - w_o().emplace_back(in.y3); - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(in.x2, in.x3, in.y3, in.y2); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -514,55 +484,50 @@ void UltraCircuitBuilder_::create_ecc_dbl_gate(const ecc_dbl_ga * can also chain double gates together **/ bool can_fuse_into_previous_gate = true; - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_r()[this->num_gates - 1] == in.x1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_o()[this->num_gates - 1] == in.y1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_arith()[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_lookup_type()[this->num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_aux()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.w_r()[this->num_gates - 1] == in.x1); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.w_o()[this->num_gates - 1] == in.y1); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.q_arith()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = + can_fuse_into_previous_gate && (blocks.main.q_lookup_type()[this->num_gates - 1] == 0); + can_fuse_into_previous_gate = can_fuse_into_previous_gate && (blocks.main.q_aux()[this->num_gates - 1] == 0); if (can_fuse_into_previous_gate) { - q_elliptic()[this->num_gates - 1] = 1; - q_m()[this->num_gates - 1] = 1; + blocks.main.q_elliptic()[this->num_gates - 1] = 1; + blocks.main.q_m()[this->num_gates - 1] = 1; } else { - w_r().emplace_back(in.x1); - w_o().emplace_back(in.y1); - w_l().emplace_back(this->zero_idx); - w_4().emplace_back(this->zero_idx); - q_elliptic().emplace_back(1); - q_m().emplace_back(1); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(this->zero_idx, in.x1, in.y1, this->zero_idx); + blocks.main.q_elliptic().emplace_back(1); + blocks.main.q_m().emplace_back(1); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; } - w_r().emplace_back(in.x3); - w_o().emplace_back(in.y3); - w_l().emplace_back(this->zero_idx); - w_4().emplace_back(this->zero_idx); - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(this->zero_idx, in.x3, in.y3, this->zero_idx); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -579,23 +544,20 @@ void UltraCircuitBuilder_::fix_witness(const uint32_t witness_i { this->assert_valid_variables({ witness_index }); - w_l().emplace_back(witness_index); - w_r().emplace_back(this->zero_idx); - w_o().emplace_back(this->zero_idx); - w_4().emplace_back(this->zero_idx); - q_m().emplace_back(0); - q_1().emplace_back(1); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(-witness_value); - q_arith().emplace_back(1); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.populate_wires(witness_index, this->zero_idx, this->zero_idx, this->zero_idx); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(-witness_value); + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -657,23 +619,20 @@ plookup::ReadData UltraCircuitBuilder_::create_gates_ read_data[plookup::ColumnIdx::C3].push_back(third_idx); this->assert_valid_variables({ first_idx, second_idx, third_idx }); - q_lookup_type().emplace_back(FF(1)); - q_3().emplace_back(FF(table.table_index)); - w_l().emplace_back(first_idx); - w_r().emplace_back(second_idx); - w_o().emplace_back(third_idx); - w_4().emplace_back(this->zero_idx); - q_1().emplace_back(0); - q_2().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_1_step_sizes[i + 1])); - q_m().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_2_step_sizes[i + 1])); - q_c().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_3_step_sizes[i + 1])); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(FF(1)); + blocks.main.q_3().emplace_back(FF(table.table_index)); + blocks.main.populate_wires(first_idx, second_idx, third_idx, this->zero_idx); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_1_step_sizes[i + 1])); + blocks.main.q_m().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_2_step_sizes[i + 1])); + blocks.main.q_c().emplace_back((i == (num_lookups - 1) ? 0 : -multi_table.column_3_step_sizes[i + 1])); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); ++this->num_gates; @@ -967,47 +926,43 @@ void UltraCircuitBuilder_::create_sort_constraint(const std::ve this->assert_valid_variables(variable_index); for (size_t i = 0; i < variable_index.size(); i += gate_width) { + blocks.main.populate_wires( + variable_index[i], variable_index[i + 1], variable_index[i + 2], variable_index[i + 3]); - w_l().emplace_back(variable_index[i]); - w_r().emplace_back(variable_index[i + 1]); - w_o().emplace_back(variable_index[i + 2]); - w_4().emplace_back(variable_index[i + 3]); ++this->num_gates; - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(1); - q_elliptic().emplace_back(0); - q_lookup_type().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(1); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); } // dummy gate needed because of sort widget's check of next row - w_l().emplace_back(variable_index[variable_index.size() - 1]); - w_r().emplace_back(this->zero_idx); - w_o().emplace_back(this->zero_idx); - w_4().emplace_back(this->zero_idx); + blocks.main.populate_wires( + variable_index[variable_index.size() - 1], this->zero_idx, this->zero_idx, this->zero_idx); ++this->num_gates; - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_elliptic().emplace_back(0); - q_lookup_type().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); } @@ -1027,24 +982,21 @@ void UltraCircuitBuilder_::create_dummy_constraints(const std:: this->assert_valid_variables(padded_list); for (size_t i = 0; i < padded_list.size(); i += gate_width) { - w_l().emplace_back(padded_list[i]); - w_r().emplace_back(padded_list[i + 1]); - w_o().emplace_back(padded_list[i + 2]); - w_4().emplace_back(padded_list[i + 3]); + blocks.main.populate_wires(padded_list[i], padded_list[i + 1], padded_list[i + 2], padded_list[i + 3]); ++this->num_gates; - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_elliptic().emplace_back(0); - q_lookup_type().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); } @@ -1061,94 +1013,87 @@ void UltraCircuitBuilder_::create_sort_constraint_with_edges( this->assert_valid_variables(variable_index); // enforce range checks of first row and starting at start - w_l().emplace_back(variable_index[0]); - w_r().emplace_back(variable_index[1]); - w_o().emplace_back(variable_index[2]); - w_4().emplace_back(variable_index[3]); + blocks.main.populate_wires(variable_index[0], variable_index[1], variable_index[2], variable_index[3]); ++this->num_gates; - q_m().emplace_back(0); - q_1().emplace_back(1); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(-start); - q_arith().emplace_back(1); - q_4().emplace_back(0); - q_sort().emplace_back(1); - q_elliptic().emplace_back(0); - q_lookup_type().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(-start); + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(1); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); // enforce range check for middle rows for (size_t i = gate_width; i < variable_index.size() - gate_width; i += gate_width) { - w_l().emplace_back(variable_index[i]); - w_r().emplace_back(variable_index[i + 1]); - w_o().emplace_back(variable_index[i + 2]); - w_4().emplace_back(variable_index[i + 3]); + blocks.main.populate_wires( + variable_index[i], variable_index[i + 1], variable_index[i + 2], variable_index[i + 3]); ++this->num_gates; - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(1); - q_elliptic().emplace_back(0); - q_lookup_type().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(1); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); } // enforce range checks of last row and ending at end if (variable_index.size() > gate_width) { - w_l().emplace_back(variable_index[variable_index.size() - 4]); - w_r().emplace_back(variable_index[variable_index.size() - 3]); - w_o().emplace_back(variable_index[variable_index.size() - 2]); - w_4().emplace_back(variable_index[variable_index.size() - 1]); + blocks.main.populate_wires(variable_index[variable_index.size() - 4], + variable_index[variable_index.size() - 3], + variable_index[variable_index.size() - 2], + variable_index[variable_index.size() - 1]); ++this->num_gates; - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); - q_4().emplace_back(0); - q_sort().emplace_back(1); - q_elliptic().emplace_back(0); - q_lookup_type().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(1); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); } // dummy gate needed because of sort widget's check of next row // use this gate to check end condition - w_l().emplace_back(variable_index[variable_index.size() - 1]); - w_r().emplace_back(this->zero_idx); - w_o().emplace_back(this->zero_idx); - w_4().emplace_back(this->zero_idx); + blocks.main.populate_wires( + variable_index[variable_index.size() - 1], this->zero_idx, this->zero_idx, this->zero_idx); ++this->num_gates; - q_m().emplace_back(0); - q_1().emplace_back(1); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_c().emplace_back(-end); - q_arith().emplace_back(1); - q_4().emplace_back(0); - q_sort().emplace_back(0); - q_elliptic().emplace_back(0); - q_lookup_type().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_c().emplace_back(-end); + blocks.main.q_arith().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); } @@ -1253,77 +1198,77 @@ std::vector UltraCircuitBuilder_::decompose_into_defa template void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECTORS type) { - q_aux().emplace_back(type == AUX_SELECTORS::NONE ? 0 : 1); - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(type == AUX_SELECTORS::NONE ? 0 : 1); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); switch (type) { case AUX_SELECTORS::LIMB_ACCUMULATE_1: { - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(1); - q_4().emplace_back(1); - q_m().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(1); + blocks.main.q_4().emplace_back(1); + blocks.main.q_m().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; } case AUX_SELECTORS::LIMB_ACCUMULATE_2: { - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(1); - q_4().emplace_back(0); - q_m().emplace_back(1); - q_c().emplace_back(0); - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(1); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_1: { - q_1().emplace_back(0); - q_2().emplace_back(1); - q_3().emplace_back(1); - q_4().emplace_back(0); - q_m().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(1); + blocks.main.q_3().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_2: { - q_1().emplace_back(0); - q_2().emplace_back(1); - q_3().emplace_back(0); - q_4().emplace_back(1); - q_m().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(1); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(1); + blocks.main.q_m().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; } case AUX_SELECTORS::NON_NATIVE_FIELD_3: { - q_1().emplace_back(0); - q_2().emplace_back(1); - q_3().emplace_back(0); - q_4().emplace_back(0); - q_m().emplace_back(1); - q_c().emplace_back(0); - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(1); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(1); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; @@ -1333,15 +1278,15 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // Apply sorted memory read checks with the following additional check: // 1. Assert that if index field across two gates does not change, the value field does not change. // Used for ROM reads and RAM reads across write/read boundaries - q_1().emplace_back(1); - q_2().emplace_back(1); - q_3().emplace_back(0); - q_4().emplace_back(0); - q_m().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(1); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; @@ -1352,15 +1297,15 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // 2. Validate record computation (r = read_write_flag + index * \eta + \timestamp * \eta^2 + value * \eta^3) // 3. If adjacent index values across 2 gates does not change, and the next gate's read_write_flag is set to // 'read', validate adjacent values do not change Used for ROM reads and RAM reads across read/write boundaries - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_4().emplace_back(0); - q_m().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(1); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(1); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; @@ -1368,15 +1313,15 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT case AUX_SELECTORS::RAM_TIMESTAMP_CHECK: { // For two adjacent RAM entries that share the same index, validate the timestamp value is monotonically // increasing - q_1().emplace_back(1); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_4().emplace_back(1); - q_m().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(1); + blocks.main.q_m().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; @@ -1385,15 +1330,15 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // Memory read gate for reading memory cells. // Validates record witness computation (r = read_write_flag + index * \eta + timestamp * \eta^2 + value * // \eta^3) - q_1().emplace_back(1); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_4().emplace_back(0); - q_m().emplace_back(1); // validate record witness is correctly computed - q_c().emplace_back(0); // read/write flag stored in q_c - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(1); // validate record witness is correctly computed + blocks.main.q_c().emplace_back(0); // read/write flag stored in q_c + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; @@ -1402,15 +1347,15 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // Memory read gate for reading memory cells. // Validates record witness computation (r = read_write_flag + index * \eta + timestamp * \eta^2 + value * // \eta^3) - q_1().emplace_back(1); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_4().emplace_back(0); - q_m().emplace_back(1); // validate record witness is correctly computed - q_c().emplace_back(0); // read/write flag stored in q_c - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(1); // validate record witness is correctly computed + blocks.main.q_c().emplace_back(0); // read/write flag stored in q_c + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; @@ -1419,29 +1364,29 @@ void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECT // Memory read gate for writing memory cells. // Validates record witness computation (r = read_write_flag + index * \eta + timestamp * \eta^2 + value * // \eta^3) - q_1().emplace_back(1); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_4().emplace_back(0); - q_m().emplace_back(1); // validate record witness is correctly computed - q_c().emplace_back(1); // read/write flag stored in q_c - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(1); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(1); // validate record witness is correctly computed + blocks.main.q_c().emplace_back(1); // read/write flag stored in q_c + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; } default: { - q_1().emplace_back(0); - q_2().emplace_back(0); - q_3().emplace_back(0); - q_4().emplace_back(0); - q_m().emplace_back(0); - q_c().emplace_back(0); - q_arith().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(0); + blocks.main.q_3().emplace_back(0); + blocks.main.q_4().emplace_back(0); + blocks.main.q_m().emplace_back(0); + blocks.main.q_c().emplace_back(0); + blocks.main.q_arith().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } check_selector_length_consistency(); break; @@ -1509,20 +1454,9 @@ void UltraCircuitBuilder_::range_constrain_two_limbs(const uint const std::array lo_sublimbs = get_sublimbs(lo_idx, lo_masks); const std::array hi_sublimbs = get_sublimbs(hi_idx, hi_masks); - w_l().emplace_back(lo_sublimbs[0]); - w_r().emplace_back(lo_sublimbs[1]); - w_o().emplace_back(lo_sublimbs[2]); - w_4().emplace_back(lo_idx); - - w_l().emplace_back(lo_sublimbs[3]); - w_r().emplace_back(lo_sublimbs[4]); - w_o().emplace_back(hi_sublimbs[0]); - w_4().emplace_back(hi_sublimbs[1]); - - w_l().emplace_back(hi_sublimbs[2]); - w_r().emplace_back(hi_sublimbs[3]); - w_o().emplace_back(hi_sublimbs[4]); - w_4().emplace_back(hi_idx); + blocks.main.populate_wires(lo_sublimbs[0], lo_sublimbs[1], lo_sublimbs[2], lo_idx); + blocks.main.populate_wires(lo_sublimbs[3], lo_sublimbs[4], hi_sublimbs[0], hi_sublimbs[1]); + blocks.main.populate_wires(hi_sublimbs[2], hi_sublimbs[3], hi_sublimbs[4], hi_idx); apply_aux_selectors(AUX_SELECTORS::LIMB_ACCUMULATE_1); apply_aux_selectors(AUX_SELECTORS::LIMB_ACCUMULATE_2); @@ -1682,28 +1616,19 @@ std::array UltraCircuitBuilder_::evaluate_non_nati 0 }, true); - w_l().emplace_back(input.a[1]); - w_r().emplace_back(input.b[1]); - w_o().emplace_back(input.r[0]); - w_4().emplace_back(lo_0_idx); + blocks.main.populate_wires(input.a[1], input.b[1], input.r[0], lo_0_idx); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_1); ++this->num_gates; - w_l().emplace_back(input.a[0]); - w_r().emplace_back(input.b[0]); - w_o().emplace_back(input.a[3]); - w_4().emplace_back(input.b[3]); + + blocks.main.populate_wires(input.a[0], input.b[0], input.a[3], input.b[3]); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_2); ++this->num_gates; - w_l().emplace_back(input.a[2]); - w_r().emplace_back(input.b[2]); - w_o().emplace_back(input.r[3]); - w_4().emplace_back(hi_0_idx); + + blocks.main.populate_wires(input.a[2], input.b[2], input.r[3], hi_0_idx); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_3); ++this->num_gates; - w_l().emplace_back(input.a[1]); - w_r().emplace_back(input.b[1]); - w_o().emplace_back(input.r[2]); - w_4().emplace_back(hi_1_idx); + + blocks.main.populate_wires(input.a[1], input.b[1], input.r[2], hi_1_idx); apply_aux_selectors(AUX_SELECTORS::NONE); ++this->num_gates; @@ -1767,28 +1692,30 @@ void UltraCircuitBuilder_::process_non_native_field_multiplicat // iterate over the cached items and create constraints for (const auto& input : cached_partial_non_native_field_multiplications) { - w_l().emplace_back(input.a[1]); - w_r().emplace_back(input.b[1]); - w_o().emplace_back(this->zero_idx); - w_4().emplace_back(input.lo_0); + blocks.main.w_l().emplace_back(input.a[1]); + blocks.main.w_r().emplace_back(input.b[1]); + blocks.main.w_o().emplace_back(this->zero_idx); + blocks.main.w_4().emplace_back(input.lo_0); + apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_1); ++this->num_gates; - w_l().emplace_back(input.a[0]); - w_r().emplace_back(input.b[0]); - w_o().emplace_back(input.a[3]); - w_4().emplace_back(input.b[3]); + + blocks.main.populate_wires(input.a[0], input.b[0], input.a[3], input.b[3]); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_2); ++this->num_gates; - w_l().emplace_back(input.a[2]); - w_r().emplace_back(input.b[2]); - w_o().emplace_back(this->zero_idx); - w_4().emplace_back(input.hi_0); + + blocks.main.w_l().emplace_back(input.a[2]); + blocks.main.w_r().emplace_back(input.b[2]); + blocks.main.w_o().emplace_back(this->zero_idx); + blocks.main.w_4().emplace_back(input.hi_0); + apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_3); ++this->num_gates; - w_l().emplace_back(input.a[1]); - w_r().emplace_back(input.b[1]); - w_o().emplace_back(this->zero_idx); - w_4().emplace_back(input.hi_1); + blocks.main.w_l().emplace_back(input.a[1]); + blocks.main.w_r().emplace_back(input.b[1]); + blocks.main.w_o().emplace_back(this->zero_idx); + blocks.main.w_4().emplace_back(input.hi_1); + apply_aux_selectors(AUX_SELECTORS::NONE); ++this->num_gates; } @@ -1909,63 +1836,58 @@ std::array UltraCircuitBuilder_::evaluate_non_nati * By setting `q_arith` to `3`, we can validate `x_p + y_p + q_m = z_p` **/ // GATE 1 - w_l().emplace_back(y_p); - w_r().emplace_back(x_0); - w_o().emplace_back(y_0); - w_4().emplace_back(x_p); - w_l().emplace_back(z_p); - w_r().emplace_back(x_1); - w_o().emplace_back(y_1); // | 1 | 2 | 3 | 4 | - w_4().emplace_back(z_0); // |-----|-----|-----|-----| - w_l().emplace_back(x_2); // | y.p | x.0 | y.0 | z.p | (b.p + b.p - c.p = 0) AND (a.0 + b.0 - c.0 = 0) - w_r().emplace_back(y_2); // | x.p | x.1 | y.1 | z.0 | (a.1 + b.1 - c.1 = 0) - w_o().emplace_back(z_2); // | x.2 | y.2 | z.2 | z.1 | (a.2 + b.2 - c.2 = 0) - w_4().emplace_back(z_1); // | x.3 | y.3 | z.3 | --- | (a.3 + b.3 - c.3 = 0) - w_l().emplace_back(x_3); - w_r().emplace_back(y_3); - w_o().emplace_back(z_3); - w_4().emplace_back(this->zero_idx); - - q_m().emplace_back(addconstp); - q_1().emplace_back(0); - q_2().emplace_back(-x_mulconst0 * - 2); // scale constants by 2. If q_arith = 3 then w_4_omega value (z0) gets scaled by 2x - q_3().emplace_back(-y_mulconst0 * 2); // z_0 - (x_0 * -xmulconst0) - (y_0 * ymulconst0) = 0 => z_0 = x_0 + y_0 - q_4().emplace_back(0); - q_c().emplace_back(-addconst0 * 2); - q_arith().emplace_back(3); - - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(-x_mulconst1); - q_3().emplace_back(-y_mulconst1); - q_4().emplace_back(0); - q_c().emplace_back(-addconst1); - q_arith().emplace_back(2); - - q_m().emplace_back(0); - q_1().emplace_back(-x_mulconst2); - q_2().emplace_back(-y_mulconst2); - q_3().emplace_back(1); - q_4().emplace_back(0); - q_c().emplace_back(-addconst2); - q_arith().emplace_back(1); - - q_m().emplace_back(0); - q_1().emplace_back(-x_mulconst3); - q_2().emplace_back(-y_mulconst3); - q_3().emplace_back(1); - q_4().emplace_back(0); - q_c().emplace_back(-addconst3); - q_arith().emplace_back(1); + // | 1 | 2 | 3 | 4 | + // |-----|-----|-----|-----| + // | y.p | x.0 | y.0 | z.p | (b.p + b.p - c.p = 0) AND (a.0 + b.0 - c.0 = 0) + // | x.p | x.1 | y.1 | z.0 | (a.1 + b.1 - c.1 = 0) + // | x.2 | y.2 | z.2 | z.1 | (a.2 + b.2 - c.2 = 0) + // | x.3 | y.3 | z.3 | --- | (a.3 + b.3 - c.3 = 0) + blocks.main.populate_wires(y_p, x_0, y_0, x_p); + blocks.main.populate_wires(z_p, x_1, y_1, z_0); + blocks.main.populate_wires(x_2, y_2, z_2, z_1); + blocks.main.populate_wires(x_3, y_3, z_3, this->zero_idx); + + blocks.main.q_m().emplace_back(addconstp); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back( + -x_mulconst0 * 2); // scale constants by 2. If q_arith = 3 then w_4_omega value (z0) gets scaled by 2x + blocks.main.q_3().emplace_back(-y_mulconst0 * + 2); // z_0 - (x_0 * -xmulconst0) - (y_0 * ymulconst0) = 0 => z_0 = x_0 + y_0 + blocks.main.q_4().emplace_back(0); + blocks.main.q_c().emplace_back(-addconst0 * 2); + blocks.main.q_arith().emplace_back(3); + + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(-x_mulconst1); + blocks.main.q_3().emplace_back(-y_mulconst1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_c().emplace_back(-addconst1); + blocks.main.q_arith().emplace_back(2); + + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(-x_mulconst2); + blocks.main.q_2().emplace_back(-y_mulconst2); + blocks.main.q_3().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_c().emplace_back(-addconst2); + blocks.main.q_arith().emplace_back(1); + + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(-x_mulconst3); + blocks.main.q_2().emplace_back(-y_mulconst3); + blocks.main.q_3().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_c().emplace_back(-addconst3); + blocks.main.q_arith().emplace_back(1); for (size_t i = 0; i < 4; ++i) { - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } } check_selector_length_consistency(); @@ -2035,62 +1957,57 @@ std::array UltraCircuitBuilder_::evaluate_non_nati * **/ // GATE 1 - w_l().emplace_back(y_p); - w_r().emplace_back(x_0); - w_o().emplace_back(y_0); - w_4().emplace_back(z_p); - w_l().emplace_back(x_p); - w_r().emplace_back(x_1); - w_o().emplace_back(y_1); // | 1 | 2 | 3 | 4 | - w_4().emplace_back(z_0); // |-----|-----|-----|-----| - w_l().emplace_back(x_2); // | y.p | x.0 | y.0 | z.p | (b.p + c.p - a.p = 0) AND (a.0 - b.0 - c.0 = 0) - w_r().emplace_back(y_2); // | x.p | x.1 | y.1 | z.0 | (a.1 - b.1 - c.1 = 0) - w_o().emplace_back(z_2); // | x.2 | y.2 | z.2 | z.1 | (a.2 - b.2 - c.2 = 0) - w_4().emplace_back(z_1); // | x.3 | y.3 | z.3 | --- | (a.3 - b.3 - c.3 = 0) - w_l().emplace_back(x_3); - w_r().emplace_back(y_3); - w_o().emplace_back(z_3); - w_4().emplace_back(this->zero_idx); - - q_m().emplace_back(-addconstp); - q_1().emplace_back(0); - q_2().emplace_back(-x_mulconst0 * 2); - q_3().emplace_back(y_mulconst0 * 2); // z_0 + (x_0 * -xmulconst0) + (y_0 * ymulconst0) = 0 => z_0 = x_0 - y_0 - q_4().emplace_back(0); - q_c().emplace_back(-addconst0 * 2); - q_arith().emplace_back(3); - - q_m().emplace_back(0); - q_1().emplace_back(0); - q_2().emplace_back(-x_mulconst1); - q_3().emplace_back(y_mulconst1); - q_4().emplace_back(0); - q_c().emplace_back(-addconst1); - q_arith().emplace_back(2); - - q_m().emplace_back(0); - q_1().emplace_back(-x_mulconst2); - q_2().emplace_back(y_mulconst2); - q_3().emplace_back(1); - q_4().emplace_back(0); - q_c().emplace_back(-addconst2); - q_arith().emplace_back(1); - - q_m().emplace_back(0); - q_1().emplace_back(-x_mulconst3); - q_2().emplace_back(y_mulconst3); - q_3().emplace_back(1); - q_4().emplace_back(0); - q_c().emplace_back(-addconst3); - q_arith().emplace_back(1); + // | 1 | 2 | 3 | 4 | + // |-----|-----|-----|-----| + // | y.p | x.0 | y.0 | z.p | (b.p + c.p - a.p = 0) AND (a.0 - b.0 - c.0 = 0) + // | x.p | x.1 | y.1 | z.0 | (a.1 - b.1 - c.1 = 0) + // | x.2 | y.2 | z.2 | z.1 | (a.2 - b.2 - c.2 = 0) + // | x.3 | y.3 | z.3 | --- | (a.3 - b.3 - c.3 = 0) + blocks.main.populate_wires(y_p, x_0, y_0, z_p); + blocks.main.populate_wires(x_p, x_1, y_1, z_0); + blocks.main.populate_wires(x_2, y_2, z_2, z_1); + blocks.main.populate_wires(x_3, y_3, z_3, this->zero_idx); + + blocks.main.q_m().emplace_back(-addconstp); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(-x_mulconst0 * 2); + blocks.main.q_3().emplace_back(y_mulconst0 * + 2); // z_0 + (x_0 * -xmulconst0) + (y_0 * ymulconst0) = 0 => z_0 = x_0 - y_0 + blocks.main.q_4().emplace_back(0); + blocks.main.q_c().emplace_back(-addconst0 * 2); + blocks.main.q_arith().emplace_back(3); + + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(0); + blocks.main.q_2().emplace_back(-x_mulconst1); + blocks.main.q_3().emplace_back(y_mulconst1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_c().emplace_back(-addconst1); + blocks.main.q_arith().emplace_back(2); + + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(-x_mulconst2); + blocks.main.q_2().emplace_back(y_mulconst2); + blocks.main.q_3().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_c().emplace_back(-addconst2); + blocks.main.q_arith().emplace_back(1); + + blocks.main.q_m().emplace_back(0); + blocks.main.q_1().emplace_back(-x_mulconst3); + blocks.main.q_2().emplace_back(y_mulconst3); + blocks.main.q_3().emplace_back(1); + blocks.main.q_4().emplace_back(0); + blocks.main.q_c().emplace_back(-addconst3); + blocks.main.q_arith().emplace_back(1); for (size_t i = 0; i < 4; ++i) { - q_sort().emplace_back(0); - q_lookup_type().emplace_back(0); - q_elliptic().emplace_back(0); - q_aux().emplace_back(0); + blocks.main.q_sort().emplace_back(0); + blocks.main.q_lookup_type().emplace_back(0); + blocks.main.q_elliptic().emplace_back(0); + blocks.main.q_aux().emplace_back(0); if constexpr (HasAdditionalSelectors) { - selectors.pad_additional(); + blocks.main.pad_additional(); } } check_selector_length_consistency(); @@ -2113,10 +2030,9 @@ template void UltraCircuitBuilder_:: // Record wire value can't yet be computed record.record_witness = this->add_variable(0); apply_aux_selectors(AUX_SELECTORS::ROM_READ); - w_l().emplace_back(record.index_witness); - w_r().emplace_back(record.value_column1_witness); - w_o().emplace_back(record.value_column2_witness); - w_4().emplace_back(record.record_witness); + blocks.main.populate_wires( + record.index_witness, record.value_column1_witness, record.value_column2_witness, record.record_witness); + record.gate_index = this->num_gates; ++this->num_gates; } @@ -2133,10 +2049,9 @@ void UltraCircuitBuilder_::create_sorted_ROM_gate(RomRecord& re { record.record_witness = this->add_variable(0); apply_aux_selectors(AUX_SELECTORS::ROM_CONSISTENCY_CHECK); - w_l().emplace_back(record.index_witness); - w_r().emplace_back(record.value_column1_witness); - w_o().emplace_back(record.value_column2_witness); - w_4().emplace_back(record.record_witness); + blocks.main.populate_wires( + record.index_witness, record.value_column1_witness, record.value_column2_witness, record.record_witness); + record.gate_index = this->num_gates; ++this->num_gates; } @@ -2179,10 +2094,9 @@ template void UltraCircuitBuilder_:: record.record_witness = this->add_variable(0); apply_aux_selectors(record.access_type == RamRecord::AccessType::READ ? AUX_SELECTORS::RAM_READ : AUX_SELECTORS::RAM_WRITE); - w_l().emplace_back(record.index_witness); - w_r().emplace_back(record.timestamp_witness); - w_o().emplace_back(record.value_witness); - w_4().emplace_back(record.record_witness); + blocks.main.populate_wires( + record.index_witness, record.timestamp_witness, record.value_witness, record.record_witness); + record.gate_index = this->num_gates; ++this->num_gates; } @@ -2200,10 +2114,9 @@ void UltraCircuitBuilder_::create_sorted_RAM_gate(RamRecord& re { record.record_witness = this->add_variable(0); apply_aux_selectors(AUX_SELECTORS::RAM_CONSISTENCY_CHECK); - w_l().emplace_back(record.index_witness); - w_r().emplace_back(record.timestamp_witness); - w_o().emplace_back(record.value_witness); - w_4().emplace_back(record.record_witness); + blocks.main.populate_wires( + record.index_witness, record.timestamp_witness, record.value_witness, record.record_witness); + record.gate_index = this->num_gates; ++this->num_gates; } @@ -2695,10 +2608,9 @@ template void UltraCircuitBuilder_:: uint32_t timestamp_delta_witness = this->add_variable(timestamp_delta); apply_aux_selectors(AUX_SELECTORS::RAM_TIMESTAMP_CHECK); - w_l().emplace_back(current.index_witness); - w_r().emplace_back(current.timestamp_witness); - w_o().emplace_back(timestamp_delta_witness); - w_4().emplace_back(this->zero_idx); + blocks.main.populate_wires( + current.index_witness, current.timestamp_witness, timestamp_delta_witness, this->zero_idx); + ++this->num_gates; // store timestamp offsets for later. Need to apply range checks to them, but calling @@ -3288,6 +3200,9 @@ inline typename Arithmetization::FF UltraCircuitBuilder_::compu * * @details The method switches the circuit to the "in-the-head" version, finalizes it, checks gates, lookups and * permutations and then switches it back from the in-the-head version, discarding the updates + * @note We want to check that the whole circuit works, but ultra circuits need to have ram, rom and range gates added + * in the end for the check to be complete as well as the set permutation check, so we finalize the circuit when we + * check it. This structure allows us to restore the circuit to the state before the finalization. * * @return true * @return false @@ -3295,9 +3210,11 @@ inline typename Arithmetization::FF UltraCircuitBuilder_::compu template bool UltraCircuitBuilder_::check_circuit() { bool result = true; - CircuitDataBackup circuit_backup = CircuitDataBackup::store_prefinilized_state(this); - // Finalize circuit-in-the-head + // Copy prefinalized circuit so that original circuit can be restored prior to return + UltraCircuitBuilder_ prefinalized_circuit = *this; + + // Finalize the circuit finalize_circuit(); // Sample randomness @@ -3397,26 +3314,26 @@ template bool UltraCircuitBuilder_:: FF w_4_value; FF w_4_index; // Get the values of selectors and wires and update tag products along the way - q_arith_value = q_arith()[i]; - q_aux_value = q_aux()[i]; - q_elliptic_value = q_elliptic()[i]; - q_sort_value = q_sort()[i]; - q_lookup_type_value = q_lookup_type()[i]; - q_1_value = q_1()[i]; - q_2_value = q_2()[i]; - q_3_value = q_3()[i]; - q_4_value = q_4()[i]; - q_m_value = q_m()[i]; - q_c_value = q_c()[i]; - w_1_value = this->get_variable(w_l()[i]); - update_tag_check_information(w_l()[i], w_1_value); - w_2_value = this->get_variable(w_r()[i]); - update_tag_check_information(w_r()[i], w_2_value); - w_3_value = this->get_variable(w_o()[i]); - update_tag_check_information(w_o()[i], w_3_value); - w_4_value = this->get_variable(w_4()[i]); + q_arith_value = blocks.main.q_arith()[i]; + q_aux_value = blocks.main.q_aux()[i]; + q_elliptic_value = blocks.main.q_elliptic()[i]; + q_sort_value = blocks.main.q_sort()[i]; + q_lookup_type_value = blocks.main.q_lookup_type()[i]; + q_1_value = blocks.main.q_1()[i]; + q_2_value = blocks.main.q_2()[i]; + q_3_value = blocks.main.q_3()[i]; + q_4_value = blocks.main.q_4()[i]; + q_m_value = blocks.main.q_m()[i]; + q_c_value = blocks.main.q_c()[i]; + w_1_value = this->get_variable(blocks.main.w_l()[i]); + update_tag_check_information(blocks.main.w_l()[i], w_1_value); + w_2_value = this->get_variable(blocks.main.w_r()[i]); + update_tag_check_information(blocks.main.w_r()[i], w_2_value); + w_3_value = this->get_variable(blocks.main.w_o()[i]); + update_tag_check_information(blocks.main.w_o()[i], w_3_value); + w_4_value = this->get_variable(blocks.main.w_4()[i]); // We need to wait before updating tag product for w_4 - w_4_index = w_4()[i]; + w_4_index = blocks.main.w_4()[i]; // If we are touching a gate with memory access, we need to update the value of the 4th witness if (memory_read_record_gates.contains(i)) { @@ -3432,10 +3349,10 @@ template bool UltraCircuitBuilder_:: FF w_3_shifted_value; FF w_4_shifted_value; if (i < (this->num_gates - 1)) { - w_1_shifted_value = this->get_variable(w_l()[i + 1]); - w_2_shifted_value = this->get_variable(w_r()[i + 1]); - w_3_shifted_value = this->get_variable(w_o()[i + 1]); - w_4_shifted_value = this->get_variable(w_4()[i + 1]); + w_1_shifted_value = this->get_variable(blocks.main.w_l()[i + 1]); + w_2_shifted_value = this->get_variable(blocks.main.w_r()[i + 1]); + w_3_shifted_value = this->get_variable(blocks.main.w_o()[i + 1]); + w_4_shifted_value = this->get_variable(blocks.main.w_4()[i + 1]); } else { w_1_shifted_value = FF::zero(); w_2_shifted_value = FF::zero(); @@ -3549,7 +3466,10 @@ template bool UltraCircuitBuilder_:: result = false; } - circuit_backup.restore_prefinilized_state(this); + + // Restore the circuit to its pre-finalized state + *this = prefinalized_circuit; + return result; } template class UltraCircuitBuilder_>; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp index d9e533c15c1..fef275152d2 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp @@ -1,5 +1,6 @@ #pragma once #include "barretenberg/polynomials/polynomial.hpp" +#include "barretenberg/proof_system/execution_trace/execution_trace.hpp" #include "barretenberg/proof_system/op_queue/ecc_op_queue.hpp" #include "barretenberg/proof_system/plookup_tables/plookup_tables.hpp" #include "barretenberg/proof_system/plookup_tables/types.hpp" @@ -24,10 +25,12 @@ template struct non_native_field_witnesses { using namespace bb; -template -class UltraCircuitBuilder_ : public CircuitBuilderBase { +template +class UltraCircuitBuilder_ : public CircuitBuilderBase { public: - using Selectors = Arithmetization; + using Arithmetization = Arithmetization_; + using GateBlocks = typename Arithmetization::TraceBlocks; + using FF = typename Arithmetization::FF; static constexpr size_t NUM_WIRES = Arithmetization::NUM_WIRES; // Keeping NUM_WIRES, at least temporarily, for backward compatibility @@ -268,347 +271,8 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase>; - using SelectorVector = std::vector>; - - std::vector public_inputs; - std::vector variables; - // index of next variable in equivalence class (=REAL_VARIABLE if you're last) - std::vector next_var_index; - // index of previous variable in equivalence class (=FIRST if you're in a cycle alone) - std::vector prev_var_index; - // indices of corresponding real variables - std::vector real_variable_index; - std::vector real_variable_tags; - std::map constant_variable_indices; - WireVector w_l; - WireVector w_r; - WireVector w_o; - WireVector w_4; - SelectorVector q_m; - SelectorVector q_c; - SelectorVector q_1; - SelectorVector q_2; - SelectorVector q_3; - SelectorVector q_4; - SelectorVector q_arith; - SelectorVector q_sort; - SelectorVector q_elliptic; - SelectorVector q_aux; - SelectorVector q_lookup_type; - uint32_t current_tag = DUMMY_TAG; - std::map tau; - - std::vector ram_arrays; - std::vector rom_arrays; - - std::vector memory_read_records; - std::vector memory_write_records; - std::map range_lists; - - std::vector - cached_partial_non_native_field_multiplications; - - size_t num_gates; - bool circuit_finalized = false; - /** - * @brief Stores the state of everything logic-related in the builder. - * - * @details We need this function for tests. Specifically, to ensure that we are not changing anything in - * check_circuit - * - * @param builder - * @return CircuitDataBackup - */ - template static CircuitDataBackup store_full_state(const CircuitBuilder& builder) - { - CircuitDataBackup stored_state; - stored_state.public_inputs = builder.public_inputs; - stored_state.variables = builder.variables; - - stored_state.next_var_index = builder.next_var_index; - - stored_state.prev_var_index = builder.prev_var_index; - - stored_state.real_variable_index = builder.real_variable_index; - stored_state.real_variable_tags = builder.real_variable_tags; - stored_state.constant_variable_indices = builder.constant_variable_indices; - stored_state.w_l = builder.w_l(); - stored_state.w_r = builder.w_r(); - stored_state.w_o = builder.w_o(); - stored_state.w_4 = builder.w_4(); - stored_state.q_m = builder.q_m(); - stored_state.q_c = builder.q_c(); - stored_state.q_1 = builder.q_1(); - stored_state.q_2 = builder.q_2(); - stored_state.q_3 = builder.q_3(); - stored_state.q_4 = builder.q_4(); - stored_state.q_arith = builder.q_arith(); - stored_state.q_sort = builder.q_sort(); - stored_state.q_elliptic = builder.q_elliptic(); - stored_state.q_aux = builder.q_aux(); - stored_state.q_lookup_type = builder.q_lookup_type(); - stored_state.current_tag = builder.current_tag; - stored_state.tau = builder.tau; - - stored_state.ram_arrays = builder.ram_arrays; - stored_state.rom_arrays = builder.rom_arrays; - - stored_state.memory_read_records = builder.memory_read_records; - stored_state.memory_write_records = builder.memory_write_records; - stored_state.range_lists = builder.range_lists; - stored_state.circuit_finalized = builder.circuit_finalized; - stored_state.num_gates = builder.num_gates; - stored_state.cached_partial_non_native_field_multiplications = - builder.cached_partial_non_native_field_multiplications; - return stored_state; - } - - /** - * @brief Stores the state of all members of the circuit constructor that are needed to restore the state - * after finalizing the circuit. - * - * @param builder - * @return CircuitDataBackup - */ - template - static CircuitDataBackup store_prefinilized_state(const CircuitBuilder* builder) - { - CircuitDataBackup stored_state; - stored_state.public_inputs = builder->public_inputs; - stored_state.variables = builder->variables; - - stored_state.next_var_index = builder->next_var_index; - - stored_state.prev_var_index = builder->prev_var_index; - - stored_state.real_variable_index = builder->real_variable_index; - stored_state.real_variable_tags = builder->real_variable_tags; - stored_state.constant_variable_indices = builder->constant_variable_indices; - stored_state.current_tag = builder->current_tag; - stored_state.tau = builder->tau; - - stored_state.ram_arrays = builder->ram_arrays; - stored_state.rom_arrays = builder->rom_arrays; - - stored_state.memory_read_records = builder->memory_read_records; - stored_state.memory_write_records = builder->memory_write_records; - stored_state.range_lists = builder->range_lists; - stored_state.circuit_finalized = builder->circuit_finalized; - stored_state.num_gates = builder->num_gates; - stored_state.cached_partial_non_native_field_multiplications = - builder->cached_partial_non_native_field_multiplications; - - return stored_state; - } - - /** - * @brief Restores circuit constructor to a prefinilized state. - * - * @param builder - * @return CircuitDataBackup - */ - template void restore_prefinilized_state(CircuitBuilder* builder) - { - builder->public_inputs = public_inputs; - builder->variables = variables; - - builder->next_var_index = next_var_index; - - builder->prev_var_index = prev_var_index; - - builder->real_variable_index = real_variable_index; - builder->real_variable_tags = real_variable_tags; - builder->constant_variable_indices = constant_variable_indices; - builder->current_tag = current_tag; - builder->tau = tau; - - builder->ram_arrays = ram_arrays; - builder->rom_arrays = rom_arrays; - - builder->memory_read_records = memory_read_records; - builder->memory_write_records = memory_write_records; - builder->range_lists = range_lists; - builder->circuit_finalized = circuit_finalized; - builder->num_gates = num_gates; - builder->cached_partial_non_native_field_multiplications = cached_partial_non_native_field_multiplications; - builder->w_l().resize(num_gates); - builder->w_r().resize(num_gates); - builder->w_o().resize(num_gates); - builder->w_4().resize(num_gates); - builder->q_m().resize(num_gates); - builder->q_c().resize(num_gates); - builder->q_1().resize(num_gates); - builder->q_2().resize(num_gates); - builder->q_3().resize(num_gates); - builder->q_4().resize(num_gates); - builder->q_arith().resize(num_gates); - builder->q_sort().resize(num_gates); - builder->q_elliptic().resize(num_gates); - builder->q_aux().resize(num_gates); - builder->q_lookup_type().resize(num_gates); - if constexpr (HasAdditionalSelectors) { - builder->selectors.resize_additional(num_gates); - } - } - /** - * @brief Checks that the circuit state is the same as the stored circuit's one - * - * @param builder - * @return true - * @return false - */ - template bool is_same_state(const CircuitBuilder& builder) - { - if (!(public_inputs == builder.public_inputs)) { - return false; - } - if (!(variables == builder.variables)) { - return false; - } - if (!(next_var_index == builder.next_var_index)) { - return false; - } - if (!(prev_var_index == builder.prev_var_index)) { - return false; - } - if (!(real_variable_index == builder.real_variable_index)) { - return false; - } - if (!(real_variable_tags == builder.real_variable_tags)) { - return false; - } - if (!(constant_variable_indices == builder.constant_variable_indices)) { - return false; - } - if (!(w_l == builder.w_l())) { - return false; - } - if (!(w_r == builder.w_r())) { - return false; - } - if (!(w_o == builder.w_o())) { - return false; - } - if (!(w_4 == builder.w_4())) { - return false; - } - if (!(q_m == builder.q_m())) { - return false; - } - if (!(q_c == builder.q_c())) { - return false; - } - if (!(q_1 == builder.q_1())) { - return false; - } - if (!(q_2 == builder.q_2())) { - return false; - } - if (!(q_3 == builder.q_3())) { - return false; - } - if (!(q_4 == builder.q_4())) { - return false; - } - if (!(q_arith == builder.q_arith())) { - return false; - } - if (!(q_sort == builder.q_sort())) { - return false; - } - if (!(q_elliptic == builder.q_elliptic())) { - return false; - } - if (!(q_aux == builder.q_aux())) { - return false; - } - if (!(q_lookup_type == builder.q_lookup_type())) { - return false; - } - if (!(current_tag == builder.current_tag)) { - return false; - } - if (!(tau == builder.tau)) { - return false; - } - if (!(ram_arrays == builder.ram_arrays)) { - return false; - } - if (!(rom_arrays == builder.rom_arrays)) { - return false; - } - if (!(memory_read_records == builder.memory_read_records)) { - return false; - } - if (!(memory_write_records == builder.memory_write_records)) { - return false; - } - if (!(range_lists == builder.range_lists)) { - return false; - } - if (!(cached_partial_non_native_field_multiplications == - builder.cached_partial_non_native_field_multiplications)) { - return false; - } - if (!(num_gates == builder.num_gates)) { - return false; - } - if (!(circuit_finalized == builder.circuit_finalized)) { - return false; - } - return true; - } - }; - - std::array>, NUM_WIRES> wires; - Arithmetization selectors; - - using WireVector = std::vector>; - using SelectorVector = std::vector>; - - WireVector& w_l() { return std::get<0>(wires); }; - WireVector& w_r() { return std::get<1>(wires); }; - WireVector& w_o() { return std::get<2>(wires); }; - WireVector& w_4() { return std::get<3>(wires); }; - - const WireVector& w_l() const { return std::get<0>(wires); }; - const WireVector& w_r() const { return std::get<1>(wires); }; - const WireVector& w_o() const { return std::get<2>(wires); }; - const WireVector& w_4() const { return std::get<3>(wires); }; - - SelectorVector& q_m() { return selectors.q_m(); }; - SelectorVector& q_c() { return selectors.q_c(); }; - SelectorVector& q_1() { return selectors.q_1(); }; - SelectorVector& q_2() { return selectors.q_2(); }; - SelectorVector& q_3() { return selectors.q_3(); }; - SelectorVector& q_4() { return selectors.q_4(); }; - SelectorVector& q_arith() { return selectors.q_arith(); }; - SelectorVector& q_sort() { return selectors.q_sort(); }; - SelectorVector& q_elliptic() { return selectors.q_elliptic(); }; - SelectorVector& q_aux() { return selectors.q_aux(); }; - SelectorVector& q_lookup_type() { return selectors.q_lookup_type(); }; - - const SelectorVector& q_c() const { return selectors.q_c(); }; - const SelectorVector& q_1() const { return selectors.q_1(); }; - const SelectorVector& q_2() const { return selectors.q_2(); }; - const SelectorVector& q_3() const { return selectors.q_3(); }; - const SelectorVector& q_4() const { return selectors.q_4(); }; - const SelectorVector& q_arith() const { return selectors.q_arith(); }; - const SelectorVector& q_sort() const { return selectors.q_sort(); }; - const SelectorVector& q_elliptic() const { return selectors.q_elliptic(); }; - const SelectorVector& q_aux() const { return selectors.q_aux(); }; - const SelectorVector& q_lookup_type() const { return selectors.q_lookup_type(); }; - const SelectorVector& q_m() const { return selectors.q_m(); }; + // Storage for wires and selectors for all gate types + GateBlocks blocks; // These are variables that we have used a gate on, to enforce that they are // equal to a defined value. @@ -649,11 +313,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase(size_hint) { - selectors.reserve(size_hint); - w_l().reserve(size_hint); - w_r().reserve(size_hint); - w_o().reserve(size_hint); - w_4().reserve(size_hint); + blocks.main.reserve(size_hint); this->zero_idx = put_constant_variable(FF::zero()); this->tau.insert({ DUMMY_TAG, DUMMY_TAG }); // TODO(luke): explain this }; @@ -678,11 +338,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase(size_hint) { - selectors.reserve(size_hint); - w_l().reserve(size_hint); - w_r().reserve(size_hint); - w_o().reserve(size_hint); - w_4().reserve(size_hint); + blocks.main.reserve(size_hint); for (size_t idx = 0; idx < varnum; ++idx) { // Zeros are added for variables whose existence is known but whose values are not yet known. The values may @@ -705,8 +361,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase(std::move(other)) { - wires = other.wires; - selectors = other.selectors; + blocks = other.blocks; constant_variable_indices = other.constant_variable_indices; lookup_tables = other.lookup_tables; @@ -723,8 +378,7 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase::operator=(std::move(other)); - wires = other.wires; - selectors = other.selectors; + blocks = other.blocks; constant_variable_indices = other.constant_variable_indices; lookup_tables = other.lookup_tables; @@ -740,6 +394,8 @@ class UltraCircuitBuilder_ : public CircuitBuilderBase>= table_bits; } } - auto saved_state = UltraCircuitBuilder::CircuitDataBackup::store_full_state(circuit_builder); + + UltraCircuitBuilder circuit_copy{ circuit_builder }; bool result = circuit_builder.check_circuit(); EXPECT_EQ(result, true); - EXPECT_TRUE(saved_state.is_same_state(circuit_builder)); + // Ensure that check_circuit did not alter the circuit + EXPECT_EQ(circuit_copy, circuit_builder); } TEST(ultra_circuit_constructor, base_case) @@ -154,11 +156,12 @@ TEST(ultra_circuit_constructor, test_elliptic_gate) circuit_constructor.create_ecc_add_gate({ x1, y1, x2, y2, x3, y3, 1 }); - auto saved_state = UltraCircuitBuilder::CircuitDataBackup::store_full_state(circuit_constructor); + UltraCircuitBuilder circuit_copy{ circuit_constructor }; bool result = circuit_constructor.check_circuit(); EXPECT_EQ(result, true); - EXPECT_TRUE(saved_state.is_same_state(circuit_constructor)); + // Ensure that check_circuit did not alter the circuit + EXPECT_EQ(circuit_copy, circuit_constructor); circuit_constructor.create_ecc_add_gate({ x1 + 1, y1, x2, y2, x3, y3, 1 }); @@ -181,11 +184,12 @@ TEST(ultra_circuit_constructor, test_elliptic_double_gate) circuit_constructor.create_ecc_dbl_gate({ x1, y1, x3, y3 }); - auto saved_state = UltraCircuitBuilder::CircuitDataBackup::store_full_state(circuit_constructor); + UltraCircuitBuilder circuit_copy{ circuit_constructor }; bool result = circuit_constructor.check_circuit(); EXPECT_EQ(result, true); - EXPECT_TRUE(saved_state.is_same_state(circuit_constructor)); + // Ensure that check_circuit did not alter the circuit + EXPECT_EQ(circuit_copy, circuit_constructor); } TEST(ultra_circuit_constructor, non_trivial_tag_permutation) @@ -212,11 +216,12 @@ TEST(ultra_circuit_constructor, non_trivial_tag_permutation) circuit_constructor.assign_tag(c_idx, 2); circuit_constructor.assign_tag(d_idx, 2); - auto saved_state = UltraCircuitBuilder::CircuitDataBackup::store_full_state(circuit_constructor); + UltraCircuitBuilder circuit_copy{ circuit_constructor }; bool result = circuit_constructor.check_circuit(); EXPECT_EQ(result, true); - EXPECT_TRUE(saved_state.is_same_state(circuit_constructor)); + // Ensure that check_circuit did not alter the circuit + EXPECT_EQ(circuit_copy, circuit_constructor); // Break the tag circuit_constructor.real_variable_tags[circuit_constructor.real_variable_index[a_idx]] = 2; @@ -257,11 +262,12 @@ TEST(ultra_circuit_constructor, non_trivial_tag_permutation_and_cycles) circuit_constructor.create_add_gate( { e_idx, f_idx, circuit_constructor.zero_idx, fr::one(), -fr::one(), fr::zero(), fr::zero() }); - auto saved_state = UltraCircuitBuilder::CircuitDataBackup::store_full_state(circuit_constructor); + UltraCircuitBuilder circuit_copy{ circuit_constructor }; bool result = circuit_constructor.check_circuit(); EXPECT_EQ(result, true); - EXPECT_TRUE(saved_state.is_same_state(circuit_constructor)); + // Ensure that check_circuit did not alter the circuit + EXPECT_EQ(circuit_copy, circuit_constructor); // Break the tag circuit_constructor.real_variable_tags[circuit_constructor.real_variable_index[a_idx]] = 2; @@ -281,11 +287,12 @@ TEST(ultra_circuit_constructor, bad_tag_permutation) circuit_constructor.create_add_gate({ a_idx, b_idx, circuit_constructor.zero_idx, 1, 1, 0, 0 }); circuit_constructor.create_add_gate({ c_idx, d_idx, circuit_constructor.zero_idx, 1, 1, 0, -1 }); - auto saved_state = UltraCircuitBuilder::CircuitDataBackup::store_full_state(circuit_constructor); + UltraCircuitBuilder circuit_copy{ circuit_constructor }; bool result = circuit_constructor.check_circuit(); EXPECT_EQ(result, true); - EXPECT_TRUE(saved_state.is_same_state(circuit_constructor)); + // Ensure that check_circuit did not alter the circuit + EXPECT_EQ(circuit_copy, circuit_constructor); circuit_constructor.create_tag(1, 2); circuit_constructor.create_tag(2, 1); @@ -654,11 +661,13 @@ TEST(ultra_circuit_constructor, non_native_field_multiplication) const auto [lo_1_idx, hi_1_idx] = circuit_constructor.evaluate_non_native_field_multiplication(inputs); circuit_constructor.range_constrain_two_limbs(lo_1_idx, hi_1_idx, 70, 70); - auto saved_state = UltraCircuitBuilder::CircuitDataBackup::store_full_state(circuit_constructor); + UltraCircuitBuilder circuit_copy{ circuit_constructor }; + bool result = circuit_constructor.check_circuit(); EXPECT_EQ(result, true); - EXPECT_TRUE(saved_state.is_same_state(circuit_constructor)); + // Ensure that check_circuit did not alter the circuit + EXPECT_EQ(circuit_copy, circuit_constructor); } TEST(ultra_circuit_constructor, rom) @@ -764,12 +773,13 @@ TEST(ultra_circuit_constructor, ram) }, false); - auto saved_state = UltraCircuitBuilder::CircuitDataBackup::store_full_state(circuit_constructor); + UltraCircuitBuilder circuit_copy{ circuit_constructor }; bool result = circuit_constructor.check_circuit(); EXPECT_EQ(result, true); - EXPECT_TRUE(saved_state.is_same_state(circuit_constructor)); + // Ensure that check_circuit did not alter the circuit + EXPECT_EQ(circuit_copy, circuit_constructor); // Test the builder copy constructor for a circuit with RAM gates UltraCircuitBuilder duplicate_circuit_constructor{ circuit_constructor }; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/execution_trace/execution_trace.cpp b/barretenberg/cpp/src/barretenberg/proof_system/execution_trace/execution_trace.cpp index 2235bf8f2c6..6c94579f4d7 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/execution_trace/execution_trace.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/execution_trace/execution_trace.cpp @@ -6,7 +6,7 @@ namespace bb { template -void ExecutionTrace_::generate(const Builder& builder, +void ExecutionTrace_::populate(Builder& builder, const std::shared_ptr& proving_key) { // Construct wire polynomials, selector polynomials, and copy cycles from raw circuit data @@ -14,20 +14,24 @@ void ExecutionTrace_::generate(const Builder& builder, add_wires_and_selectors_to_proving_key(trace_data, builder, proving_key); + if constexpr (IsGoblinFlavor) { + add_ecc_op_wires_to_proving_key(builder, proving_key); + } + // Compute the permutation argument polynomials (sigma/id) and add them to proving key compute_permutation_argument_polynomials(builder, proving_key.get(), trace_data.copy_cycles); } template void ExecutionTrace_::add_wires_and_selectors_to_proving_key( - TraceData& trace_data, const Builder& builder, const std::shared_ptr& proving_key) + TraceData& trace_data, Builder& builder, const std::shared_ptr& proving_key) { if constexpr (IsHonkFlavor) { for (auto [pkey_wire, trace_wire] : zip_view(proving_key->get_wires(), trace_data.wires)) { - pkey_wire = std::move(trace_wire); + pkey_wire = trace_wire.share(); } for (auto [pkey_selector, trace_selector] : zip_view(proving_key->get_selectors(), trace_data.selectors)) { - pkey_selector = std::move(trace_selector); + pkey_selector = trace_selector.share(); } } else if constexpr (IsPlonkFlavor) { for (size_t idx = 0; idx < trace_data.wires.size(); ++idx) { @@ -42,19 +46,17 @@ void ExecutionTrace_::add_wires_and_selectors_to_proving_key( } template -typename ExecutionTrace_::TraceData ExecutionTrace_::construct_trace_data(const Builder& builder, +typename ExecutionTrace_::TraceData ExecutionTrace_::construct_trace_data(Builder& builder, size_t dyadic_circuit_size) { TraceData trace_data{ dyadic_circuit_size, builder }; - // TODO(https://github.com/AztecProtocol/barretenberg/issues/862): Eventually trace_blocks will be constructed - // directly in the builder, i.e. the gate addition methods will directly populate the wire/selectors in the - // appropriate block. In the mean time we do some inefficient copying etc to construct it here post facto. - auto trace_blocks = create_execution_trace_blocks(builder); + // Complete the public inputs execution trace block from builder.public_inputs + populate_public_inputs_block(builder); - uint32_t offset = 0; // Track offset at which to place each block in the trace polynomials + uint32_t offset = Flavor::has_zero_row ? 1 : 0; // Offset at which to place each block in the trace polynomials // For each block in the trace, populate wire polys, copy cycles and selector polys - for (auto& block : trace_blocks) { + for (auto& block : builder.blocks.get()) { auto block_size = static_cast(block.wires[0].size()); // Update wire polynomials and copy cycles @@ -73,7 +75,7 @@ typename ExecutionTrace_::TraceData ExecutionTrace_::construct_t // Insert the selector values for this block into the selector polynomials at the correct offset // TODO(https://github.com/AztecProtocol/barretenberg/issues/398): implicit arithmetization/flavor consistency - for (auto [selector_poly, selector] : zip_view(trace_data.selectors, block.selectors.get())) { + for (auto [selector_poly, selector] : zip_view(trace_data.selectors, block.selectors)) { for (size_t row_idx = 0; row_idx < block_size; ++row_idx) { size_t trace_row_idx = row_idx + offset; selector_poly[trace_row_idx] = selector[row_idx]; @@ -85,52 +87,51 @@ typename ExecutionTrace_::TraceData ExecutionTrace_::construct_t return trace_data; } -template -std::vector::TraceBlock> ExecutionTrace_::create_execution_trace_blocks( - const Builder& builder) +template void ExecutionTrace_::populate_public_inputs_block(Builder& builder) { - std::vector trace_blocks; - - // Make a block for the zero row - if constexpr (Flavor::has_zero_row) { - TraceBlock zero_block; - for (auto& wire : zero_block.wires) { - wire.emplace_back(builder.zero_idx); - } - for (auto& selector : zero_block.selectors.get()) { - selector.emplace_back(0); - } - trace_blocks.emplace_back(zero_block); - } - - // Make a block for the ecc op wires - if constexpr (IsGoblinFlavor) { - trace_blocks.emplace_back(builder.ecc_op_block); - } - - // Make a block for the public inputs - TraceBlock public_block; + // Update the public inputs block for (auto& idx : builder.public_inputs) { for (size_t wire_idx = 0; wire_idx < NUM_WIRES; ++wire_idx) { if (wire_idx < 2) { // first two wires get a copy of the public inputs - public_block.wires[wire_idx].emplace_back(idx); + builder.blocks.pub_inputs.wires[wire_idx].emplace_back(idx); } else { // the remaining wires get zeros - public_block.wires[wire_idx].emplace_back(builder.zero_idx); + builder.blocks.pub_inputs.wires[wire_idx].emplace_back(builder.zero_idx); } } - for (auto& selector : public_block.selectors.get()) { + for (auto& selector : builder.blocks.pub_inputs.selectors) { selector.emplace_back(0); } } +} - public_block.is_public_input = true; - trace_blocks.emplace_back(public_block); - - // Make a block for the basic wires and selectors - TraceBlock conventional_block{ builder.wires, builder.selectors }; - trace_blocks.emplace_back(conventional_block); +template +void ExecutionTrace_::add_ecc_op_wires_to_proving_key( + Builder& builder, const std::shared_ptr& proving_key) + requires IsGoblinFlavor +{ + // Initialize the ecc op wire polynomials to zero on the whole domain + std::array op_wire_polynomials; + for (auto& poly : op_wire_polynomials) { + poly = Polynomial{ proving_key->circuit_size }; + } + Polynomial ecc_op_selector{ proving_key->circuit_size }; + + // Copy the ecc op data from the conventional wires into the op wires over the range of ecc op gates + const size_t op_wire_offset = Flavor::has_zero_row ? 1 : 0; + for (auto [ecc_op_wire, wire] : zip_view(op_wire_polynomials, proving_key->get_wires())) { + for (size_t i = 0; i < builder.num_ecc_op_gates; ++i) { + size_t idx = i + op_wire_offset; + ecc_op_wire[idx] = wire[idx]; + ecc_op_selector[idx] = 1; // construct the selector as the indicator on the ecc op block + } + } - return trace_blocks; + proving_key->num_ecc_op_gates = builder.num_ecc_op_gates; + proving_key->ecc_op_wire_1 = op_wire_polynomials[0].share(); + proving_key->ecc_op_wire_2 = op_wire_polynomials[1].share(); + proving_key->ecc_op_wire_3 = op_wire_polynomials[2].share(); + proving_key->ecc_op_wire_4 = op_wire_polynomials[3].share(); + proving_key->lagrange_ecc_op = ecc_op_selector.share(); } template class ExecutionTrace_; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/execution_trace/execution_trace.hpp b/barretenberg/cpp/src/barretenberg/proof_system/execution_trace/execution_trace.hpp index a79877761de..6f635786e39 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/execution_trace/execution_trace.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/execution_trace/execution_trace.hpp @@ -5,26 +5,12 @@ namespace bb { -/** - * @brief The wires and selectors used to define a block in the execution trace - * - * @tparam Arithmetization The set of selectors corresponding to the arithmetization - */ -template struct ExecutionTraceBlock { - // WORKTODO: Zac - make this less terrible - using Wires = std::array>, Arithmetization::NUM_WIRES>; - Wires wires; - Arithmetization selectors; - bool is_public_input = false; -}; - template class ExecutionTrace_ { using Builder = typename Flavor::CircuitBuilder; using Polynomial = typename Flavor::Polynomial; using FF = typename Flavor::FF; - using TraceBlock = ExecutionTraceBlock; + using TrackBlocks = typename Builder::Arithmetization::TraceBlocks; using Wires = std::array>, Builder::NUM_WIRES>; - using Selectors = typename Builder::Selectors; using ProvingKey = typename Flavor::ProvingKey; public: @@ -32,11 +18,11 @@ template class ExecutionTrace_ { struct TraceData { std::array wires; - std::array selectors; + std::array selectors; // A vector of sets (vectors) of addresses into the wire polynomials whose values are copy constrained std::vector copy_cycles; - TraceData(size_t dyadic_circuit_size, const Builder& builder) + TraceData(size_t dyadic_circuit_size, Builder& builder) { // Initializate the wire and selector polynomials for (auto& wire : wires) { @@ -54,7 +40,7 @@ template class ExecutionTrace_ { * * @param builder */ - static void generate(const Builder& builder, const std::shared_ptr&); + static void populate(Builder& builder, const std::shared_ptr&); private: /** @@ -65,7 +51,7 @@ template class ExecutionTrace_ { * @param proving_key */ static void add_wires_and_selectors_to_proving_key(TraceData& trace_data, - const Builder& builder, + Builder& builder, const std::shared_ptr& proving_key); /** @@ -75,16 +61,27 @@ template class ExecutionTrace_ { * @param dyadic_circuit_size * @return TraceData */ - static TraceData construct_trace_data(const Builder& builder, size_t dyadic_circuit_size); + static TraceData construct_trace_data(Builder& builder, size_t dyadic_circuit_size); + + /** + * @brief Populate the public inputs block + * @details The first two wires are a copy of the public inputs and the other wires and all selectors are zero + * + * @param builder + */ + static void populate_public_inputs_block(Builder& builder); /** - * @brief Temporary helper method to construct execution trace blocks from existing builder structures - * @details Eventually the builder will construct blocks directly + * @brief Construct and add the goblin ecc op wires to the proving key + * @details The ecc op wires vanish everywhere except on the ecc op block, where they contain a copy of the ecc op + * data assumed already to be present in the corrresponding block of the conventional wires in the proving key. * * @param builder - * @return std::vector + * @param proving_key */ - static std::vector create_execution_trace_blocks(const Builder& builder); + static void add_ecc_op_wires_to_proving_key(Builder& builder, + const std::shared_ptr& proving_key) + requires IsGoblinFlavor; }; } // namespace bb \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/types.hpp b/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/types.hpp index 489d9e60071..0dfcaa916d3 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/types.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/plookup_tables/types.hpp @@ -190,6 +190,7 @@ struct MultiTable { MultiTable& operator=(const MultiTable& other) = default; MultiTable& operator=(MultiTable&& other) = default; + bool operator==(const MultiTable& other) const = default; }; // struct PlookupLargeKeyTable { @@ -262,6 +263,8 @@ struct MultiTable { */ struct BasicTable { struct KeyEntry { + bool operator==(const KeyEntry& other) const = default; + std::array key{ 0, 0 }; std::array value{ bb::fr(0), bb::fr(0) }; bool operator<(const KeyEntry& other) const @@ -296,6 +299,8 @@ struct BasicTable { std::vector lookup_gates; std::array (*get_values_from_key)(const std::array); + + bool operator==(const BasicTable& other) const = default; }; enum ColumnIdx { C1, C2, C3 }; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp index 6977453e34a..da806c978ef 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/field/field.test.cpp @@ -180,7 +180,12 @@ template class stdlib_field : public testing::Test { auto gates_before = builder.get_num_gates(); uint64_t expected = fidget(builder); auto gates_after = builder.get_num_gates(); - EXPECT_EQ(builder.get_variable(builder.w_o()[gates_after - 1]), fr(expected)); + if constexpr (IsAnyOf) { + EXPECT_EQ(builder.get_variable(builder.blocks.arithmetic.w_o()[gates_after - 1]), fr(expected)); + } + if constexpr (IsAnyOf) { + EXPECT_EQ(builder.get_variable(builder.blocks.main.w_o()[gates_after - 1]), fr(expected)); + } info("Number of gates added", gates_after - gates_before); bool result = builder.check_circuit(); EXPECT_EQ(result, true); @@ -254,7 +259,12 @@ template class stdlib_field : public testing::Test { auto gates_before = builder.get_num_gates(); fibbonaci(builder); auto gates_after = builder.get_num_gates(); - EXPECT_EQ(builder.get_variable(builder.w_l()[builder.get_num_gates() - 1]), fr(4181)); + if constexpr (IsAnyOf) { + EXPECT_EQ(builder.get_variable(builder.blocks.arithmetic.w_l()[builder.get_num_gates() - 1]), fr(4181)); + } + if constexpr (IsAnyOf) { + EXPECT_EQ(builder.get_variable(builder.blocks.main.w_l()[builder.get_num_gates() - 1]), fr(4181)); + } EXPECT_EQ(gates_after - gates_before, 18UL); bool result = builder.check_circuit(); diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp index 1f2d09bb086..db6030ed29b 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.cpp @@ -32,44 +32,6 @@ template size_t ProverInstance_::compute_dyadic_size(Circ return circuit.get_circuit_subgroup_size(total_num_gates); } -/** - * @brief Construct Goblin style ECC op wire polynomials - * @details The Ecc op wire values are assumed to have already been stored in the corresponding block of the - * conventional wire polynomials. The values for the ecc op wire polynomials are set based on those values. - * - * @tparam Flavor - * @param wire_polynomials - */ -template -void ProverInstance_::construct_ecc_op_wire_polynomials(Circuit& circuit) - requires IsGoblinFlavor -{ - std::array op_wire_polynomials; - for (auto& poly : op_wire_polynomials) { - poly = Polynomial{ dyadic_circuit_size }; - } - Polynomial ecc_op_selector{ dyadic_circuit_size }; - - // The ECC op wires are constructed to contain the op data on the appropriate range and to vanish everywhere else. - // The op data is assumed to have already been stored at the correct location in the convetional wires so the data - // can simply be copied over directly. - const size_t op_wire_offset = Flavor::has_zero_row ? 1 : 0; - for (auto [ecc_op_wire, wire] : zip_view(op_wire_polynomials, proving_key->get_wires())) { - for (size_t i = 0; i < circuit.num_ecc_op_gates; ++i) { - size_t idx = i + op_wire_offset; - ecc_op_wire[idx] = wire[idx]; - ecc_op_selector[idx] = 1; - } - } - - proving_key->num_ecc_op_gates = circuit.num_ecc_op_gates; - proving_key->ecc_op_wire_1 = op_wire_polynomials[0].share(); - proving_key->ecc_op_wire_2 = op_wire_polynomials[1].share(); - proving_key->ecc_op_wire_3 = op_wire_polynomials[2].share(); - proving_key->ecc_op_wire_4 = op_wire_polynomials[3].share(); - proving_key->lagrange_ecc_op = ecc_op_selector.share(); -} - /** * @brief * @details diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp index d2b8da8f28e..5313f7b8304 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.hpp @@ -69,12 +69,10 @@ template class ProverInstance_ { proving_key = std::make_shared(dyadic_circuit_size, circuit.public_inputs.size()); // Construct and add to proving key the wire, selector and copy constraint polynomials - Trace::generate(circuit, proving_key); + Trace::populate(circuit, proving_key); - // If Goblin, construct the ECC op queue wire and databus polynomials - // TODO(https://github.com/AztecProtocol/barretenberg/issues/862): Maybe do this in trace generation? + // If Goblin, construct the databus polynomials if constexpr (IsGoblinFlavor) { - construct_ecc_op_wire_polynomials(circuit); construct_databus_polynomials(circuit); } @@ -116,9 +114,6 @@ template class ProverInstance_ { size_t compute_dyadic_size(Circuit&); - void construct_ecc_op_wire_polynomials(Circuit&) - requires IsGoblinFlavor; - void construct_databus_polynomials(Circuit&) requires IsGoblinFlavor;