diff --git a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp index 9b079013dfdd..4958e940df7f 100644 --- a/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/plonk/composer/composer_lib.hpp @@ -55,9 +55,9 @@ void enforce_nonzero_selector_polynomials(const auto& circuit_constructor, auto* { for (size_t idx = 0; idx < circuit_constructor.num_selectors; ++idx) { auto current_selector = - proving_key->polynomial_store.get(circuit_constructor.selector_names_[idx] + "_lagrange"); + proving_key->polynomial_store.get(circuit_constructor.selector_names[idx] + "_lagrange"); current_selector[current_selector.size() - 1] = idx + 1; - proving_key->polynomial_store.put(circuit_constructor.selector_names_[idx] + "_lagrange", + proving_key->polynomial_store.put(circuit_constructor.selector_names[idx] + "_lagrange", std::move(current_selector)); } } diff --git a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp index 59c573229f7a..d62bc2b52e04 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp @@ -17,167 +17,96 @@ namespace arithmetization { * @remark It may make sense to say this is only partial arithmetization data, with the full data being * contained in the circuit constructor. We could change the name of this class if it conflicts with common usage. * - * @tparam _NUM_WIRES - * @tparam _num_selectors + * @note For even greater modularity, in each instantiation we could specify a list of components here, where a + * component is a meaningful collection of functions for creating gates, as in: + * + * struct Component { + * using Arithmetic = component::Arithmetic3Wires; + * using RangeConstraints = component::Base4Accumulators or component::GenPerm or... + * using LookupTables = component::Plookup4Wire or component::CQ8Wire or... + * ... + * }; + * + * We should only do this if it becomes necessary or convenient. */ -template struct Arithmetization { - static constexpr size_t NUM_WIRES = _NUM_WIRES; - static constexpr size_t num_selectors = _num_selectors; - - // Note: For even greater modularity, in each instantiation we could specify a list of components here, where a - // component is a meaningful collection of functions for creating gates, as in: - // - // struct Component { - // using Arithmetic = component::Arithmetic3Wires; - // using RangeConstraints = component::Base4Accumulators or component::GenPerm or... - // using LookupTables = component::Plookup4Wire or component::CQ8Wire or... - // ... - // }; - // - // We should only do this if it becomes necessary or convenient. -}; - -template struct SelectorsBase { - using DataType = std::array>, num_selectors>; - DataType _data; - size_t size() { return _data.size(); }; - typename DataType::const_iterator begin() const { return _data.begin(); }; - typename DataType::iterator begin() { return _data.begin(); }; - typename DataType::const_iterator end() const { return _data.end(); }; - typename DataType::iterator end() { return _data.end(); }; -}; // 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 Standard : public Arithmetization { +template class Standard { public: - using FF = _FF; - struct Selectors : SelectorsBase { - std::vector>& q_m = std::get<0>(this->_data); - std::vector>& q_1 = std::get<1>(this->_data); - std::vector>& q_2 = std::get<2>(this->_data); - std::vector>& q_3 = std::get<3>(this->_data); - std::vector>& q_c = std::get<4>(this->_data); - Selectors() - : SelectorsBase(){}; - Selectors(const Selectors& other) - : SelectorsBase(other) - {} - Selectors(Selectors&& other) - { - this->_data = std::move(other._data); - this->q_m = std::get<0>(this->_data); - this->q_1 = std::get<1>(this->_data); - this->q_2 = std::get<2>(this->_data); - this->q_3 = std::get<3>(this->_data); - this->q_c = std::get<4>(this->_data); - }; - Selectors& operator=(Selectors&& other) - { - SelectorsBase::operator=(other); - return *this; - } - ~Selectors() = default; - }; -}; + static constexpr size_t NUM_WIRES = 3; + static constexpr size_t num_selectors = 5; + using FF = FF_; + using SelectorType = std::vector>; -template class Turbo : public Arithmetization { - public: - using FF = _FF; - struct Selectors : SelectorsBase { - std::vector>& q_m = std::get<0>(this->_data); - std::vector>& q_c = std::get<1>(this->_data); - std::vector>& q_1 = std::get<2>(this->_data); - std::vector>& q_2 = std::get<3>(this->_data); - std::vector>& q_3 = std::get<4>(this->_data); - std::vector>& q_4 = std::get<5>(this->_data); - std::vector>& q_5 = std::get<6>(this->_data); - std::vector>& q_arith = std::get<7>(this->_data); - std::vector>& q_fixed_base = std::get<8>(this->_data); - std::vector>& q_range = std::get<9>(this->_data); - std::vector>& q_logic = std::get<10>(this->_data); - Selectors() - : SelectorsBase(){}; - Selectors(const Selectors& other) - : SelectorsBase(other) - {} - Selectors(Selectors&& other) - { - this->_data = std::move(other._data); - this->q_m = std::get<0>(this->_data); - this->q_c = std::get<1>(this->_data); - this->q_1 = std::get<2>(this->_data); - this->q_2 = std::get<3>(this->_data); - this->q_3 = std::get<4>(this->_data); - this->q_4 = std::get<5>(this->_data); - this->q_5 = std::get<6>(this->_data); - this->q_arith = std::get<7>(this->_data); - this->q_fixed_base = std::get<8>(this->_data); - this->q_range = std::get<9>(this->_data); - this->q_logic = std::get<10>(this->_data); - }; - Selectors& operator=(Selectors&& other) - { - SelectorsBase::operator=(other); - return *this; + std::vector selectors; + + 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]; }; + + Standard() + : selectors(num_selectors) + {} + + const auto& get() const { return selectors; }; + + void reserve(size_t size_hint) + { + for (auto& p : selectors) { + p.reserve(size_hint); } - ~Selectors() = default; - }; + } + + // Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct. + inline static const std::vector selector_names = { "q_m", "q_1", "q_2", "q_3", "q_c" }; }; -template class Ultra : public Arithmetization { +template class Ultra { public: - using FF = _FF; - struct Selectors : SelectorsBase { - std::vector>& q_m = std::get<0>(this->_data); - std::vector>& q_c = std::get<1>(this->_data); - std::vector>& q_1 = std::get<2>(this->_data); - std::vector>& q_2 = std::get<3>(this->_data); - std::vector>& q_3 = std::get<4>(this->_data); - std::vector>& q_4 = std::get<5>(this->_data); - std::vector>& q_arith = std::get<6>(this->_data); - std::vector>& q_sort = std::get<7>(this->_data); - std::vector>& q_elliptic = std::get<8>(this->_data); - std::vector>& q_aux = std::get<9>(this->_data); - std::vector>& q_lookup_type = std::get<10>(this->_data); - Selectors() - : SelectorsBase(){}; - Selectors(const Selectors& other) - : SelectorsBase(other) - {} - Selectors(Selectors&& other) - { - this->_data = std::move(other._data); - this->q_m = std::get<0>(this->_data); - this->q_c = std::get<1>(this->_data); - this->q_1 = std::get<2>(this->_data); - this->q_2 = std::get<3>(this->_data); - this->q_3 = std::get<4>(this->_data); - this->q_4 = std::get<5>(this->_data); - this->q_arith = std::get<6>(this->_data); - this->q_sort = std::get<7>(this->_data); - this->q_elliptic = std::get<8>(this->_data); - this->q_aux = std::get<9>(this->_data); - this->q_lookup_type = std::get<10>(this->_data); - }; - Selectors& operator=(Selectors&& other) - { - SelectorsBase::operator=(other); - return *this; + static constexpr size_t NUM_WIRES = 4; + static constexpr size_t num_selectors = 11; + using FF = FF_; + using SelectorType = std::vector>; + + std::vector selectors; + + 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]; }; + + Ultra() + : selectors(num_selectors) + {} + + const auto& get() const { return selectors; }; + + void reserve(size_t size_hint) + { + for (auto& p : selectors) { + p.reserve(size_hint); } - ~Selectors() = default; - // Selectors() = default; - // Selectors(const Selectors& other) = default; - // Selectors(Selectors&& other) = default; - // Selectors& operator=(Selectors const& other) = default; - // Selectors& operator=(Selectors&& other) = default; - // ~Selectors() = default; - }; + } + + // Note: These are needed for Plonk only (for poly storage in a std::map). Must be in same order as above struct. + inline static const std::vector selector_names = { "q_m", "q_c", "q_1", "q_2", + "q_3", "q_4", "q_arith", "q_sort", + "q_elliptic", "q_aux", "table_type" }; }; -class GoblinTranslator : public Arithmetization { + +class GoblinTranslator { public: - // Dirty hack - using Selectors = bool; - using FF = curve::BN254::ScalarField; + static constexpr size_t NUM_WIRES = 81; + static constexpr size_t num_selectors = 0; }; } // namespace arithmetization \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp index b919594528e1..0b469a3b08d4 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp @@ -11,10 +11,10 @@ namespace proof_system { * @param b_variable_idx Index of a variable in class b. * @param msg Class tag. * */ -template -void CircuitBuilderBase::assert_equal(const uint32_t a_variable_idx, - const uint32_t b_variable_idx, - std::string const& msg) +template +void CircuitBuilderBase::assert_equal(const uint32_t a_variable_idx, + const uint32_t b_variable_idx, + std::string const& msg) { assert_valid_variables({ a_variable_idx, b_variable_idx }); bool values_equal = (get_variable(a_variable_idx) == get_variable(b_variable_idx)); @@ -43,8 +43,6 @@ void CircuitBuilderBase::assert_equal(const uint32_t a_variable real_variable_tags[a_real_idx] = real_variable_tags[b_real_idx]; } // Standard honk/ plonk instantiation -template class CircuitBuilderBase>; -template class CircuitBuilderBase>; -template class CircuitBuilderBase>; -template class CircuitBuilderBase; +template class CircuitBuilderBase; +template class CircuitBuilderBase; } // namespace proof_system 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 cb226fc5255c..140d98b234fe 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 @@ -1,5 +1,4 @@ #pragma once -#include "barretenberg/common/slab_allocator.hpp" #include "barretenberg/ecc/curves/bn254/fr.hpp" #include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include "barretenberg/proof_system/arithmetization/arithmetization.hpp" @@ -12,25 +11,14 @@ namespace proof_system { static constexpr uint32_t DUMMY_TAG = 0; -template class CircuitBuilderBase { +template class CircuitBuilderBase { public: - using FF = typename Arithmetization::FF; + using FF = FF_; using EmbeddedCurve = std::conditional_t, curve::BN254, curve::Grumpkin>; - 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; - static constexpr size_t num_selectors = Arithmetization::num_selectors; - - // TODO(Cody): These are plonk-specific and could be specified in the plonk flavors. - // Also, there is loose coupling with the vectors of SelectorProperties - std::vector selector_names_; size_t num_gates = 0; - std::array>, NUM_WIRES> wires; - typename Arithmetization::Selectors selectors; - std::vector public_inputs; std::vector variables; std::unordered_map variable_names; @@ -57,13 +45,7 @@ template class CircuitBuilderBase { static constexpr uint32_t REAL_VARIABLE = UINT32_MAX - 1; static constexpr uint32_t FIRST_VARIABLE_IN_CLASS = UINT32_MAX - 2; - // Enum values spaced in increments of 30-bits (multiples of 2 ** 30). - // TODO(#216)(Adrian): This is unused, and this type of hard coded data should be avoided - // Cody: This is used by compute_wire_copy_cycles in Plonk. - // enum WireType { LEFT = 0U, RIGHT = (1U << 30U), OUTPUT = (1U << 31U), FOURTH = 0xc0000000 }; - - CircuitBuilderBase(std::vector selector_names, size_t size_hint = 0) - : selector_names_(std::move(selector_names)) + CircuitBuilderBase(size_t size_hint = 0) { variables.reserve(size_hint * 3); variable_names.reserve(size_hint * 3); @@ -71,12 +53,6 @@ template class CircuitBuilderBase { prev_var_index.reserve(size_hint * 3); real_variable_index.reserve(size_hint * 3); real_variable_tags.reserve(size_hint * 3); - // We set selectors type to bool, when we don't actually use them - if constexpr (!std::is_same::value) { - for (auto& p : selectors) { - p.reserve(size_hint); - } - } } CircuitBuilderBase(const CircuitBuilderBase& other) = default; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp index 04c13069c915..2235a9343454 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/circuit_builder/goblin_translator_circuit_builder.hpp @@ -73,12 +73,15 @@ namespace proof_system { * microlimb. * */ -class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase { +class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase { // We don't need templating for Goblin using Fr = barretenberg::fr; using Fq = barretenberg::fq; + using Arithmetization = arithmetization::GoblinTranslator; public: + static constexpr size_t NUM_WIRES = Arithmetization::NUM_WIRES; + /** * We won't need these standard gates that are defined as virtual in circuit builder base * @@ -324,6 +327,8 @@ class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase>, NUM_WIRES> wires; + /** * @brief Construct a new Goblin Translator Circuit Builder object * @@ -334,11 +339,11 @@ class GoblinTranslatorCircuitBuilder : public CircuitBuilderBase void GoblinUltraCircuitBuilder_::finalize_circuit() { - UltraCircuitBuilder_::finalize_circuit(); + UltraCircuitBuilder_>::finalize_circuit(); } /** @@ -22,7 +22,7 @@ template void GoblinUltraCircuitBuilder_::finalize_circuit() // polynomials is zero, which is required for them to be shiftable. template void GoblinUltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_non_zero() { - UltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_non_zero(); + UltraCircuitBuilder_>::add_gates_to_ensure_all_polys_are_non_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 7982af217e54..329baf57e60e 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 @@ -16,12 +16,12 @@ namespace proof_system { using namespace barretenberg; -template class GoblinUltraCircuitBuilder_ : public UltraCircuitBuilder_ { +template class GoblinUltraCircuitBuilder_ : public UltraCircuitBuilder_> { public: static constexpr std::string_view NAME_STRING = "GoblinUltraArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::ULTRA; static constexpr size_t DEFAULT_NON_NATIVE_FIELD_LIMB_BITS = - UltraCircuitBuilder_::DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; + UltraCircuitBuilder_>::DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; size_t num_ecc_op_gates = 0; // number of ecc op "gates" (rows); these are placed at the start of the circuit @@ -56,7 +56,7 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui public: GoblinUltraCircuitBuilder_(const size_t size_hint = 0, std::shared_ptr op_queue_in = std::make_shared()) - : UltraCircuitBuilder_(size_hint) + : UltraCircuitBuilder_>(size_hint) , op_queue(op_queue_in) { // Set indices to constants corresponding to Goblin ECC op codes @@ -86,7 +86,7 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui */ size_t get_num_gates() const override { - auto num_ultra_gates = UltraCircuitBuilder_::get_num_gates(); + auto num_ultra_gates = UltraCircuitBuilder_>::get_num_gates(); return num_ultra_gates + num_ecc_op_gates; } @@ -101,7 +101,8 @@ template class GoblinUltraCircuitBuilder_ : public UltraCircuitBui size_t romcount = 0; size_t ramcount = 0; size_t nnfcount = 0; - UltraCircuitBuilder_::get_num_gates_split_into_components(count, rangecount, romcount, ramcount, nnfcount); + UltraCircuitBuilder_>::get_num_gates_split_into_components( + count, rangecount, romcount, ramcount, nnfcount); size_t total = count + romcount + ramcount + rangecount + num_ecc_op_gates; std::cout << "gates = " << total << " (arith " << count << ", rom " << romcount << ", ram " << ramcount 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 285eed8283cc..c9bcaa65b8f2 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 @@ -518,7 +518,7 @@ template bool StandardCircuitBuilder_::check_circuit() */ template msgpack::sbuffer StandardCircuitBuilder_::export_circuit() { - using base = CircuitBuilderBase>; + using base = CircuitBuilderBase; CircuitSchema cir; uint64_t modulus[4] = { 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 9c97bacd9b0f..015fcb3a143d 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 @@ -8,31 +8,36 @@ #include namespace proof_system { -inline std::vector standard_selector_names() -{ - std::vector result{ "q_m", "q_1", "q_2", "q_3", "q_c" }; - return result; -} -template class StandardCircuitBuilder_ : public CircuitBuilderBase> { +template class StandardCircuitBuilder_ : public CircuitBuilderBase { public: + using Arithmetization = arithmetization::Standard; + 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; + static constexpr size_t num_selectors = Arithmetization::num_selectors; + std::vector selector_names = Arithmetization::selector_names; + static constexpr std::string_view NAME_STRING = "StandardArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::STANDARD; 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 = std::get<0>(this->wires); - WireVector& w_r = std::get<1>(this->wires); - WireVector& w_o = std::get<2>(this->wires); + WireVector& w_l = std::get<0>(wires); + WireVector& w_r = std::get<1>(wires); + WireVector& w_o = std::get<2>(wires); - SelectorVector& q_m = this->selectors.q_m; - SelectorVector& q_1 = this->selectors.q_1; - SelectorVector& q_2 = this->selectors.q_2; - SelectorVector& q_3 = this->selectors.q_3; - SelectorVector& q_c = this->selectors.q_c; + SelectorVector& q_m = this->selectors.q_m(); + SelectorVector& q_1 = this->selectors.q_1(); + SelectorVector& q_2 = this->selectors.q_2(); + SelectorVector& q_3 = this->selectors.q_3(); + SelectorVector& q_c = this->selectors.q_c(); static constexpr size_t UINT_LOG2_BASE = 2; @@ -42,8 +47,9 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase std::map constant_variable_indices; StandardCircuitBuilder_(const size_t size_hint = 0) - : CircuitBuilderBase>(standard_selector_names(), size_hint) + : CircuitBuilderBase(size_hint) { + selectors.reserve(size_hint); w_l.reserve(size_hint); w_r.reserve(size_hint); w_o.reserve(size_hint); @@ -63,8 +69,10 @@ template class StandardCircuitBuilder_ : public CircuitBuilderBase StandardCircuitBuilder_& operator=(const StandardCircuitBuilder_& other) = delete; StandardCircuitBuilder_& operator=(StandardCircuitBuilder_&& other) { - CircuitBuilderBase>::operator=(std::move(other)); + CircuitBuilderBase::operator=(std::move(other)); constant_variable_indices = other.constant_variable_indices; + wires = other.wires; + selectors = other.selectors; 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 e6c83a20fd82..15f06b4e6e5d 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 @@ -14,7 +14,7 @@ using namespace barretenberg; namespace proof_system { -template void UltraCircuitBuilder_::finalize_circuit() +template void UltraCircuitBuilder_::finalize_circuit() { /** * First of all, add the gates related to ROM arrays and range lists. @@ -58,7 +58,8 @@ template void UltraCircuitBuilder_::finalize_circuit() // TODO(#423): This function adds valid (but arbitrary) gates to ensure that the circuit which includes // them will not result in any zero-polynomials. It also ensures that the first coefficient of the wire // polynomials is zero, which is required for them to be shiftable. -template void UltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_non_zero() +template +void UltraCircuitBuilder_::add_gates_to_ensure_all_polys_are_non_zero() { // 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 @@ -117,7 +118,8 @@ template void UltraCircuitBuilder_::add_gates_to_ensure_all_po * * @param in A structure with variable indexes and selector values for the gate. */ -template void UltraCircuitBuilder_::create_add_gate(const add_triple_& in) +template +void UltraCircuitBuilder_::create_add_gate(const add_triple_& in) { this->assert_valid_variables({ in.a, in.b, in.c }); @@ -147,8 +149,9 @@ template void UltraCircuitBuilder_::create_add_gate(const add_ * @param in Structure with variable indexes and wire selector values * @param include_next_gate_w_4 Switches on/off the addition of w_4 at the next index */ -template -void UltraCircuitBuilder_::create_big_add_gate(const add_quad_& in, const bool include_next_gate_w_4) +template +void UltraCircuitBuilder_::create_big_add_gate(const add_quad_& in, + 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); @@ -175,7 +178,8 @@ void UltraCircuitBuilder_::create_big_add_gate(const add_quad_& in, cons * * @param in Structure with variables and witness selector values */ -template void UltraCircuitBuilder_::create_big_add_gate_with_bit_extraction(const add_quad_& in) +template +void UltraCircuitBuilder_::create_big_add_gate_with_bit_extraction(const add_quad_& in) { // This method is an artifact of a turbo plonk feature that implicitly extracts // a high or low bit from a base-4 quad and adds it into the arithmetic gate relationship. @@ -238,7 +242,8 @@ template void UltraCircuitBuilder_::create_big_add_gate_with_b * * @param in Structure containing variables and witness selectors */ -template void UltraCircuitBuilder_::create_big_mul_gate(const mul_quad_& in) +template +void UltraCircuitBuilder_::create_big_mul_gate(const mul_quad_& in) { this->assert_valid_variables({ in.a, in.b, in.c, in.d }); @@ -262,7 +267,8 @@ template void UltraCircuitBuilder_::create_big_mul_gate(const // Creates a width-4 addition gate, where the fourth witness must be a boolean. // Can be used to normalize a 32-bit addition -template void UltraCircuitBuilder_::create_balanced_add_gate(const add_quad_& in) +template +void UltraCircuitBuilder_::create_balanced_add_gate(const add_quad_& in) { this->assert_valid_variables({ in.a, in.b, in.c, in.d }); @@ -302,7 +308,8 @@ template void UltraCircuitBuilder_::create_balanced_add_gate(c * * @param in Structure containing variables and witness selectors */ -template void UltraCircuitBuilder_::create_mul_gate(const mul_triple_& in) +template +void UltraCircuitBuilder_::create_mul_gate(const mul_triple_& in) { this->assert_valid_variables({ in.a, in.b, in.c }); @@ -328,7 +335,8 @@ template void UltraCircuitBuilder_::create_mul_gate(const mul_ * * @param variable_index the variable which needs to be constrained */ -template void UltraCircuitBuilder_::create_bool_gate(const uint32_t variable_index) +template +void UltraCircuitBuilder_::create_bool_gate(const uint32_t variable_index) { this->assert_valid_variables({ variable_index }); @@ -357,7 +365,8 @@ template void UltraCircuitBuilder_::create_bool_gate(const uin * * @param in Structure containing variables and witness selectors */ -template void UltraCircuitBuilder_::create_poly_gate(const poly_triple_& in) +template +void UltraCircuitBuilder_::create_poly_gate(const poly_triple_& in) { this->assert_valid_variables({ in.a, in.b, in.c }); @@ -388,7 +397,8 @@ template void UltraCircuitBuilder_::create_poly_gate(const pol * @param in Elliptic curve point addition gate parameters, including the the affine coordinates of the two points being * added, the resulting point coordinates and the selector values that describe whether the second point is negated. */ -template void UltraCircuitBuilder_::create_ecc_add_gate(const ecc_add_gate_& in) +template +void UltraCircuitBuilder_::create_ecc_add_gate(const ecc_add_gate_& in) { /** * gate structure: @@ -454,7 +464,8 @@ template void UltraCircuitBuilder_::create_ecc_add_gate(const * * @param in Elliptic curve point doubling gate parameters */ -template void UltraCircuitBuilder_::create_ecc_dbl_gate(const ecc_dbl_gate_& in) +template +void UltraCircuitBuilder_::create_ecc_dbl_gate(const ecc_dbl_gate_& in) { /** * gate structure: @@ -517,7 +528,8 @@ template void UltraCircuitBuilder_::create_ecc_dbl_gate(const * @param witness_index The index of the witness we are fixing * @param witness_value The value we are fixing it to */ -template void UltraCircuitBuilder_::fix_witness(const uint32_t witness_index, const FF& witness_value) +template +void UltraCircuitBuilder_::fix_witness(const uint32_t witness_index, const FF& witness_value) { this->assert_valid_variables({ witness_index }); @@ -539,7 +551,8 @@ template void UltraCircuitBuilder_::fix_witness(const uint32_t ++this->num_gates; } -template uint32_t UltraCircuitBuilder_::put_constant_variable(const FF& variable) +template +uint32_t UltraCircuitBuilder_::put_constant_variable(const FF& variable) { if (constant_variable_indices.contains(variable)) { return constant_variable_indices.at(variable); @@ -551,7 +564,8 @@ template uint32_t UltraCircuitBuilder_::put_constant_variable( } } -template plookup::BasicTable& UltraCircuitBuilder_::get_table(const plookup::BasicTableId id) +template +plookup::BasicTable& UltraCircuitBuilder_::get_table(const plookup::BasicTableId id) { for (plookup::BasicTable& table : lookup_tables) { if (table.id == id) { @@ -567,8 +581,8 @@ template plookup::BasicTable& UltraCircuitBuilder_::get_table( * @brief Perform a series of lookups, one for each 'row' in read_values. */ -template -plookup::ReadData UltraCircuitBuilder_::create_gates_from_plookup_accumulators( +template +plookup::ReadData UltraCircuitBuilder_::create_gates_from_plookup_accumulators( const plookup::MultiTableId& id, const plookup::ReadData& read_values, const uint32_t key_a_index, @@ -616,8 +630,9 @@ plookup::ReadData UltraCircuitBuilder_::create_gates_from_plookup_ /** * Generalized Permutation Methods **/ -template -typename UltraCircuitBuilder_::RangeList UltraCircuitBuilder_::create_range_list(const uint64_t target_range) +template +typename UltraCircuitBuilder_::RangeList UltraCircuitBuilder_::create_range_list( + const uint64_t target_range) { RangeList result; const auto range_tag = get_new_tag(); // current_tag + 1; @@ -649,11 +664,9 @@ typename UltraCircuitBuilder_::RangeList UltraCircuitBuilder_::create_ra // range constraint a value by decomposing it into limbs whose size should be the default range constraint size -template -std::vector UltraCircuitBuilder_::decompose_into_default_range(const uint32_t variable_index, - const uint64_t num_bits, - const uint64_t target_range_bitnum, - std::string const& msg) +template +std::vector UltraCircuitBuilder_::decompose_into_default_range( + const uint32_t variable_index, const uint64_t num_bits, const uint64_t target_range_bitnum, std::string const& msg) { this->assert_valid_variables({ variable_index }); @@ -764,10 +777,10 @@ std::vector UltraCircuitBuilder_::decompose_into_default_range(con * @param variable_index * @param target_range */ -template -void UltraCircuitBuilder_::create_new_range_constraint(const uint32_t variable_index, - const uint64_t target_range, - std::string const msg) +template +void UltraCircuitBuilder_::create_new_range_constraint(const uint32_t variable_index, + const uint64_t target_range, + std::string const msg) { if (uint256_t(this->get_variable(variable_index)).data[0] > target_range) { if (!this->failed()) { @@ -818,7 +831,7 @@ void UltraCircuitBuilder_::create_new_range_constraint(const uint32_t variab } } -template void UltraCircuitBuilder_::process_range_list(RangeList& list) +template void UltraCircuitBuilder_::process_range_list(RangeList& list) { this->assert_valid_variables(list.variable_indices); @@ -872,7 +885,7 @@ template void UltraCircuitBuilder_::process_range_list(RangeLi create_sort_constraint_with_edges(indices, 0, list.target_range); } -template void UltraCircuitBuilder_::process_range_lists() +template void UltraCircuitBuilder_::process_range_lists() { for (auto& i : range_lists) { process_range_list(i.second); @@ -892,8 +905,8 @@ template void UltraCircuitBuilder_::process_range_lists() * std::map range_lists; */ // Check for a sequence of variables that neighboring differences are at most 3 (used for batched range checkj) -template -void UltraCircuitBuilder_::create_sort_constraint(const std::vector& variable_index) +template +void UltraCircuitBuilder_::create_sort_constraint(const std::vector& variable_index) { constexpr size_t gate_width = plonk::ultra_settings::program_width; ASSERT(variable_index.size() % gate_width == 0); @@ -939,8 +952,8 @@ void UltraCircuitBuilder_::create_sort_constraint(const std::vector -void UltraCircuitBuilder_::create_dummy_constraints(const std::vector& variable_index) +template +void UltraCircuitBuilder_::create_dummy_constraints(const std::vector& variable_index) { std::vector padded_list = variable_index; constexpr size_t gate_width = plonk::ultra_settings::program_width; @@ -972,10 +985,9 @@ void UltraCircuitBuilder_::create_dummy_constraints(const std::vector -void UltraCircuitBuilder_::create_sort_constraint_with_edges(const std::vector& variable_index, - const FF& start, - const FF& end) +template +void UltraCircuitBuilder_::create_sort_constraint_with_edges( + const std::vector& variable_index, const FF& start, const FF& end) { // Convenient to assume size is at least 8 (gate_width = 4) for separate gates for start and end conditions constexpr size_t gate_width = plonk::ultra_settings::program_width; @@ -1061,8 +1073,8 @@ void UltraCircuitBuilder_::create_sort_constraint_with_edges(const std::vect // range constraint a value by decomposing it into limbs whose size should be the default range constraint size -template -std::vector UltraCircuitBuilder_::decompose_into_default_range_better_for_oddlimbnum( +template +std::vector UltraCircuitBuilder_::decompose_into_default_range_better_for_oddlimbnum( const uint32_t variable_index, const size_t num_bits, std::string const& msg) { std::vector sums; @@ -1156,7 +1168,8 @@ std::vector UltraCircuitBuilder_::decompose_into_default_range_bet * * @param type */ -template void UltraCircuitBuilder_::apply_aux_selectors(const AUX_SELECTORS type) +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); @@ -1316,11 +1329,11 @@ template void UltraCircuitBuilder_::apply_aux_selectors(const * Applies range constraints to two 70-bit limbs, splititng each into 5 14-bit sublimbs. * We can efficiently chain together two 70-bit limb checks in 3 gates, using auxiliary gates **/ -template -void UltraCircuitBuilder_::range_constrain_two_limbs(const uint32_t lo_idx, - const uint32_t hi_idx, - const size_t lo_limb_bits, - const size_t hi_limb_bits) +template +void UltraCircuitBuilder_::range_constrain_two_limbs(const uint32_t lo_idx, + const uint32_t hi_idx, + const size_t lo_limb_bits, + const size_t hi_limb_bits) { // Validate limbs are <= 70 bits. If limbs are larger we require more witnesses and cannot use our limb accumulation // custom gate @@ -1407,8 +1420,8 @@ void UltraCircuitBuilder_::range_constrain_two_limbs(const uint32_t lo_idx, * @return std::array The indices of new limbs. */ -template -std::array UltraCircuitBuilder_::decompose_non_native_field_double_width_limb( +template +std::array UltraCircuitBuilder_::decompose_non_native_field_double_width_limb( const uint32_t limb_idx, const size_t num_limb_bits) { ASSERT(uint256_t(this->get_variable_reference(limb_idx)) < (uint256_t(1) << num_limb_bits)); @@ -1446,8 +1459,8 @@ std::array UltraCircuitBuilder_::decompose_non_native_field_dou * N.B.: This method does NOT evaluate the prime field component of non-native field multiplications. **/ -template -std::array UltraCircuitBuilder_::evaluate_non_native_field_multiplication( +template +std::array UltraCircuitBuilder_::evaluate_non_native_field_multiplication( const non_native_field_witnesses& input, const bool range_constrain_quotient_and_remainder) { @@ -1609,7 +1622,8 @@ std::array UltraCircuitBuilder_::evaluate_non_native_field_mult * Iterates over the cached_non_native_field_multiplication objects, * removes duplicates, and instantiates the remainder as constraints` */ -template void UltraCircuitBuilder_::process_non_native_field_multiplications() +template +void UltraCircuitBuilder_::process_non_native_field_multiplications() { for (size_t i = 0; i < cached_partial_non_native_field_multiplications.size(); ++i) { auto& c = cached_partial_non_native_field_multiplications[i]; @@ -1666,8 +1680,8 @@ template void UltraCircuitBuilder_::process_non_native_field_m * **/ -template -std::array UltraCircuitBuilder_::queue_partial_non_native_field_multiplication( +template +std::array UltraCircuitBuilder_::queue_partial_non_native_field_multiplication( const non_native_field_witnesses& input) { @@ -1713,8 +1727,8 @@ std::array UltraCircuitBuilder_::queue_partial_non_native_field * field elements in 4 gates (would normally take 5) **/ -template -std::array UltraCircuitBuilder_::evaluate_non_native_field_addition( +template +std::array UltraCircuitBuilder_::evaluate_non_native_field_addition( add_simple limb0, add_simple limb1, add_simple limb2, add_simple limb3, std::tuple limbp) { const auto& x_0 = std::get<0>(limb0).first; @@ -1836,8 +1850,8 @@ std::array UltraCircuitBuilder_::evaluate_non_native_field_addi }; } -template -std::array UltraCircuitBuilder_::evaluate_non_native_field_subtraction( +template +std::array UltraCircuitBuilder_::evaluate_non_native_field_subtraction( add_simple limb0, add_simple limb1, add_simple limb2, add_simple limb3, std::tuple limbp) { const auto& x_0 = std::get<0>(limb0).first; @@ -1964,7 +1978,7 @@ std::array UltraCircuitBuilder_::evaluate_non_native_field_subt * * @param record Stores details of this read operation. Mutated by this fn! */ -template void UltraCircuitBuilder_::create_ROM_gate(RomRecord& record) +template void UltraCircuitBuilder_::create_ROM_gate(RomRecord& record) { // Record wire value can't yet be computed record.record_witness = this->add_variable(0); @@ -1984,7 +1998,8 @@ template void UltraCircuitBuilder_::create_ROM_gate(RomRecord& * * @param record Stores details of this read operation. Mutated by this fn! */ -template void UltraCircuitBuilder_::create_sorted_ROM_gate(RomRecord& record) +template +void UltraCircuitBuilder_::create_sorted_ROM_gate(RomRecord& record) { record.record_witness = this->add_variable(0); apply_aux_selectors(AUX_SELECTORS::ROM_CONSISTENCY_CHECK); @@ -2007,7 +2022,8 @@ template void UltraCircuitBuilder_::create_sorted_ROM_gate(Rom * @return size_t The index of the element */ -template size_t UltraCircuitBuilder_::create_ROM_array(const size_t array_size) +template +size_t UltraCircuitBuilder_::create_ROM_array(const size_t array_size) { RomTranscript new_transcript; for (size_t i = 0; i < array_size; ++i) { @@ -2024,7 +2040,7 @@ template size_t UltraCircuitBuilder_::create_ROM_array(const s * * @param record Stores details of this read operation. Mutated by this fn! */ -template void UltraCircuitBuilder_::create_RAM_gate(RamRecord& record) +template void UltraCircuitBuilder_::create_RAM_gate(RamRecord& record) { // Record wire value can't yet be computed (uses randomnes generated during proof construction). // However it needs a distinct witness index, @@ -2049,7 +2065,8 @@ template void UltraCircuitBuilder_::create_RAM_gate(RamRecord& * * @param record Stores details of this read operation. Mutated by this fn! */ -template void UltraCircuitBuilder_::create_sorted_RAM_gate(RamRecord& record) +template +void UltraCircuitBuilder_::create_sorted_RAM_gate(RamRecord& record) { record.record_witness = this->add_variable(0); apply_aux_selectors(AUX_SELECTORS::RAM_CONSISTENCY_CHECK); @@ -2067,8 +2084,8 @@ template void UltraCircuitBuilder_::create_sorted_RAM_gate(Ram * * @param record Stores details of this read operation. Mutated by this fn! */ -template -void UltraCircuitBuilder_::create_final_sorted_RAM_gate(RamRecord& record, const size_t ram_array_size) +template +void UltraCircuitBuilder_::create_final_sorted_RAM_gate(RamRecord& record, const size_t ram_array_size) { record.record_witness = this->add_variable(0); record.gate_index = this->num_gates; @@ -2096,7 +2113,8 @@ void UltraCircuitBuilder_::create_final_sorted_RAM_gate(RamRecord& record, c * @param array_size The size of region in elements * @return size_t The index of the element */ -template size_t UltraCircuitBuilder_::create_RAM_array(const size_t array_size) +template +size_t UltraCircuitBuilder_::create_RAM_array(const size_t array_size) { RamTranscript new_transcript; for (size_t i = 0; i < array_size; ++i) { @@ -2113,10 +2131,10 @@ template size_t UltraCircuitBuilder_::create_RAM_array(const s * @param index_value The index of the cell within the array (an actual index, not a witness index) * @param value_witness The index of the witness with the value that should be in the */ -template -void UltraCircuitBuilder_::init_RAM_element(const size_t ram_id, - const size_t index_value, - const uint32_t value_witness) +template +void UltraCircuitBuilder_::init_RAM_element(const size_t ram_id, + const size_t index_value, + const uint32_t value_witness) { ASSERT(ram_arrays.size() > ram_id); RamTranscript& ram_array = ram_arrays[ram_id]; @@ -2137,8 +2155,8 @@ void UltraCircuitBuilder_::init_RAM_element(const size_t ram_id, ram_array.records.emplace_back(new_record); } -template -uint32_t UltraCircuitBuilder_::read_RAM_array(const size_t ram_id, const uint32_t index_witness) +template +uint32_t UltraCircuitBuilder_::read_RAM_array(const size_t ram_id, const uint32_t index_witness) { ASSERT(ram_arrays.size() > ram_id); RamTranscript& ram_array = ram_arrays[ram_id]; @@ -2166,10 +2184,10 @@ uint32_t UltraCircuitBuilder_::read_RAM_array(const size_t ram_id, const uin return value_witness; } -template -void UltraCircuitBuilder_::write_RAM_array(const size_t ram_id, - const uint32_t index_witness, - const uint32_t value_witness) +template +void UltraCircuitBuilder_::write_RAM_array(const size_t ram_id, + const uint32_t index_witness, + const uint32_t value_witness) { ASSERT(ram_arrays.size() > ram_id); RamTranscript& ram_array = ram_arrays[ram_id]; @@ -2209,10 +2227,10 @@ void UltraCircuitBuilder_::write_RAM_array(const size_t ram_id, * @param index_value The index of the cell within the array (an actual index, not a witness index) * @param value_witness The index of the witness with the value that should be in the */ -template -void UltraCircuitBuilder_::set_ROM_element(const size_t rom_id, - const size_t index_value, - const uint32_t value_witness) +template +void UltraCircuitBuilder_::set_ROM_element(const size_t rom_id, + const size_t index_value, + const uint32_t value_witness) { ASSERT(rom_arrays.size() > rom_id); RomTranscript& rom_array = rom_arrays[rom_id]; @@ -2252,10 +2270,10 @@ void UltraCircuitBuilder_::set_ROM_element(const size_t rom_id, * @param index_value Index in the array * @param value_witnesses The witnesses to put in the slot */ -template -void UltraCircuitBuilder_::set_ROM_element_pair(const size_t rom_id, - const size_t index_value, - const std::array& value_witnesses) +template +void UltraCircuitBuilder_::set_ROM_element_pair(const size_t rom_id, + const size_t index_value, + const std::array& value_witnesses) { ASSERT(rom_arrays.size() > rom_id); RomTranscript& rom_array = rom_arrays[rom_id]; @@ -2283,8 +2301,8 @@ void UltraCircuitBuilder_::set_ROM_element_pair(const size_t rom_id, * @param index_witness The witness with the index inside the array * @return uint32_t Cell value witness index */ -template -uint32_t UltraCircuitBuilder_::read_ROM_array(const size_t rom_id, const uint32_t index_witness) +template +uint32_t UltraCircuitBuilder_::read_ROM_array(const size_t rom_id, const uint32_t index_witness) { ASSERT(rom_arrays.size() > rom_id); RomTranscript& rom_array = rom_arrays[rom_id]; @@ -2316,8 +2334,9 @@ uint32_t UltraCircuitBuilder_::read_ROM_array(const size_t rom_id, const uin * @return std::array A pair of indexes of witness variables of cell values */ -template -std::array UltraCircuitBuilder_::read_ROM_array_pair(const size_t rom_id, const uint32_t index_witness) +template +std::array UltraCircuitBuilder_::read_ROM_array_pair(const size_t rom_id, + const uint32_t index_witness) { std::array value_witnesses; @@ -2352,7 +2371,7 @@ std::array UltraCircuitBuilder_::read_ROM_array_pair(const size * @param rom_id The id of the ROM table * @param gate_offset_from_public_inputs Required to track the gate position of where we're adding extra gates */ -template void UltraCircuitBuilder_::process_ROM_array(const size_t rom_id) +template void UltraCircuitBuilder_::process_ROM_array(const size_t rom_id) { auto& rom_array = rom_arrays[rom_id]; @@ -2438,7 +2457,7 @@ template void UltraCircuitBuilder_::process_ROM_array(const si * @param ram_id The id of the RAM table * @param gate_offset_from_public_inputs Required to track the gate position of where we're adding extra gates */ -template void UltraCircuitBuilder_::process_RAM_array(const size_t ram_id) +template void UltraCircuitBuilder_::process_RAM_array(const size_t ram_id) { RamTranscript& ram_array = ram_arrays[ram_id]; const auto access_tag = get_new_tag(); // current_tag + 1; @@ -2578,13 +2597,13 @@ template void UltraCircuitBuilder_::process_RAM_array(const si } } -template void UltraCircuitBuilder_::process_ROM_arrays() +template void UltraCircuitBuilder_::process_ROM_arrays() { for (size_t i = 0; i < rom_arrays.size(); ++i) { process_ROM_array(i); } } -template void UltraCircuitBuilder_::process_RAM_arrays() +template void UltraCircuitBuilder_::process_RAM_arrays() { for (size_t i = 0; i < ram_arrays.size(); ++i) { process_RAM_array(i); @@ -2658,22 +2677,23 @@ template void UltraCircuitBuilder_::process_RAM_arrays() * @param alpha * @return fr */ -template -inline FF UltraCircuitBuilder_::compute_arithmetic_identity(FF q_arith_value, - FF q_1_value, - FF q_2_value, - FF q_3_value, - FF q_4_value, - FF q_m_value, - FF q_c_value, - FF w_1_value, - FF w_2_value, - FF w_3_value, - FF w_4_value, - FF w_1_shifted_value, - FF w_4_shifted_value, - FF alpha_base, - FF alpha) const +template +inline typename Arithmetization::FF UltraCircuitBuilder_::compute_arithmetic_identity( + FF q_arith_value, + FF q_1_value, + FF q_2_value, + FF q_3_value, + FF q_4_value, + FF q_m_value, + FF q_c_value, + FF w_1_value, + FF w_2_value, + FF w_3_value, + FF w_4_value, + FF w_1_shifted_value, + FF w_4_shifted_value, + FF alpha_base, + FF alpha) const { constexpr FF neg_half = FF(-2).invert(); // The main arithmetic identity that gets activated for q_arith_value == 1 @@ -2723,15 +2743,16 @@ inline FF UltraCircuitBuilder_::compute_arithmetic_identity(FF q_arith_value * @param alpha * @return fr */ -template -inline FF UltraCircuitBuilder_::compute_genperm_sort_identity(FF q_sort_value, - FF w_1_value, - FF w_2_value, - FF w_3_value, - FF w_4_value, - FF w_1_shifted_value, - FF alpha_base, - FF alpha) const +template +inline typename Arithmetization::FF UltraCircuitBuilder_::compute_genperm_sort_identity( + FF q_sort_value, + FF w_1_value, + FF w_2_value, + FF w_3_value, + FF w_4_value, + FF w_1_shifted_value, + FF alpha_base, + FF alpha) const { // Power of alpha to separate individual delta relations // TODO(kesha): This is a repeated computation which can be efficiently optimized @@ -2782,18 +2803,19 @@ inline FF UltraCircuitBuilder_::compute_genperm_sort_identity(FF q_sort_valu * @param w_4_shifted_value y₃ * @return fr */ -template -inline FF UltraCircuitBuilder_::compute_elliptic_identity(FF q_elliptic_value, - FF q_1_value, - FF q_m_value, - FF w_2_value, - FF w_3_value, - FF w_1_shifted_value, - FF w_2_shifted_value, - FF w_3_shifted_value, - FF w_4_shifted_value, - FF alpha_base, - FF alpha) const +template +inline typename Arithmetization::FF UltraCircuitBuilder_::compute_elliptic_identity( + FF q_elliptic_value, + FF q_1_value, + FF q_m_value, + FF w_2_value, + FF w_3_value, + FF w_1_shifted_value, + FF w_2_shifted_value, + FF w_3_shifted_value, + FF w_4_shifted_value, + FF alpha_base, + FF alpha) const { const FF x_1 = w_2_value; const FF y_1 = w_3_value; @@ -2865,26 +2887,27 @@ inline FF UltraCircuitBuilder_::compute_elliptic_identity(FF q_elliptic_valu * */ -template -inline FF UltraCircuitBuilder_::compute_auxilary_identity(FF q_aux_value, - FF q_arith_value, - FF q_1_value, - FF q_2_value, - FF q_3_value, - FF q_4_value, - FF q_m_value, - FF q_c_value, - FF w_1_value, - FF w_2_value, - FF w_3_value, - FF w_4_value, - FF w_1_shifted_value, - FF w_2_shifted_value, - FF w_3_shifted_value, - FF w_4_shifted_value, - FF alpha_base, - FF alpha, - FF eta) const +template +inline typename Arithmetization::FF UltraCircuitBuilder_::compute_auxilary_identity( + FF q_aux_value, + FF q_arith_value, + FF q_1_value, + FF q_2_value, + FF q_3_value, + FF q_4_value, + FF q_m_value, + FF q_c_value, + FF w_1_value, + FF w_2_value, + FF w_3_value, + FF w_4_value, + FF w_1_shifted_value, + FF w_2_shifted_value, + FF w_3_shifted_value, + FF w_4_shifted_value, + FF alpha_base, + FF alpha, + FF eta) const { constexpr FF LIMB_SIZE(uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); // TODO(kesha): Replace with a constant defined in header @@ -3139,7 +3162,7 @@ inline FF UltraCircuitBuilder_::compute_auxilary_identity(FF q_aux_value, * @return true * @return false */ -template bool UltraCircuitBuilder_::check_circuit() +template bool UltraCircuitBuilder_::check_circuit() { bool result = true; CircuitDataBackup circuit_backup = CircuitDataBackup::store_prefinilized_state(this); @@ -3399,7 +3422,7 @@ template bool UltraCircuitBuilder_::check_circuit() circuit_backup.restore_prefinilized_state(this); return result; } -template class UltraCircuitBuilder_; +template class UltraCircuitBuilder_>; // To enable this we need to template plookup // 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 9c3f25ee6090..0d3c5241eeab 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 @@ -3,7 +3,6 @@ #include "barretenberg/plonk/proof_system/types/polynomial_manifest.hpp" #include "barretenberg/plonk/proof_system/types/prover_settings.hpp" #include "barretenberg/polynomials/polynomial.hpp" -#include "barretenberg/proof_system/arithmetization/arithmetization.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" @@ -16,8 +15,16 @@ namespace proof_system { using namespace barretenberg; -template class UltraCircuitBuilder_ : public CircuitBuilderBase> { +template +class UltraCircuitBuilder_ : public CircuitBuilderBase { public: + using FF = typename Arithmetization::FF; + 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; + static constexpr size_t num_selectors = Arithmetization::num_selectors; + std::vector selector_names = Arithmetization::selector_names; + static constexpr std::string_view NAME_STRING = "UltraArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::ULTRA; static constexpr merkle::HashType merkle_hash_type = merkle::HashType::LOOKUP_PEDERSEN; @@ -212,12 +219,6 @@ template class UltraCircuitBuilder_ : public CircuitBuilderBase ultra_selector_names() - { - std::vector result{ "q_m", "q_c", "q_1", "q_2", "q_3", "q_4", - "q_arith", "q_sort", "q_elliptic", "q_aux", "table_type" }; - return result; - } struct non_native_field_multiplication_cross_terms { uint32_t lo_0_idx; uint32_t lo_1_idx; @@ -526,25 +527,28 @@ template class UltraCircuitBuilder_ : public CircuitBuilderBase>, NUM_WIRES> wires; + Arithmetization selectors; + using WireVector = std::vector>; using SelectorVector = std::vector>; - WireVector& w_l = std::get<0>(this->wires); - WireVector& w_r = std::get<1>(this->wires); - WireVector& w_o = std::get<2>(this->wires); - WireVector& w_4 = std::get<3>(this->wires); - - SelectorVector& q_m = this->selectors.q_m; - SelectorVector& q_c = this->selectors.q_c; - SelectorVector& q_1 = this->selectors.q_1; - SelectorVector& q_2 = this->selectors.q_2; - SelectorVector& q_3 = this->selectors.q_3; - SelectorVector& q_4 = this->selectors.q_4; - SelectorVector& q_arith = this->selectors.q_arith; - SelectorVector& q_sort = this->selectors.q_sort; - SelectorVector& q_elliptic = this->selectors.q_elliptic; - SelectorVector& q_aux = this->selectors.q_aux; - SelectorVector& q_lookup_type = this->selectors.q_lookup_type; + WireVector& w_l = std::get<0>(wires); + WireVector& w_r = std::get<1>(wires); + WireVector& w_o = std::get<2>(wires); + WireVector& w_4 = std::get<3>(wires); + + SelectorVector& q_m = selectors.q_m(); + SelectorVector& q_c = selectors.q_c(); + SelectorVector& q_1 = selectors.q_1(); + SelectorVector& q_2 = selectors.q_2(); + SelectorVector& q_3 = selectors.q_3(); + SelectorVector& q_4 = selectors.q_4(); + SelectorVector& q_arith = selectors.q_arith(); + SelectorVector& q_sort = selectors.q_sort(); + SelectorVector& q_elliptic = selectors.q_elliptic(); + SelectorVector& q_aux = selectors.q_aux(); + SelectorVector& q_lookup_type = selectors.q_lookup_type(); // These are variables that we have used a gate on, to enforce that they are // equal to a defined value. @@ -583,8 +587,9 @@ template class UltraCircuitBuilder_ : public CircuitBuilderBase>(ultra_selector_names(), size_hint) + : CircuitBuilderBase(size_hint) { + selectors.reserve(size_hint); w_l.reserve(size_hint); w_r.reserve(size_hint); w_o.reserve(size_hint); @@ -594,8 +599,10 @@ template class UltraCircuitBuilder_ : public CircuitBuilderBase>(std::move(other)) + : CircuitBuilderBase(std::move(other)) { + wires = other.wires; + selectors = other.selectors; constant_variable_indices = other.constant_variable_indices; lookup_tables = other.lookup_tables; @@ -611,7 +618,9 @@ template class UltraCircuitBuilder_ : public CircuitBuilderBase>::operator=(std::move(other)); + CircuitBuilderBase::operator=(std::move(other)); + wires = other.wires; + selectors = other.selectors; constant_variable_indices = other.constant_variable_indices; lookup_tables = other.lookup_tables; @@ -723,7 +732,6 @@ template class UltraCircuitBuilder_ : public CircuitBuilderBase>::program_width; // each RAM gate adds +2 extra gates due to the ram reads being copied to a sorted list set, // as well as an extra gate to validate timestamps std::vector ram_timestamps; @@ -744,12 +752,12 @@ template class UltraCircuitBuilder_ : public CircuitBuilderBase class UltraCircuitBuilder_ : public CircuitBuilderBase class UltraCircuitBuilder_ : public CircuitBuilderBase class UltraCircuitBuilder_ : public CircuitBuilderBase; -using UltraCircuitBuilder = UltraCircuitBuilder_; -} // namespace proof_system +extern template class UltraCircuitBuilder_>; +using UltraCircuitBuilder = UltraCircuitBuilder_>; +} // namespace proof_system \ No newline at end of file diff --git a/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.hpp b/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.hpp index 8f7db1a3327d..c1bcc1fe7543 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/composer/composer_lib.hpp @@ -39,7 +39,7 @@ void construct_selector_polynomials(const typename Flavor::CircuitBuilder& circu // TODO(#398): Loose coupling here! Would rather build up pk from arithmetization size_t selector_idx = 0; // TODO(https://github.com/AztecProtocol/barretenberg/issues/391) zip - for (auto& selector_values : circuit_constructor.selectors) { + for (auto& selector_values : circuit_constructor.selectors.get()) { ASSERT(proving_key->circuit_size >= selector_values.size()); // Copy the selector values for all gates, keeping the rows at which we store public inputs as 0. @@ -53,7 +53,7 @@ void construct_selector_polynomials(const typename Flavor::CircuitBuilder& circu proving_key->_precomputed_polynomials[selector_idx] = selector_poly_lagrange; } else if constexpr (IsPlonkFlavor) { // TODO(Cody): Loose coupling here of selector_names and selector_properties. - proving_key->polynomial_store.put(circuit_constructor.selector_names_[selector_idx] + "_lagrange", + proving_key->polynomial_store.put(circuit_constructor.selector_names[selector_idx] + "_lagrange", std::move(selector_poly_lagrange)); } ++selector_idx; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp b/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp index 01bc6a21a106..5b46b4c25d5c 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp @@ -21,12 +21,16 @@ class Bn254FrParams; class Bn254FqParams; template struct alignas(32) field; } // namespace barretenberg +namespace arithmetization { +template class Ultra; +} // namespace arithmetization namespace proof_system { template class StandardCircuitBuilder_; using StandardCircuitBuilder = StandardCircuitBuilder_>; using StandardGrumpkinCircuitBuilder = StandardCircuitBuilder_>; -template class UltraCircuitBuilder_; -using UltraCircuitBuilder = UltraCircuitBuilder_>; +template class UltraCircuitBuilder_; +using UltraCircuitBuilder = + UltraCircuitBuilder_>>; template class GoblinUltraCircuitBuilder_; using GoblinUltraCircuitBuilder = GoblinUltraCircuitBuilder_>; } // namespace proof_system