diff --git a/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp b/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp index ed8d3424ef..84688be1a6 100644 --- a/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp +++ b/cpp/src/barretenberg/ecc/curves/bn254/bn254.hpp @@ -1,5 +1,6 @@ #pragma once #include "../bn254/fq.hpp" +#include "../bn254/fq12.hpp" #include "../bn254/fq2.hpp" #include "../bn254/fr.hpp" #include "../bn254/g1.hpp" @@ -15,5 +16,6 @@ class BN254 { using AffineElement = typename Group::affine_element; using G2AffineElement = typename barretenberg::g2::affine_element; using G2BaseField = typename barretenberg::fq2; + using TargetField = barretenberg::fq12; }; } // namespace curve \ No newline at end of file diff --git a/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp b/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp index fc7f4e16ca..ed1dcfcc27 100644 --- a/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp +++ b/cpp/src/barretenberg/proof_system/arithmetization/arithmetization.hpp @@ -48,8 +48,9 @@ template struct SelectorsBase { // 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 Arithmetization { 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); @@ -79,8 +80,9 @@ template class Standard : public Arithmetization class Turbo : public Arithmetization { +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); @@ -122,8 +124,9 @@ template class Turbo : public Arithmetization class Ultra : public Arithmetization { +template class Ultra : 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); diff --git a/cpp/src/barretenberg/proof_system/arithmetization/gate_data.hpp b/cpp/src/barretenberg/proof_system/arithmetization/gate_data.hpp index a054c3b792..f47a033838 100644 --- a/cpp/src/barretenberg/proof_system/arithmetization/gate_data.hpp +++ b/cpp/src/barretenberg/proof_system/arithmetization/gate_data.hpp @@ -3,64 +3,73 @@ #include "barretenberg/ecc/curves/bn254/fr.hpp" #include +// TODO(#557): The field-specific aliases for gates should be removed and the type could be explicit when this +// structures are used to avoid having foo_gate and foo_gate_grumpkin (i.e. use foo_gate instead). Moreover, we +// need to ensure the read/write functions handle grumpkin gates as well. namespace proof_system { -struct add_triple { +template struct add_triple_ { uint32_t a; uint32_t b; uint32_t c; - barretenberg::fr a_scaling; - barretenberg::fr b_scaling; - barretenberg::fr c_scaling; - barretenberg::fr const_scaling; + FF a_scaling; + FF b_scaling; + FF c_scaling; + FF const_scaling; }; +using add_triple = add_triple_; -struct add_quad { +template struct add_quad_ { uint32_t a; uint32_t b; uint32_t c; uint32_t d; - barretenberg::fr a_scaling; - barretenberg::fr b_scaling; - barretenberg::fr c_scaling; - barretenberg::fr d_scaling; - barretenberg::fr const_scaling; + FF a_scaling; + FF b_scaling; + FF c_scaling; + FF d_scaling; + FF const_scaling; }; +using add_quad = add_quad_; -struct mul_quad { +template struct mul_quad_ { uint32_t a; uint32_t b; uint32_t c; uint32_t d; - barretenberg::fr mul_scaling; - barretenberg::fr a_scaling; - barretenberg::fr b_scaling; - barretenberg::fr c_scaling; - barretenberg::fr d_scaling; - barretenberg::fr const_scaling; + FF mul_scaling; + FF a_scaling; + FF b_scaling; + FF c_scaling; + FF d_scaling; + FF const_scaling; }; +using mul_quad = mul_quad_; -struct mul_triple { +template struct mul_triple_ { uint32_t a; uint32_t b; uint32_t c; - barretenberg::fr mul_scaling; - barretenberg::fr c_scaling; - barretenberg::fr const_scaling; + FF mul_scaling; + FF c_scaling; + FF const_scaling; }; +using mul_triple = mul_triple_; -struct poly_triple { +template struct poly_triple_ { uint32_t a; uint32_t b; uint32_t c; - barretenberg::fr q_m; - barretenberg::fr q_l; - barretenberg::fr q_r; - barretenberg::fr q_o; - barretenberg::fr q_c; + FF q_m; + FF q_l; + FF q_r; + FF q_o; + FF q_c; - friend bool operator==(poly_triple const& lhs, poly_triple const& rhs) = default; + friend bool operator==(poly_triple_ const& lhs, poly_triple_ const& rhs) = default; }; +using poly_triple = poly_triple_; + template inline void read(B& buf, poly_triple& constraint) { using serialize::read; @@ -73,7 +82,6 @@ template inline void read(B& buf, poly_triple& constraint) read(buf, constraint.q_o); read(buf, constraint.q_c); } - template inline void write(B& buf, poly_triple const& constraint) { using serialize::write; @@ -87,38 +95,42 @@ template inline void write(B& buf, poly_triple const& constraint) write(buf, constraint.q_c); } -struct fixed_group_add_quad { +template struct fixed_group_add_quad_ { uint32_t a; uint32_t b; uint32_t c; uint32_t d; - barretenberg::fr q_x_1; - barretenberg::fr q_x_2; - barretenberg::fr q_y_1; - barretenberg::fr q_y_2; + FF q_x_1; + FF q_x_2; + FF q_y_1; + FF q_y_2; }; +using fixed_group_add_quad = fixed_group_add_quad_; -struct fixed_group_init_quad { - barretenberg::fr q_x_1; - barretenberg::fr q_x_2; - barretenberg::fr q_y_1; - barretenberg::fr q_y_2; +template struct fixed_group_init_quad_ { + FF q_x_1; + FF q_x_2; + FF q_y_1; + FF q_y_2; }; +using fixed_group_init_quad = fixed_group_init_quad_; -struct accumulator_triple { +template struct accumulator_triple_ { std::vector left; std::vector right; std::vector out; }; +using accumulator_triple = accumulator_triple_; -struct ecc_add_gate { +template struct ecc_add_gate_ { uint32_t x1; uint32_t y1; uint32_t x2; uint32_t y2; uint32_t x3; uint32_t y3; - barretenberg::fr endomorphism_coefficient; - barretenberg::fr sign_coefficient; + FF endomorphism_coefficient; + FF sign_coefficient; }; +using ecc_add_gate = ecc_add_gate_; } // namespace proof_system diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp b/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp index 76b1513033..1cce2aabb7 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.cpp @@ -1,4 +1,6 @@ #include "circuit_builder_base.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" namespace proof_system { @@ -42,6 +44,7 @@ void CircuitBuilderBase::assert_equal(const uint32_t a_variable } // Standard honk/ plonk instantiation template class CircuitBuilderBase>; -template class CircuitBuilderBase>; +template class CircuitBuilderBase>; template class CircuitBuilderBase>; +template class CircuitBuilderBase>; } // namespace proof_system diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp b/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp index 4d98845767..b0b591da58 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/circuit_builder_base.hpp @@ -10,9 +10,7 @@ static constexpr uint32_t DUMMY_TAG = 0; template class CircuitBuilderBase { public: - // TODO(Cody): This needs to be templated to allow constructing circuits over Grumpkin. For now, adding FF here - // since the flavor can extract it. - using FF = barretenberg::fr; + 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; @@ -27,7 +25,7 @@ template class CircuitBuilderBase { typename Arithmetization::Selectors selectors; std::vector public_inputs; - std::vector variables; + 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) @@ -81,10 +79,10 @@ template class CircuitBuilderBase { uint32_t zero_idx = 0; uint32_t one_idx = 1; - virtual void create_add_gate(const add_triple& in) = 0; - virtual void create_mul_gate(const mul_triple& in) = 0; + virtual void create_add_gate(const add_triple_& in) = 0; + virtual void create_mul_gate(const mul_triple_& in) = 0; virtual void create_bool_gate(const uint32_t a) = 0; - virtual void create_poly_gate(const poly_triple& in) = 0; + virtual void create_poly_gate(const poly_triple_& in) = 0; virtual size_t get_num_constant_gates() const = 0; /** @@ -123,7 +121,7 @@ template class CircuitBuilderBase { * @param index The index of the variable. * @return The value of the variable. * */ - inline barretenberg::fr get_variable(const uint32_t index) const + inline FF get_variable(const uint32_t index) const { ASSERT(variables.size() > index); return variables[real_variable_index[index]]; @@ -137,7 +135,7 @@ template class CircuitBuilderBase { * @param index The index of the variable. * @return The value of the variable. * */ - inline const barretenberg::fr& get_variable_reference(const uint32_t index) const + inline const FF& get_variable_reference(const uint32_t index) const { ASSERT(variables.size() > index); return variables[real_variable_index[index]]; @@ -156,11 +154,11 @@ template class CircuitBuilderBase { return result; } - barretenberg::fr get_public_input(const uint32_t index) const { return get_variable(public_inputs[index]); } + FF get_public_input(const uint32_t index) const { return get_variable(public_inputs[index]); } - std::vector get_public_inputs() const + std::vector get_public_inputs() const { - std::vector result; + std::vector result; for (uint32_t i = 0; i < get_num_public_inputs(); ++i) { result.push_back(get_public_input(i)); } @@ -173,7 +171,7 @@ template class CircuitBuilderBase { * @param in The value of the variable * @return The index of the new variable in the variables vector */ - virtual uint32_t add_variable(const barretenberg::fr& in) + virtual uint32_t add_variable(const FF& in) { variables.emplace_back(in); @@ -195,7 +193,7 @@ template class CircuitBuilderBase { * @param in The value of the variable * @return The index of the new variable in the variables vector */ - virtual uint32_t add_public_variable(const barretenberg::fr& in) + virtual uint32_t add_public_variable(const FF& in) { const uint32_t index = add_variable(in); public_inputs.emplace_back(index); diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp b/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp index 0f312f3d8f..025699f521 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.cpp @@ -1,4 +1,6 @@ #include "standard_circuit_builder.hpp" +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.hpp" #include #include @@ -12,20 +14,20 @@ namespace proof_system { * @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. */ -void StandardCircuitBuilder::create_add_gate(const add_triple& in) +template void StandardCircuitBuilder_::create_add_gate(const add_triple_& in) { - assert_valid_variables({ in.a, in.b, in.c }); + 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(fr::zero()); + 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); - ++num_gates; + ++this->num_gates; } /** @@ -35,18 +37,18 @@ void StandardCircuitBuilder::create_add_gate(const add_triple& in) * @param in An add quad containing the indexes of variables a, b, c, d and * the scaling factors. * */ -void StandardCircuitBuilder::create_big_add_gate(const add_quad& in) +template void StandardCircuitBuilder_::create_big_add_gate(const add_quad_& in) { // (a terms + b terms = temp) // (c terms + d terms + temp = 0 ) - fr t0 = get_variable(in.a) * in.a_scaling; - fr t1 = get_variable(in.b) * in.b_scaling; - fr temp = t0 + t1; - uint32_t temp_idx = add_variable(temp); + FF t0 = this->get_variable(in.a) * in.a_scaling; + FF t1 = this->get_variable(in.b) * in.b_scaling; + FF temp = t0 + t1; + uint32_t temp_idx = this->add_variable(temp); - create_add_gate(add_triple{ in.a, in.b, temp_idx, in.a_scaling, in.b_scaling, fr::neg_one(), fr::zero() }); + create_add_gate({ in.a, in.b, temp_idx, in.a_scaling, in.b_scaling, FF::neg_one(), FF::zero() }); - create_add_gate(add_triple{ in.c, in.d, temp_idx, in.c_scaling, in.d_scaling, fr::one(), in.const_scaling }); + create_add_gate({ in.c, in.d, temp_idx, in.c_scaling, in.d_scaling, FF::one(), in.const_scaling }); } /** @@ -56,69 +58,69 @@ void StandardCircuitBuilder::create_big_add_gate(const add_quad& in) * @param in An add quad containing the indexes of variables a, b, c, d and * the scaling factors. * */ -void StandardCircuitBuilder::create_balanced_add_gate(const add_quad& in) +template void StandardCircuitBuilder_::create_balanced_add_gate(const add_quad_& in) { - - assert_valid_variables({ in.a, in.b, in.c, in.d }); + this->assert_valid_variables({ in.a, in.b, in.c, in.d }); // (a terms + b terms = temp) // (c terms + d terms + temp = 0 ) - fr t0 = get_variable(in.a) * in.a_scaling; - fr t1 = get_variable(in.b) * in.b_scaling; - fr temp = t0 + t1; - uint32_t temp_idx = add_variable(temp); + FF t0 = this->get_variable(in.a) * in.a_scaling; + FF t1 = this->get_variable(in.b) * in.b_scaling; + 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(fr::zero()); + q_m.emplace_back(FF::zero()); q_1.emplace_back(in.a_scaling); q_2.emplace_back(in.b_scaling); - q_3.emplace_back(fr::neg_one()); - q_c.emplace_back(fr::zero()); + q_3.emplace_back(FF::neg_one()); + q_c.emplace_back(FF::zero()); - ++num_gates; + ++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(fr::zero()); - q_1.emplace_back(fr::one()); + 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); - ++num_gates; + ++this->num_gates; // in.d must be between 0 and 3 // i.e. in.d * (in.d - 1) * (in.d - 2) = 0 - fr temp_2 = get_variable(in.d).sqr() - get_variable(in.d); - uint32_t temp_2_idx = add_variable(temp_2); + 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(fr::one()); - q_1.emplace_back(fr::neg_one()); - q_2.emplace_back(fr::zero()); - q_3.emplace_back(fr::neg_one()); - q_c.emplace_back(fr::zero()); + 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()); - ++num_gates; + ++this->num_gates; - constexpr fr neg_two = -fr(2); + constexpr FF neg_two = -FF(2); w_l.emplace_back(temp_2_idx); w_r.emplace_back(in.d); - w_o.emplace_back(zero_idx); - q_m.emplace_back(fr::one()); + w_o.emplace_back(this->zero_idx); + q_m.emplace_back(FF::one()); q_1.emplace_back(neg_two); - q_2.emplace_back(fr::zero()); - q_3.emplace_back(fr::zero()); - q_c.emplace_back(fr::zero()); + q_2.emplace_back(FF::zero()); + q_3.emplace_back(FF::zero()); + q_c.emplace_back(FF::zero()); - ++num_gates; + ++this->num_gates; } -void StandardCircuitBuilder::create_big_add_gate_with_bit_extraction(const add_quad& in) +template +void StandardCircuitBuilder_::create_big_add_gate_with_bit_extraction(const add_quad_& in) { // blah. // delta = (c - 4d) @@ -126,51 +128,50 @@ void StandardCircuitBuilder::create_big_add_gate_with_bit_extraction(const add_q // r = (-2*delta*delta + 9*delta - 7)*delta // r = - fr delta = get_variable(in.d); + FF delta = this->get_variable(in.d); delta += delta; delta += delta; - delta = get_variable(in.c) - delta; - - uint32_t delta_idx = add_variable(delta); - constexpr fr neg_four = -(fr(4)); - create_add_gate(add_triple{ in.c, in.d, delta_idx, fr::one(), neg_four, fr::neg_one(), fr::zero() }); - - constexpr fr two = fr(2); - constexpr fr seven = fr(7); - constexpr fr nine = fr(9); - const fr r_0 = (delta * nine) - ((delta.sqr() * two) + seven); - uint32_t r_0_idx = add_variable(r_0); - create_poly_gate(poly_triple{ delta_idx, delta_idx, r_0_idx, -two, nine, fr::zero(), fr::neg_one(), -seven }); - - fr r_1 = r_0 * delta; - uint32_t r_1_idx = add_variable(r_1); - create_mul_gate(mul_triple{ + delta = this->get_variable(in.c) - delta; + + uint32_t delta_idx = this->add_variable(delta); + constexpr FF neg_four = -(FF(4)); + create_add_gate({ in.c, in.d, delta_idx, FF::one(), neg_four, FF::neg_one(), FF::zero() }); + + constexpr FF two = FF(2); + constexpr FF seven = FF(7); + constexpr FF nine = FF(9); + const FF r_0 = (delta * nine) - ((delta.sqr() * two) + seven); + uint32_t r_0_idx = this->add_variable(r_0); + create_poly_gate({ delta_idx, delta_idx, r_0_idx, -two, nine, FF::zero(), FF::neg_one(), -seven }); + + FF r_1 = r_0 * delta; + uint32_t r_1_idx = this->add_variable(r_1); + create_mul_gate(mul_triple_{ r_0_idx, delta_idx, r_1_idx, - fr::one(), - fr::neg_one(), - fr::zero(), + FF::one(), + FF::neg_one(), + FF::zero(), }); // ain.a1 + bin.b2 + cin.c3 + din.c4 + r_1 = 0 - fr r_2 = (r_1 + (get_variable(in.d) * in.d_scaling)); - uint32_t r_2_idx = add_variable(r_2); - create_add_gate(add_triple{ in.d, r_1_idx, r_2_idx, in.d_scaling, fr::one(), fr::neg_one(), fr::zero() }); + FF r_2 = (r_1 + (this->get_variable(in.d) * in.d_scaling)); + uint32_t r_2_idx = this->add_variable(r_2); + create_add_gate({ in.d, r_1_idx, r_2_idx, in.d_scaling, FF::one(), FF::neg_one(), FF::zero() }); - create_big_add_gate( - add_quad{ in.a, in.b, in.c, r_2_idx, in.a_scaling, in.b_scaling, in.c_scaling, fr::one(), in.const_scaling }); + create_big_add_gate(add_quad_{ + in.a, in.b, in.c, r_2_idx, in.a_scaling, in.b_scaling, in.c_scaling, FF::one(), in.const_scaling }); } -void StandardCircuitBuilder::create_big_mul_gate(const mul_quad& in) +template void StandardCircuitBuilder_::create_big_mul_gate(const mul_quad_& in) { - fr temp = ((get_variable(in.c) * in.c_scaling) + (get_variable(in.d) * in.d_scaling)); - uint32_t temp_idx = add_variable(temp); - create_add_gate(add_triple{ in.c, in.d, temp_idx, in.c_scaling, in.d_scaling, fr::neg_one(), fr::zero() }); + FF temp = ((this->get_variable(in.c) * in.c_scaling) + (this->get_variable(in.d) * in.d_scaling)); + uint32_t temp_idx = this->add_variable(temp); + create_add_gate({ in.c, in.d, temp_idx, in.c_scaling, in.d_scaling, FF::neg_one(), FF::zero() }); - create_poly_gate( - poly_triple{ in.a, in.b, temp_idx, in.mul_scaling, in.a_scaling, in.b_scaling, fr::one(), in.const_scaling }); + create_poly_gate({ in.a, in.b, temp_idx, in.mul_scaling, in.a_scaling, in.b_scaling, FF::one(), in.const_scaling }); } /** @@ -179,20 +180,20 @@ void StandardCircuitBuilder::create_big_mul_gate(const mul_quad& in) * @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. */ -void StandardCircuitBuilder::create_mul_gate(const mul_triple& in) +template void StandardCircuitBuilder_::create_mul_gate(const mul_triple_& in) { - assert_valid_variables({ in.a, in.b, in.c }); + 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(fr::zero()); - q_2.emplace_back(fr::zero()); + 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); - ++num_gates; + ++this->num_gates; } /** @@ -201,21 +202,21 @@ void StandardCircuitBuilder::create_mul_gate(const mul_triple& in) * * @param variable_index The index of the variable. */ -void StandardCircuitBuilder::create_bool_gate(const uint32_t variable_index) +template void StandardCircuitBuilder_::create_bool_gate(const uint32_t variable_index) { - assert_valid_variables({ variable_index }); + 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(fr::one()); - q_1.emplace_back(fr::zero()); - q_2.emplace_back(fr::zero()); - q_3.emplace_back(fr::neg_one()); - q_c.emplace_back(fr::zero()); + 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()); - ++num_gates; + ++this->num_gates; } /** @@ -223,9 +224,9 @@ void StandardCircuitBuilder::create_bool_gate(const uint32_t variable_index) * * @param in A poly_triple containing all the information. */ -void StandardCircuitBuilder::create_poly_gate(const poly_triple& in) +template void StandardCircuitBuilder_::create_poly_gate(const poly_triple_& in) { - assert_valid_variables({ in.a, in.b, in.c }); + this->assert_valid_variables({ in.a, in.b, in.c }); w_l.emplace_back(in.a); w_r.emplace_back(in.b); @@ -236,15 +237,16 @@ void StandardCircuitBuilder::create_poly_gate(const poly_triple& in) q_3.emplace_back(in.q_o); q_c.emplace_back(in.q_c); - ++num_gates; + ++this->num_gates; } -std::vector StandardCircuitBuilder::decompose_into_base4_accumulators(const uint32_t witness_index, - const size_t num_bits, - std::string const& msg) +template +std::vector StandardCircuitBuilder_::decompose_into_base4_accumulators(const uint32_t witness_index, + const size_t num_bits, + std::string const& msg) { ASSERT(num_bits > 0); - const uint256_t target(get_variable(witness_index)); + const uint256_t target(this->get_variable(witness_index)); std::vector accumulators; @@ -253,13 +255,13 @@ std::vector StandardCircuitBuilder::decompose_into_base4_accumulators( const auto is_edge_case = [&num_quads, &num_bits](size_t idx) { return (idx == num_quads - 1 && ((num_bits & 1ULL) == 1ULL)); }; - constexpr fr four = fr{ 4, 0, 0, 0 }.to_montgomery_form(); - fr accumulator = fr::zero(); + constexpr FF four = FF{ 4, 0, 0, 0 }.to_montgomery_form(); + FF accumulator = FF::zero(); uint32_t accumulator_idx = 0; for (size_t i = num_quads - 1; i < num_quads; --i) { bool lo = target.get_bit(2 * i); - uint32_t lo_idx = add_variable(lo ? fr::one() : fr::zero()); + uint32_t lo_idx = this->add_variable(lo ? FF::one() : FF::zero()); create_bool_gate(lo_idx); uint32_t quad_idx; @@ -268,74 +270,74 @@ std::vector StandardCircuitBuilder::decompose_into_base4_accumulators( quad_idx = lo_idx; } else { bool hi = target.get_bit(2 * i + 1); - uint32_t hi_idx = add_variable(hi ? fr::one() : fr::zero()); + uint32_t hi_idx = this->add_variable(hi ? FF::one() : FF::zero()); create_bool_gate(hi_idx); uint64_t quad = (lo ? 1U : 0U) + (hi ? 2U : 0U); - quad_idx = add_variable(fr{ quad, 0, 0, 0 }.to_montgomery_form()); + quad_idx = this->add_variable(FF{ quad, 0, 0, 0 }.to_montgomery_form()); - create_add_gate( - add_triple{ lo_idx, hi_idx, quad_idx, fr::one(), fr::one() + fr::one(), fr::neg_one(), fr::zero() }); + create_add_gate({ lo_idx, hi_idx, quad_idx, FF::one(), FF::one() + FF::one(), FF::neg_one(), FF::zero() }); } if (i == num_quads - 1) { accumulators.push_back(quad_idx); - accumulator = get_variable(quad_idx); + accumulator = this->get_variable(quad_idx); accumulator_idx = quad_idx; } else { - fr new_accumulator = accumulator + accumulator; + FF new_accumulator = accumulator + accumulator; new_accumulator = new_accumulator + new_accumulator; - new_accumulator = new_accumulator + get_variable(quad_idx); - uint32_t new_accumulator_idx = add_variable(new_accumulator); - create_add_gate(add_triple{ - accumulator_idx, quad_idx, new_accumulator_idx, four, fr::one(), fr::neg_one(), fr::zero() }); + new_accumulator = new_accumulator + this->get_variable(quad_idx); + uint32_t new_accumulator_idx = this->add_variable(new_accumulator); + create_add_gate( + { accumulator_idx, quad_idx, new_accumulator_idx, four, FF::one(), FF::neg_one(), FF::zero() }); accumulators.push_back(new_accumulator_idx); accumulator = new_accumulator; accumulator_idx = new_accumulator_idx; } } - assert_equal(witness_index, accumulator_idx, msg); + this->assert_equal(witness_index, accumulator_idx, msg); return accumulators; } -accumulator_triple StandardCircuitBuilder::create_logic_constraint(const uint32_t a, - const uint32_t b, - const size_t num_bits, - const bool is_xor_gate) +template +accumulator_triple StandardCircuitBuilder_::create_logic_constraint(const uint32_t a, + const uint32_t b, + const size_t num_bits, + const bool is_xor_gate) { - assert_valid_variables({ a, b }); + this->assert_valid_variables({ a, b }); accumulator_triple accumulators; - const uint256_t left_witness_value(get_variable(a)); - const uint256_t right_witness_value(get_variable(b)); + const uint256_t left_witness_value(this->get_variable(a)); + const uint256_t right_witness_value(this->get_variable(b)); - fr left_accumulator = fr::zero(); - fr right_accumulator = fr::zero(); - fr out_accumulator = fr::zero(); + FF left_accumulator = FF::zero(); + FF right_accumulator = FF::zero(); + FF out_accumulator = FF::zero(); - uint32_t left_accumulator_idx = zero_idx; - uint32_t right_accumulator_idx = zero_idx; - uint32_t out_accumulator_idx = zero_idx; - constexpr fr four = fr(4); - constexpr fr neg_two = -fr(2); + uint32_t left_accumulator_idx = this->zero_idx; + uint32_t right_accumulator_idx = this->zero_idx; + uint32_t out_accumulator_idx = this->zero_idx; + constexpr FF four = FF(4); + constexpr FF neg_two = -FF(2); for (size_t i = num_bits - 1; i < num_bits; i -= 2) { bool left_hi_val = left_witness_value.get_bit(i); bool left_lo_val = left_witness_value.get_bit(i - 1); bool right_hi_val = right_witness_value.get_bit((i)); bool right_lo_val = right_witness_value.get_bit(i - 1); - uint32_t left_hi_idx = add_variable(left_hi_val ? fr::one() : fr::zero()); - uint32_t left_lo_idx = add_variable(left_lo_val ? fr::one() : fr::zero()); - uint32_t right_hi_idx = add_variable(right_hi_val ? fr::one() : fr::zero()); - uint32_t right_lo_idx = add_variable(right_lo_val ? fr::one() : fr::zero()); + uint32_t left_hi_idx = this->add_variable(left_hi_val ? FF::one() : FF::zero()); + uint32_t left_lo_idx = this->add_variable(left_lo_val ? FF::one() : FF::zero()); + uint32_t right_hi_idx = this->add_variable(right_hi_val ? FF::one() : FF::zero()); + uint32_t right_lo_idx = this->add_variable(right_lo_val ? FF::one() : FF::zero()); bool out_hi_val = is_xor_gate ? left_hi_val ^ right_hi_val : left_hi_val & right_hi_val; bool out_lo_val = is_xor_gate ? left_lo_val ^ right_lo_val : left_lo_val & right_lo_val; - uint32_t out_hi_idx = add_variable(out_hi_val ? fr::one() : fr::zero()); - uint32_t out_lo_idx = add_variable(out_lo_val ? fr::one() : fr::zero()); + uint32_t out_hi_idx = this->add_variable(out_hi_val ? FF::one() : FF::zero()); + uint32_t out_lo_idx = this->add_variable(out_lo_val ? FF::one() : FF::zero()); create_bool_gate(left_hi_idx); create_bool_gate(right_hi_idx); @@ -347,65 +349,67 @@ accumulator_triple StandardCircuitBuilder::create_logic_constraint(const uint32_ // a & b = ab // a ^ b = a + b - 2ab - create_poly_gate(poly_triple{ left_hi_idx, - right_hi_idx, - out_hi_idx, - is_xor_gate ? neg_two : fr::one(), - is_xor_gate ? fr::one() : fr::zero(), - is_xor_gate ? fr::one() : fr::zero(), - fr::neg_one(), - fr::zero() }); - - create_poly_gate(poly_triple{ left_lo_idx, - right_lo_idx, - out_lo_idx, - is_xor_gate ? neg_two : fr::one(), - is_xor_gate ? fr::one() : fr::zero(), - is_xor_gate ? fr::one() : fr::zero(), - fr::neg_one(), - fr::zero() }); - - fr left_quad = get_variable(left_lo_idx) + get_variable(left_hi_idx) + get_variable(left_hi_idx); - fr right_quad = get_variable(right_lo_idx) + get_variable(right_hi_idx) + get_variable(right_hi_idx); - fr out_quad = get_variable(out_lo_idx) + get_variable(out_hi_idx) + get_variable(out_hi_idx); - - uint32_t left_quad_idx = add_variable(left_quad); - uint32_t right_quad_idx = add_variable(right_quad); - uint32_t out_quad_idx = add_variable(out_quad); - - fr new_left_accumulator = left_accumulator + left_accumulator; + create_poly_gate({ left_hi_idx, + right_hi_idx, + out_hi_idx, + is_xor_gate ? neg_two : FF::one(), + is_xor_gate ? FF::one() : FF::zero(), + is_xor_gate ? FF::one() : FF::zero(), + FF::neg_one(), + FF::zero() }); + + create_poly_gate({ left_lo_idx, + right_lo_idx, + out_lo_idx, + is_xor_gate ? neg_two : FF::one(), + is_xor_gate ? FF::one() : FF::zero(), + is_xor_gate ? FF::one() : FF::zero(), + FF::neg_one(), + FF::zero() }); + + FF left_quad = + this->get_variable(left_lo_idx) + this->get_variable(left_hi_idx) + this->get_variable(left_hi_idx); + FF right_quad = + this->get_variable(right_lo_idx) + this->get_variable(right_hi_idx) + this->get_variable(right_hi_idx); + FF out_quad = this->get_variable(out_lo_idx) + this->get_variable(out_hi_idx) + this->get_variable(out_hi_idx); + + uint32_t left_quad_idx = this->add_variable(left_quad); + uint32_t right_quad_idx = this->add_variable(right_quad); + uint32_t out_quad_idx = this->add_variable(out_quad); + + FF new_left_accumulator = left_accumulator + left_accumulator; new_left_accumulator = new_left_accumulator + new_left_accumulator; new_left_accumulator = new_left_accumulator + left_quad; - uint32_t new_left_accumulator_idx = add_variable(new_left_accumulator); + uint32_t new_left_accumulator_idx = this->add_variable(new_left_accumulator); - create_add_gate(add_triple{ left_accumulator_idx, - left_quad_idx, - new_left_accumulator_idx, - four, - fr::one(), - fr::neg_one(), - fr::zero() }); + create_add_gate({ left_accumulator_idx, + left_quad_idx, + new_left_accumulator_idx, + four, + FF::one(), + FF::neg_one(), + FF::zero() }); - fr new_right_accumulator = right_accumulator + right_accumulator; + FF new_right_accumulator = right_accumulator + right_accumulator; new_right_accumulator = new_right_accumulator + new_right_accumulator; new_right_accumulator = new_right_accumulator + right_quad; - uint32_t new_right_accumulator_idx = add_variable(new_right_accumulator); + uint32_t new_right_accumulator_idx = this->add_variable(new_right_accumulator); - create_add_gate(add_triple{ right_accumulator_idx, - right_quad_idx, - new_right_accumulator_idx, - four, - fr::one(), - fr::neg_one(), - fr::zero() }); + create_add_gate({ right_accumulator_idx, + right_quad_idx, + new_right_accumulator_idx, + four, + FF::one(), + FF::neg_one(), + FF::zero() }); - fr new_out_accumulator = out_accumulator + out_accumulator; + FF new_out_accumulator = out_accumulator + out_accumulator; new_out_accumulator = new_out_accumulator + new_out_accumulator; new_out_accumulator = new_out_accumulator + out_quad; - uint32_t new_out_accumulator_idx = add_variable(new_out_accumulator); + uint32_t new_out_accumulator_idx = this->add_variable(new_out_accumulator); - create_add_gate(add_triple{ - out_accumulator_idx, out_quad_idx, new_out_accumulator_idx, four, fr::one(), fr::neg_one(), fr::zero() }); + create_add_gate( + { out_accumulator_idx, out_quad_idx, new_out_accumulator_idx, four, FF::one(), FF::neg_one(), FF::zero() }); accumulators.left.emplace_back(new_left_accumulator_idx); accumulators.right.emplace_back(new_right_accumulator_idx); @@ -423,55 +427,59 @@ accumulator_triple StandardCircuitBuilder::create_logic_constraint(const uint32_ return accumulators; } -void StandardCircuitBuilder::fix_witness(const uint32_t witness_index, const barretenberg::fr& witness_value) +template +void StandardCircuitBuilder_::fix_witness(const uint32_t witness_index, const FF& witness_value) { - assert_valid_variables({ witness_index }); + this->assert_valid_variables({ witness_index }); w_l.emplace_back(witness_index); - w_r.emplace_back(zero_idx); - w_o.emplace_back(zero_idx); - q_m.emplace_back(fr::zero()); - q_1.emplace_back(fr::one()); - q_2.emplace_back(fr::zero()); - q_3.emplace_back(fr::zero()); + 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); - ++num_gates; + ++this->num_gates; } -uint32_t StandardCircuitBuilder::put_constant_variable(const barretenberg::fr& variable) +template uint32_t StandardCircuitBuilder_::put_constant_variable(const FF& variable) { if (constant_variable_indices.contains(variable)) { return constant_variable_indices.at(variable); } else { - uint32_t variable_index = add_variable(variable); + uint32_t variable_index = this->add_variable(variable); fix_witness(variable_index, variable); constant_variable_indices.insert({ variable, variable_index }); return variable_index; } } -accumulator_triple StandardCircuitBuilder::create_and_constraint(const uint32_t a, - const uint32_t b, - const size_t num_bits) +template +accumulator_triple StandardCircuitBuilder_::create_and_constraint(const uint32_t a, + const uint32_t b, + const size_t num_bits) { return create_logic_constraint(a, b, num_bits, false); } -accumulator_triple StandardCircuitBuilder::create_xor_constraint(const uint32_t a, - const uint32_t b, - const size_t num_bits) +template +accumulator_triple StandardCircuitBuilder_::create_xor_constraint(const uint32_t a, + const uint32_t b, + const size_t num_bits) { return create_logic_constraint(a, b, num_bits, true); } -void StandardCircuitBuilder::assert_equal_constant(uint32_t const a_idx, fr const& b, std::string const& msg) +template +void StandardCircuitBuilder_::assert_equal_constant(uint32_t const a_idx, FF const& b, std::string const& msg) { - if (variables[a_idx] != b && !failed()) { - failure(msg); + if (this->variables[a_idx] != b && !this->failed()) { + this->failure(msg); } auto b_idx = put_constant_variable(b); - assert_equal(a_idx, b_idx, msg); + this->assert_equal(a_idx, b_idx, msg); } /** @@ -480,20 +488,22 @@ void StandardCircuitBuilder::assert_equal_constant(uint32_t const a_idx, fr cons * * @return true if the circuit is correct. * */ -bool StandardCircuitBuilder::check_circuit() +template bool StandardCircuitBuilder_::check_circuit() { - fr gate_sum; - fr left, right, output; - for (size_t i = 0; i < num_gates; i++) { - gate_sum = fr::zero(); - left = get_variable(w_l[i]); - right = get_variable(w_r[i]); - output = get_variable(w_o[i]); + FF gate_sum; + FF left, right, output; + 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]; if (!gate_sum.is_zero()) return false; } return true; } +template class StandardCircuitBuilder_; +template class StandardCircuitBuilder_; } // namespace proof_system \ No newline at end of file diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp b/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp index ac93ea41ad..a30bf488e1 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.hpp @@ -1,4 +1,6 @@ #pragma once +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/ecc/curves/grumpkin/grumpkin.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 +14,7 @@ inline std::vector standard_selector_names() return result; } -class StandardCircuitBuilder : public CircuitBuilderBase> { +template class StandardCircuitBuilder_ : public CircuitBuilderBase> { public: static constexpr std::string_view NAME_STRING = "StandardArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::STANDARD; @@ -20,27 +22,27 @@ class StandardCircuitBuilder : public CircuitBuilderBase>; - using SelectorVector = std::vector>; + using SelectorVector = std::vector>; - WireVector& w_l = std::get<0>(wires); - WireVector& w_r = std::get<1>(wires); - WireVector& w_o = std::get<2>(wires); + WireVector& w_l = std::get<0>(this->wires); + WireVector& w_r = std::get<1>(this->wires); + WireVector& w_o = std::get<2>(this->wires); - SelectorVector& q_m = selectors.q_m; - SelectorVector& q_1 = selectors.q_1; - SelectorVector& q_2 = selectors.q_2; - SelectorVector& q_3 = selectors.q_3; - SelectorVector& q_c = 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; // These are variables that we have used a gate on, to enforce that they are // equal to a defined value. // TODO(#216)(Adrian): Why is this not in CircuitBuilderBase - std::map constant_variable_indices; + std::map constant_variable_indices; - StandardCircuitBuilder(const size_t size_hint = 0) - : CircuitBuilderBase(standard_selector_names(), size_hint) + StandardCircuitBuilder_(const size_t size_hint = 0) + : CircuitBuilderBase>(standard_selector_names(), size_hint) { w_l.reserve(size_hint); w_r.reserve(size_hint); @@ -49,44 +51,43 @@ class StandardCircuitBuilder : public CircuitBuilderBasezero_idx = put_constant_variable(FF::zero()); // TODO(#217)(Cody): Ensure that no polynomial is ever zero. Maybe there's a better way. - one_idx = put_constant_variable(barretenberg::fr::one()); + this->one_idx = put_constant_variable(FF::one()); // 1 * 1 * 1 + 1 * 1 + 1 * 1 + 1 * 1 + -4 // m l r o c - create_poly_gate({ one_idx, one_idx, one_idx, 1, 1, 1, 1, -4 }); + create_poly_gate({ this->one_idx, this->one_idx, this->one_idx, 1, 1, 1, 1, -4 }); }; - StandardCircuitBuilder(const StandardCircuitBuilder& other) = delete; - StandardCircuitBuilder(StandardCircuitBuilder&& other) = default; - StandardCircuitBuilder& operator=(const StandardCircuitBuilder& other) = delete; - StandardCircuitBuilder& operator=(StandardCircuitBuilder&& other) + StandardCircuitBuilder_(const StandardCircuitBuilder_& other) = delete; + StandardCircuitBuilder_(StandardCircuitBuilder_&& other) = default; + 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; return *this; }; - ~StandardCircuitBuilder() override = default; + ~StandardCircuitBuilder_() override = default; - void assert_equal_constant(uint32_t const a_idx, - barretenberg::fr const& b, - std::string const& msg = "assert equal constant"); + void assert_equal_constant(uint32_t const a_idx, FF const& b, std::string const& msg = "assert equal constant"); - void create_add_gate(const add_triple& in) override; - void create_mul_gate(const mul_triple& in) override; + void create_add_gate(const add_triple_& in) override; + void create_mul_gate(const mul_triple_& in) override; void create_bool_gate(const uint32_t a) override; - void create_poly_gate(const poly_triple& in) override; - void create_big_add_gate(const add_quad& in); - void create_big_add_gate_with_bit_extraction(const add_quad& in); - void create_big_mul_gate(const mul_quad& in); - void create_balanced_add_gate(const add_quad& in); - void create_fixed_group_add_gate(const fixed_group_add_quad& in); - void create_fixed_group_add_gate_with_init(const fixed_group_add_quad& in, const fixed_group_init_quad& init); - void create_fixed_group_add_gate_final(const add_quad& in); + void create_poly_gate(const poly_triple_& in) override; + void create_big_add_gate(const add_quad_& in); + void create_big_add_gate_with_bit_extraction(const add_quad_& in); + void create_big_mul_gate(const mul_quad_& in); + void create_balanced_add_gate(const add_quad_& in); + void create_fixed_group_add_gate(const fixed_group_add_quad_& in); + void create_fixed_group_add_gate_with_init(const fixed_group_add_quad_& in, + const fixed_group_init_quad_& init); + void create_fixed_group_add_gate_final(const add_quad_& in); fixed_group_add_quad previous_add_quad; // TODO(#216)(Adrian): This should be a virtual overridable method in the base class. - void fix_witness(const uint32_t witness_index, const barretenberg::fr& witness_value); + void fix_witness(const uint32_t witness_index, const FF& witness_value); std::vector decompose_into_base4_accumulators(const uint32_t witness_index, const size_t num_bits, @@ -107,10 +108,15 @@ class StandardCircuitBuilder : public CircuitBuilderBase; +extern template class StandardCircuitBuilder_; +using StandardCircuitBuilder = StandardCircuitBuilder_; +using StandardGrumpkinCircuitBuilder = StandardCircuitBuilder_; } // namespace proof_system diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.test.cpp b/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.test.cpp index 9c9833bdf2..c263b13f8b 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.test.cpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/standard_circuit_builder.test.cpp @@ -22,6 +22,16 @@ TEST(standard_circuit_constructor, base_case) EXPECT_EQ(result, true); } +TEST(standard_circuit_constructor, grumpkin_base_case) +{ + StandardGrumpkinCircuitBuilder composer = StandardGrumpkinCircuitBuilder(); + grumpkin::fr a = grumpkin::fr::one(); + composer.add_public_variable(a); + + bool result = composer.check_circuit(); + EXPECT_EQ(result, true); +} + TEST(standard_circuit_constructor, test_add_gate) { StandardCircuitBuilder circuit_constructor = StandardCircuitBuilder(); diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.cpp b/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.cpp index 1b24f36a0a..3bfb16c48c 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.cpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.cpp @@ -12,15 +12,16 @@ namespace proof_system { * @param size_hint Assumed number of gates. Used to allocate space for various member * vectors during initialization. * */ -TurboCircuitBuilder::TurboCircuitBuilder(const size_t size_hint) - : CircuitBuilderBase(turbo_selector_names(), size_hint) +template +TurboCircuitBuilder_::TurboCircuitBuilder_(const size_t size_hint) + : CircuitBuilderBase>(turbo_selector_names(), size_hint) { w_l.reserve(size_hint); w_r.reserve(size_hint); w_o.reserve(size_hint); w_4.reserve(size_hint); - zero_idx = put_constant_variable(fr::zero()); + this->zero_idx = put_constant_variable(FF::zero()); } /** @@ -32,26 +33,26 @@ TurboCircuitBuilder::TurboCircuitBuilder(const size_t size_hint) * @param in Specifies addition gate parameters: * w_l, w_r, w_o, q_1, q_2, q_3, q_c. * */ -void TurboCircuitBuilder::create_add_gate(const add_triple& in) +template void TurboCircuitBuilder_::create_add_gate(const add_triple& in) { - assert_valid_variables({ in.a, in.b, in.c }); + 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(zero_idx); - q_m.emplace_back(fr::zero()); + w_4.emplace_back(this->zero_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(in.c_scaling); q_c.emplace_back(in.const_scaling); - q_arith.emplace_back(fr::one()); - q_4.emplace_back(fr::zero()); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - ++num_gates; + q_arith.emplace_back(FF::one()); + q_4.emplace_back(FF::zero()); + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); + ++this->num_gates; } /** @@ -63,26 +64,26 @@ void TurboCircuitBuilder::create_add_gate(const add_triple& in) * @param in Specifies addition gate parameters: * w_l, w_r, w_o, w_4, q_1, q_2, q_3, q_4, q_c. * */ -void TurboCircuitBuilder::create_big_add_gate(const add_quad& in) +template void TurboCircuitBuilder_::create_big_add_gate(const add_quad& in) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + 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(fr::zero()); + 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); - q_arith.emplace_back(fr::one()); + q_arith.emplace_back(FF::one()); q_4.emplace_back(in.d_scaling); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - ++num_gates; + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); + ++this->num_gates; } /** @@ -101,31 +102,31 @@ void TurboCircuitBuilder::create_big_add_gate(const add_quad& in) * ensure this assumption is backed by a constraint (e.g., c and d could be accumulators produced using the TurboPLONK * function `decompose_into_base4_accumulators`). * */ -void TurboCircuitBuilder::create_big_add_gate_with_bit_extraction(const add_quad& in) +template void TurboCircuitBuilder_::create_big_add_gate_with_bit_extraction(const add_quad& in) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + 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(fr::zero()); + 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); - q_arith.emplace_back(fr::one() + fr::one()); + q_arith.emplace_back(FF::one() + FF::one()); q_4.emplace_back(in.d_scaling); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - ++num_gates; + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); + ++this->num_gates; } -void TurboCircuitBuilder::create_big_mul_gate(const mul_quad& in) +template void TurboCircuitBuilder_::create_big_mul_gate(const mul_quad& in) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + this->assert_valid_variables({ in.a, in.b, in.c, in.d }); w_l.emplace_back(in.a); w_r.emplace_back(in.b); @@ -136,13 +137,13 @@ void TurboCircuitBuilder::create_big_mul_gate(const mul_quad& in) 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(fr::one()); + q_arith.emplace_back(FF::one()); q_4.emplace_back(in.d_scaling); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - ++num_gates; + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); + ++this->num_gates; } /** @@ -162,26 +163,26 @@ void TurboCircuitBuilder::create_big_mul_gate(const mul_quad& in) * @warning Even with the constraint on w_3, it is typically necessary to range constrain the wire value that will be * returned. */ -void TurboCircuitBuilder::create_balanced_add_gate(const add_quad& in) +template void TurboCircuitBuilder_::create_balanced_add_gate(const add_quad& in) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + 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(fr::zero()); + 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); - q_arith.emplace_back(fr::one()); + q_arith.emplace_back(FF::one()); q_4.emplace_back(in.d_scaling); - q_5.emplace_back(fr::one()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - ++num_gates; + q_5.emplace_back(FF::one()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); + ++this->num_gates; } /** @@ -193,26 +194,26 @@ void TurboCircuitBuilder::create_balanced_add_gate(const add_quad& in) * @param in Contains the values for w_l, w_r, w_o, * q_m, q_3, q_c. * */ -void TurboCircuitBuilder::create_mul_gate(const mul_triple& in) +template void TurboCircuitBuilder_::create_mul_gate(const mul_triple& in) { - assert_valid_variables({ in.a, in.b, in.c }); + 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(zero_idx); + w_4.emplace_back(this->zero_idx); q_m.emplace_back(in.mul_scaling); - q_1.emplace_back(fr::zero()); - q_2.emplace_back(fr::zero()); + 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); - q_arith.emplace_back(fr::one()); - q_4.emplace_back(fr::zero()); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - ++num_gates; + q_arith.emplace_back(FF::one()); + q_4.emplace_back(FF::zero()); + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); + ++this->num_gates; } /** @@ -222,27 +223,27 @@ void TurboCircuitBuilder::create_mul_gate(const mul_triple& in) * * @param variable_index The index of the variable. * */ -void TurboCircuitBuilder::create_bool_gate(const uint32_t variable_index) +template void TurboCircuitBuilder_::create_bool_gate(const uint32_t variable_index) { - assert_valid_variables({ variable_index }); + this->assert_valid_variables({ variable_index }); w_l.emplace_back(variable_index); w_r.emplace_back(variable_index); w_o.emplace_back(variable_index); - w_4.emplace_back(zero_idx); - q_arith.emplace_back(fr::one()); - q_4.emplace_back(fr::zero()); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - - q_m.emplace_back(fr::one()); - q_1.emplace_back(fr::zero()); - q_2.emplace_back(fr::zero()); - q_3.emplace_back(fr::neg_one()); - q_c.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - ++num_gates; + w_4.emplace_back(this->zero_idx); + q_arith.emplace_back(FF::one()); + q_4.emplace_back(FF::zero()); + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + + 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()); + q_logic.emplace_back(FF::zero()); + ++this->num_gates; } /** @@ -254,27 +255,27 @@ void TurboCircuitBuilder::create_bool_gate(const uint32_t variable_index) * @param in Contains the values for * w_l, w_r, w_o, q_m, q_1, q_2, q_3, q_c. * */ -void TurboCircuitBuilder::create_poly_gate(const poly_triple& in) +template void TurboCircuitBuilder_::create_poly_gate(const poly_triple& in) { - assert_valid_variables({ in.a, in.b, in.c }); + 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(zero_idx); + 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_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - - q_arith.emplace_back(fr::one()); - q_4.emplace_back(fr::zero()); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - ++num_gates; + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); + + q_arith.emplace_back(FF::one()); + q_4.emplace_back(FF::zero()); + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + ++this->num_gates; } /** @@ -282,28 +283,28 @@ void TurboCircuitBuilder::create_poly_gate(const poly_triple& in) * * @param in Witnesses and values of two points. * */ -void TurboCircuitBuilder::create_fixed_group_add_gate(const fixed_group_add_quad& in) +template void TurboCircuitBuilder_::create_fixed_group_add_gate(const fixed_group_add_quad& in) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + 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_arith.emplace_back(fr::zero()); - q_4.emplace_back(fr::zero()); - q_5.emplace_back(fr::zero()); - q_m.emplace_back(fr::zero()); - q_c.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); + q_arith.emplace_back(FF::zero()); + q_4.emplace_back(FF::zero()); + q_5.emplace_back(FF::zero()); + q_m.emplace_back(FF::zero()); + q_c.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); q_1.emplace_back(in.q_x_1); q_2.emplace_back(in.q_x_2); q_3.emplace_back(in.q_y_1); q_fixed_base.emplace_back(in.q_y_2); - ++num_gates; + ++this->num_gates; } /** @@ -312,32 +313,33 @@ void TurboCircuitBuilder::create_fixed_group_add_gate(const fixed_group_add_quad * @param in Addition parameters (points and coefficients). * @param init Initialization parameters (points). * */ -void TurboCircuitBuilder::create_fixed_group_add_gate_with_init(const fixed_group_add_quad& in, - const fixed_group_init_quad& init) +template +void TurboCircuitBuilder_::create_fixed_group_add_gate_with_init(const fixed_group_add_quad& in, + const fixed_group_init_quad& init) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + 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_arith.emplace_back(fr::zero()); + q_arith.emplace_back(FF::zero()); q_4.emplace_back(init.q_x_1); q_5.emplace_back(init.q_x_2); q_m.emplace_back(init.q_y_1); q_c.emplace_back(init.q_y_2); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); q_1.emplace_back(in.q_x_1); q_2.emplace_back(in.q_x_2); q_3.emplace_back(in.q_y_1); q_fixed_base.emplace_back(in.q_y_2); - ++num_gates; + ++this->num_gates; } -void TurboCircuitBuilder::create_fixed_group_add_gate_final(const add_quad& in) +template void TurboCircuitBuilder_::create_fixed_group_add_gate_final(const add_quad& in) { create_big_add_gate(in); } @@ -348,26 +350,26 @@ void TurboCircuitBuilder::create_fixed_group_add_gate_final(const add_quad& in) * @param witness_index Witness variable index. * @param witness_value Witness variable value. * */ -void TurboCircuitBuilder::fix_witness(const uint32_t witness_index, const barretenberg::fr& witness_value) +template void TurboCircuitBuilder_::fix_witness(const uint32_t witness_index, const FF& witness_value) { - assert_valid_variables({ witness_index }); + this->assert_valid_variables({ witness_index }); w_l.emplace_back(witness_index); - w_r.emplace_back(zero_idx); - w_o.emplace_back(zero_idx); - w_4.emplace_back(zero_idx); - q_m.emplace_back(fr::zero()); - q_1.emplace_back(fr::one()); - q_2.emplace_back(fr::zero()); - q_3.emplace_back(fr::zero()); + 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(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); - q_arith.emplace_back(fr::one()); - q_4.emplace_back(fr::zero()); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); - q_logic.emplace_back(fr::zero()); - ++num_gates; + q_arith.emplace_back(FF::one()); + q_4.emplace_back(FF::zero()); + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); + q_logic.emplace_back(FF::zero()); + ++this->num_gates; } /** @@ -379,11 +381,12 @@ void TurboCircuitBuilder::fix_witness(const uint32_t witness_index, const barret * @return Vector of variable indexes for accumulator variables used in * the constraint. * */ -std::vector TurboCircuitBuilder::decompose_into_base4_accumulators(const uint32_t witness_index, - const size_t num_bits, - std::string const& msg) +template +std::vector TurboCircuitBuilder_::decompose_into_base4_accumulators(const uint32_t witness_index, + const size_t num_bits, + std::string const& msg) { - assert_valid_variables({ witness_index }); + this->assert_valid_variables({ witness_index }); ASSERT(num_bits > 0); @@ -461,10 +464,10 @@ std::vector TurboCircuitBuilder::decompose_into_base4_accumulators(con * **/ - const uint256_t witness_value(get_variable(witness_index)); + const uint256_t witness_value(this->get_variable(witness_index)); - if (witness_value.get_msb() >= num_bits && !failed()) { - failure(msg); + if (witness_value.get_msb() >= num_bits && !this->failed()) { + this->failure(msg); } /* num_quad_gates is the minimum number of gates needed to record num_bits-many bits in a table, putting two-bits (a * quad) at each position. Since our table has width 4, we can fit 8 bits on a row, hence num_quad_gates is @@ -483,25 +486,25 @@ std::vector TurboCircuitBuilder::decompose_into_base4_accumulators(con const size_t forced_zero_threshold = 1 + (((num_quads << 1) - num_bits) >> 1); std::vector accumulators; - fr accumulator(0); + FF accumulator(0); uint32_t most_significant_segment = 0; // iterate through entries of all but final row for (size_t i = 0; i < num_quads + 1; ++i) { uint32_t accumulator_index; // prepend padding 0 quads if (i < forced_zero_threshold) { - accumulator_index = zero_idx; + accumulator_index = this->zero_idx; } else { // accumulate quad const size_t bit_index = (num_quads - i) << 1; const uint64_t quad = static_cast(witness_value.get_bit(bit_index)) + 2ULL * static_cast(witness_value.get_bit(bit_index + 1)); - const fr quad_element = fr{ quad, 0, 0, 0 }.to_montgomery_form(); + const FF quad_element = fr{ quad, 0, 0, 0 }.to_montgomery_form(); accumulator += accumulator; accumulator += accumulator; accumulator += quad_element; - accumulator_index = add_variable(accumulator); + accumulator_index = this->add_variable(accumulator); accumulators.emplace_back(accumulator_index); if (i == forced_zero_threshold) { @@ -531,15 +534,15 @@ std::vector TurboCircuitBuilder::decompose_into_base4_accumulators(con // switch off range widget for final row; fill wire values not in use with zeros q_range[q_range.size() - 1] = 0; - w_l.emplace_back(zero_idx); - w_r.emplace_back(zero_idx); - w_o.emplace_back(zero_idx); + w_l.emplace_back(this->zero_idx); + w_r.emplace_back(this->zero_idx); + w_o.emplace_back(this->zero_idx); - assert_equal(witness_index, accumulators[accumulators.size() - 1], msg); + this->assert_equal(witness_index, accumulators[accumulators.size() - 1], msg); accumulators[accumulators.size() - 1] = witness_index; - num_gates += used_gates; + this->num_gates += used_gates; // constrain top bit of top quad to zero in case num_bits is odd if ((num_bits & 1ULL) == 1ULL) { @@ -559,12 +562,13 @@ std::vector TurboCircuitBuilder::decompose_into_base4_accumulators(con * for u = T.left[T.left.size()-2], u will be too small to express a in the form a = 4u + quad. * The same holds, mutatis mutandis, for T.right. */ -accumulator_triple TurboCircuitBuilder::create_logic_constraint(const uint32_t a, - const uint32_t b, - const size_t num_bits, - const bool is_xor_gate) +template +accumulator_triple TurboCircuitBuilder_::create_logic_constraint(const uint32_t a, + const uint32_t b, + const size_t num_bits, + const bool is_xor_gate) { - assert_valid_variables({ a, b }); + this->assert_valid_variables({ a, b }); ASSERT(((num_bits >> 1U) << 1U) == num_bits); // Do not allow constraint for an odd number of bits. @@ -640,18 +644,18 @@ accumulator_triple TurboCircuitBuilder::create_logic_constraint(const uint32_t a * addition and logic operations. **/ - const uint256_t left_witness_value(get_variable(a)); - const uint256_t right_witness_value(get_variable(b)); + const uint256_t left_witness_value(this->get_variable(a)); + const uint256_t right_witness_value(this->get_variable(b)); accumulator_triple accumulators; - fr left_accumulator = fr::zero(); - fr right_accumulator = fr::zero(); - fr out_accumulator = fr::zero(); + FF left_accumulator = FF::zero(); + FF right_accumulator = FF::zero(); + FF out_accumulator = FF::zero(); // Step 1: populate 1st row accumulators with zero - w_l.emplace_back(zero_idx); - w_r.emplace_back(zero_idx); - w_4.emplace_back(zero_idx); + w_l.emplace_back(this->zero_idx); + w_r.emplace_back(this->zero_idx); + w_4.emplace_back(this->zero_idx); // w_l, w_r, w_4 now point to 1 gate ahead of w_o for (size_t j = 0; j < num_quads; ++j) { @@ -667,16 +671,16 @@ accumulator_triple TurboCircuitBuilder::create_logic_constraint(const uint32_t a const uint64_t right_quad = static_cast(right_witness_value.get_bit(bit_index)) + 2ULL * static_cast(right_witness_value.get_bit(bit_index + 1)); - const fr left_quad_element = fr{ left_quad, 0, 0, 0 }.to_montgomery_form(); - const fr right_quad_element = fr{ right_quad, 0, 0, 0 }.to_montgomery_form(); - fr out_quad_element; + const FF left_quad_element = fr{ left_quad, 0, 0, 0 }.to_montgomery_form(); + const FF right_quad_element = fr{ right_quad, 0, 0, 0 }.to_montgomery_form(); + FF out_quad_element; if (is_xor_gate) { out_quad_element = fr{ left_quad ^ right_quad, 0, 0, 0 }.to_montgomery_form(); } else { out_quad_element = fr{ left_quad & right_quad, 0, 0, 0 }.to_montgomery_form(); } - const fr product_quad_element = fr{ left_quad * right_quad, 0, 0, 0 }.to_montgomery_form(); + const FF product_quad_element = fr{ left_quad * right_quad, 0, 0, 0 }.to_montgomery_form(); // replace accumulator by 4.accumulator + quad for a, b and c left_accumulator += left_accumulator; @@ -691,75 +695,83 @@ accumulator_triple TurboCircuitBuilder::create_logic_constraint(const uint32_t a out_accumulator += out_accumulator; out_accumulator += out_quad_element; - left_accumulator_index = add_variable(left_accumulator); + left_accumulator_index = this->add_variable(left_accumulator); accumulators.left.emplace_back(left_accumulator_index); - right_accumulator_index = add_variable(right_accumulator); + right_accumulator_index = this->add_variable(right_accumulator); accumulators.right.emplace_back(right_accumulator_index); - out_accumulator_index = add_variable(out_accumulator); + out_accumulator_index = this->add_variable(out_accumulator); accumulators.out.emplace_back(out_accumulator_index); - product_index = add_variable(product_quad_element); + product_index = this->add_variable(product_quad_element); w_l.emplace_back(left_accumulator_index); w_r.emplace_back(right_accumulator_index); w_4.emplace_back(out_accumulator_index); w_o.emplace_back(product_index); } - w_o.emplace_back(zero_idx); + w_o.emplace_back(this->zero_idx); for (size_t i = 0; i < num_quads + 1; ++i) { - q_m.emplace_back(fr::zero()); - q_1.emplace_back(fr::zero()); - q_2.emplace_back(fr::zero()); - q_3.emplace_back(fr::zero()); - q_arith.emplace_back(fr::zero()); - q_4.emplace_back(fr::zero()); - q_5.emplace_back(fr::zero()); - q_fixed_base.emplace_back(fr::zero()); - q_range.emplace_back(fr::zero()); + q_m.emplace_back(FF::zero()); + q_1.emplace_back(FF::zero()); + q_2.emplace_back(FF::zero()); + q_3.emplace_back(FF::zero()); + q_arith.emplace_back(FF::zero()); + q_4.emplace_back(FF::zero()); + q_5.emplace_back(FF::zero()); + q_fixed_base.emplace_back(FF::zero()); + q_range.emplace_back(FF::zero()); if (is_xor_gate) { - q_c.emplace_back(fr::neg_one()); - q_logic.emplace_back(fr::neg_one()); + q_c.emplace_back(FF::neg_one()); + q_logic.emplace_back(FF::neg_one()); } else { - q_c.emplace_back(fr::one()); - q_logic.emplace_back(fr::one()); + q_c.emplace_back(FF::one()); + q_logic.emplace_back(FF::one()); } } - q_c[q_c.size() - 1] = fr::zero(); // last gate is a noop - q_logic[q_logic.size() - 1] = fr::zero(); // last gate is a noop + q_c[q_c.size() - 1] = FF::zero(); // last gate is a noop + q_logic[q_logic.size() - 1] = FF::zero(); // last gate is a noop - assert_equal(a, accumulators.left[accumulators.left.size() - 1], "cannot reproduce `a` value using accumulator."); + this->assert_equal( + a, accumulators.left[accumulators.left.size() - 1], "cannot reproduce `a` value using accumulator."); accumulators.left[accumulators.left.size() - 1] = a; - assert_equal(b, accumulators.right[accumulators.right.size() - 1], "cannot reproduce `b` value using accumulator."); + this->assert_equal( + b, accumulators.right[accumulators.right.size() - 1], "cannot reproduce `b` value using accumulator."); accumulators.right[accumulators.right.size() - 1] = b; - num_gates += (num_quads + 1); + this->num_gates += (num_quads + 1); return accumulators; } -accumulator_triple TurboCircuitBuilder::create_and_constraint(const uint32_t a, const uint32_t b, const size_t num_bits) +template +accumulator_triple TurboCircuitBuilder_::create_and_constraint(const uint32_t a, + const uint32_t b, + const size_t num_bits) { return create_logic_constraint(a, b, num_bits, false); } -accumulator_triple TurboCircuitBuilder::create_xor_constraint(const uint32_t a, const uint32_t b, const size_t num_bits) +template +accumulator_triple TurboCircuitBuilder_::create_xor_constraint(const uint32_t a, + const uint32_t b, + const size_t num_bits) { return create_logic_constraint(a, b, num_bits, true); } -uint32_t TurboCircuitBuilder::put_constant_variable(const barretenberg::fr& variable) +template uint32_t TurboCircuitBuilder_::put_constant_variable(const FF& variable) { if (constant_variable_indices.contains(variable)) { return constant_variable_indices.at(variable); } else { - uint32_t variable_index = add_variable(variable); + uint32_t variable_index = this->add_variable(variable); fix_witness(variable_index, variable); constant_variable_indices.insert({ variable, variable_index }); return variable_index; @@ -772,9 +784,9 @@ uint32_t TurboCircuitBuilder::put_constant_variable(const barretenberg::fr& vari * @return true Evaluation is zero * @return false Evaluation is not zero */ -inline bool TurboCircuitBuilder::lazy_arithmetic_gate_check(const size_t gate_index) +template inline bool TurboCircuitBuilder_::lazy_arithmetic_gate_check(const size_t gate_index) { - return arithmetic_gate_evaluation(gate_index, fr::one()).is_zero(); + return arithmetic_gate_evaluation(gate_index, FF::one()).is_zero(); } /** @@ -784,52 +796,52 @@ inline bool TurboCircuitBuilder::lazy_arithmetic_gate_check(const size_t gate_in * @return bool * TODO(luke/kesha): Add some comments explaining in what sense each of these checks are "lazy" */ -inline bool TurboCircuitBuilder::lazy_fixed_base_gate_check(const size_t gate_index) +template inline bool TurboCircuitBuilder_::lazy_fixed_base_gate_check(const size_t gate_index) { - ASSERT(gate_index < num_gates); + ASSERT(gate_index < this->num_gates); - constexpr barretenberg::fr grumpkin_curve_b(-17); - constexpr barretenberg::fr nine(9); + constexpr FF grumpkin_curve_b(-17); + constexpr FF nine(9); // Get witness values - fr wire_1_shifted; - fr wire_2_shifted; - fr wire_3_shifted; - fr wire_4_shifted; - const fr wire_1_value = get_variable(w_l[gate_index]); - const fr wire_2_value = get_variable(w_r[gate_index]); - const fr wire_3_value = get_variable(w_o[gate_index]); - const fr wire_4_value = get_variable(w_4[gate_index]); - if ((gate_index + 1) < num_gates) { - wire_1_shifted = get_variable(w_l[gate_index + 1]); - wire_2_shifted = get_variable(w_r[gate_index + 1]); - wire_3_shifted = get_variable(w_o[gate_index + 1]); - wire_4_shifted = get_variable(w_4[gate_index + 1]); + FF wire_1_shifted; + FF wire_2_shifted; + FF wire_3_shifted; + FF wire_4_shifted; + const FF wire_1_value = this->get_variable(w_l[gate_index]); + const FF wire_2_value = this->get_variable(w_r[gate_index]); + const FF wire_3_value = this->get_variable(w_o[gate_index]); + const FF wire_4_value = this->get_variable(w_4[gate_index]); + if ((gate_index + 1) < this->num_gates) { + wire_1_shifted = this->get_variable(w_l[gate_index + 1]); + wire_2_shifted = this->get_variable(w_r[gate_index + 1]); + wire_3_shifted = this->get_variable(w_o[gate_index + 1]); + wire_4_shifted = this->get_variable(w_4[gate_index + 1]); } else { - wire_1_shifted = fr::zero(); - wire_2_shifted = fr::zero(); - wire_3_shifted = fr::zero(); - wire_4_shifted = fr::zero(); + wire_1_shifted = FF::zero(); + wire_2_shifted = FF::zero(); + wire_3_shifted = FF::zero(); + wire_4_shifted = FF::zero(); } // Get selector values - const fr q_c_value = q_c[gate_index]; - const fr q_fixed_base_value = q_fixed_base[gate_index]; - const fr q_m_value = q_m[gate_index]; - const fr q_1_value = q_1[gate_index]; - const fr q_2_value = q_2[gate_index]; - const fr q_3_value = q_3[gate_index]; - const fr q_4_value = q_4[gate_index]; - const fr q_5_value = q_5[gate_index]; + const FF q_c_value = q_c[gate_index]; + const FF q_fixed_base_value = q_fixed_base[gate_index]; + const FF q_m_value = q_m[gate_index]; + const FF q_1_value = q_1[gate_index]; + const FF q_2_value = q_2[gate_index]; + const FF q_3_value = q_3[gate_index]; + const FF q_4_value = q_4[gate_index]; + const FF q_5_value = q_5[gate_index]; // Compute, optimizing multiplications (different fromt the way we used in widgets, since the linearization // trick is no more) - fr delta = wire_4_shifted - (wire_4_value + wire_4_value + wire_4_value + wire_4_value); - fr delta_squared = delta.sqr(); + FF delta = wire_4_shifted - (wire_4_value + wire_4_value + wire_4_value + wire_4_value); + FF delta_squared = delta.sqr(); // accumulator_identity = (δ + 3)(δ + 1)(δ - 1)(δ - 3) - if (delta_squared != nine && delta_squared != fr::one()) { + if (delta_squared != nine && delta_squared != FF::one()) { return false; } @@ -838,19 +850,19 @@ inline bool TurboCircuitBuilder::lazy_fixed_base_gate_check(const size_t gate_in return false; } - fr T0 = wire_1_shifted + wire_1_value + wire_3_shifted; - fr T1 = (wire_3_shifted - wire_1_value).sqr(); + FF T0 = wire_1_shifted + wire_1_value + wire_3_shifted; + FF T1 = (wire_3_shifted - wire_1_value).sqr(); T0 = T0 * T1; T1 = wire_3_shifted.sqr() * wire_3_shifted; - fr T2 = wire_2_value.sqr(); + FF T2 = wire_2_value.sqr(); T1 = T1 + T2; T1 = -(T1 + grumpkin_curve_b); T2 = delta * wire_2_value * q_fixed_base_value; T2 = T2 + T2; - fr T3_part = delta * wire_3_shifted * q_3_value; - fr T3 = T3_part * wire_2_value; + FF T3_part = delta * wire_3_shifted * q_3_value; + FF T3 = T3_part * wire_2_value; T3 = T3 + T3; // x_accumulator_identity = α^2 * @@ -871,19 +883,19 @@ inline bool TurboCircuitBuilder::lazy_fixed_base_gate_check(const size_t gate_in } if (!q_c_value.is_zero()) { - T0 = wire_4_value - fr::one(); + T0 = wire_4_value - FF::one(); T1 = T0 - wire_3_value; if (!T0.is_zero() && !T1.is_zero()) { return false; } - T0 = wire_3_value * (q_4_value - wire_1_value) + (fr::one() - wire_4_value) * q_5_value; + T0 = wire_3_value * (q_4_value - wire_1_value) + (FF::one() - wire_4_value) * q_5_value; if (!T0.is_zero()) { return false; } - T0 = q_c_value * (fr::one() - wire_4_value); + T0 = q_c_value * (FF::one() - wire_4_value); T1 = wire_2_value * wire_3_value; - fr y_init_identity = (T0 - T1 + q_m_value * wire_3_value); + FF y_init_identity = (T0 - T1 + q_m_value * wire_3_value); if (!y_init_identity.is_zero()) { return false; } @@ -897,44 +909,44 @@ inline bool TurboCircuitBuilder::lazy_fixed_base_gate_check(const size_t gate_in * @param gate_index Gate index * @return fr */ -inline bool TurboCircuitBuilder::lazy_logic_gate_check(const size_t gate_index) +template inline bool TurboCircuitBuilder_::lazy_logic_gate_check(const size_t gate_index) { - ASSERT(gate_index < num_gates); - - fr wire_1_shifted; - fr wire_2_shifted; - fr wire_4_shifted; - const fr wire_1_value = get_variable(w_l[gate_index]); - const fr wire_2_value = get_variable(w_r[gate_index]); - const fr wire_4_value = get_variable(w_4[gate_index]); - if ((gate_index + 1) < num_gates) { - wire_1_shifted = get_variable(w_l[gate_index + 1]); - wire_2_shifted = get_variable(w_r[gate_index + 1]); - wire_4_shifted = get_variable(w_4[gate_index + 1]); + ASSERT(gate_index < this->num_gates); + + FF wire_1_shifted; + FF wire_2_shifted; + FF wire_4_shifted; + const FF wire_1_value = this->get_variable(w_l[gate_index]); + const FF wire_2_value = this->get_variable(w_r[gate_index]); + const FF wire_4_value = this->get_variable(w_4[gate_index]); + if ((gate_index + 1) < this->num_gates) { + wire_1_shifted = this->get_variable(w_l[gate_index + 1]); + wire_2_shifted = this->get_variable(w_r[gate_index + 1]); + wire_4_shifted = this->get_variable(w_4[gate_index + 1]); } else { - wire_1_shifted = fr::zero(); - wire_2_shifted = fr::zero(); - wire_4_shifted = fr::zero(); + wire_1_shifted = FF::zero(); + wire_2_shifted = FF::zero(); + wire_4_shifted = FF::zero(); } // Get selector values - const fr q_c_value = q_c[gate_index]; - const fr q_logic_value = q_logic[gate_index]; - constexpr fr two(2); - constexpr fr three(3); - constexpr fr minus_one = -fr::one(); + const FF q_c_value = q_c[gate_index]; + const FF q_logic_value = q_logic[gate_index]; + constexpr FF two(2); + constexpr FF three(3); + constexpr FF minus_one = -FF::one(); - fr T0; - fr T1; - fr T2; + FF T0; + FF T1; + FF T2; // T0 = a T0 = wire_1_value + wire_1_value; T0 += T0; T0 = wire_1_shifted - T0; - if (!T0.is_zero() && T0 != fr::one() && T0 != two && T0 != three) { + if (!T0.is_zero() && T0 != FF::one() && T0 != two && T0 != three) { return false; } // T1 = b @@ -942,7 +954,7 @@ inline bool TurboCircuitBuilder::lazy_logic_gate_check(const size_t gate_index) T1 += T1; T1 = wire_2_shifted - T1; - if (!T1.is_zero() && T1 != fr::one() && T1 != two && T1 != three) { + if (!T1.is_zero() && T1 != FF::one() && T1 != two && T1 != three) { return false; } @@ -951,14 +963,14 @@ inline bool TurboCircuitBuilder::lazy_logic_gate_check(const size_t gate_index) T2 += T2; T2 = wire_4_shifted - T2; - if (!T2.is_zero() && T2 != fr::one() && T2 != two && T2 != three) { + if (!T2.is_zero() && T2 != FF::one() && T2 != two && T2 != three) { return false; } uint64_t a = uint256_t(T0).data[0]; uint64_t b = uint256_t(T1).data[0]; uint64_t c = uint256_t(T2).data[0]; - if (q_c_value == fr::one() && q_logic_value == fr::one()) { + if (q_c_value == FF::one() && q_logic_value == FF::one()) { return (a & b) == c; } @@ -973,50 +985,50 @@ inline bool TurboCircuitBuilder::lazy_logic_gate_check(const size_t gate_index) * @param gate_index Gate index * @return bool */ -inline bool TurboCircuitBuilder::lazy_range_gate_check(const size_t gate_index) +template inline bool TurboCircuitBuilder_::lazy_range_gate_check(const size_t gate_index) { - ASSERT(gate_index < num_gates); + ASSERT(gate_index < this->num_gates); - fr wire_4_shifted; - const fr wire_1_value = get_variable(w_l[gate_index]); - const fr wire_2_value = get_variable(w_r[gate_index]); - const fr wire_3_value = get_variable(w_o[gate_index]); - const fr wire_4_value = get_variable(w_4[gate_index]); - if ((gate_index + 1) < num_gates) { - wire_4_shifted = get_variable(w_4[gate_index + 1]); + FF wire_4_shifted; + const FF wire_1_value = this->get_variable(w_l[gate_index]); + const FF wire_2_value = this->get_variable(w_r[gate_index]); + const FF wire_3_value = this->get_variable(w_o[gate_index]); + const FF wire_4_value = this->get_variable(w_4[gate_index]); + if ((gate_index + 1) < this->num_gates) { + wire_4_shifted = this->get_variable(w_4[gate_index + 1]); } else { - wire_4_shifted = fr::zero(); + wire_4_shifted = FF::zero(); } - constexpr barretenberg::fr two(2); - constexpr barretenberg::fr three(3); + constexpr FF two(2); + constexpr FF three(3); - fr delta_1 = wire_4_value + wire_4_value; + FF delta_1 = wire_4_value + wire_4_value; delta_1 += delta_1; delta_1 = (wire_3_value - delta_1).reduce_once(); - if (!delta_1.is_zero() && delta_1 != fr::one() && delta_1 != two && delta_1 != three) { + if (!delta_1.is_zero() && delta_1 != FF::one() && delta_1 != two && delta_1 != three) { return false; } - fr delta_2 = wire_3_value + wire_3_value; + FF delta_2 = wire_3_value + wire_3_value; delta_2 += delta_2; delta_2 = wire_2_value - delta_2; - if (!delta_2.is_zero() && delta_2 != fr::one() && delta_2 != two && delta_2 != three) { + if (!delta_2.is_zero() && delta_2 != FF::one() && delta_2 != two && delta_2 != three) { return false; } - fr delta_3 = wire_2_value + wire_2_value; + FF delta_3 = wire_2_value + wire_2_value; delta_3 += delta_3; delta_3 = wire_1_value - delta_3; - if (!delta_3.is_zero() && delta_3 != fr::one() && delta_3 != two && delta_3 != three) { + if (!delta_3.is_zero() && delta_3 != FF::one() && delta_3 != two && delta_3 != three) { return false; } - fr delta_4 = wire_1_value + wire_1_value; + FF delta_4 = wire_1_value + wire_1_value; delta_4 += delta_4; delta_4 = wire_4_shifted - delta_4; - if (!delta_4.is_zero() && delta_4 != fr::one() && delta_4 != two && delta_4 != three) { + if (!delta_4.is_zero() && delta_4 != FF::one() && delta_4 != two && delta_4 != three) { return false; } @@ -1029,32 +1041,33 @@ inline bool TurboCircuitBuilder::lazy_range_gate_check(const size_t gate_index) * @param alpha_base The base value that the whole evaluation is multiplied by * @return fr */ -inline fr TurboCircuitBuilder::arithmetic_gate_evaluation(const size_t gate_index, const fr alpha_base) +template +inline FF TurboCircuitBuilder_::arithmetic_gate_evaluation(const size_t gate_index, const FF alpha_base) { - ASSERT(gate_index < num_gates); + ASSERT(gate_index < this->num_gates); - constexpr barretenberg::fr minus_seven(-7); + constexpr FF minus_seven(-7); - constexpr fr two = fr::one() + fr::one(); - const fr wire_1_value = get_variable(w_l[gate_index]); - const fr wire_2_value = get_variable(w_r[gate_index]); - const fr wire_3_value = get_variable(w_o[gate_index]); - const fr wire_4_value = get_variable(w_4[gate_index]); + constexpr FF two = FF::one() + FF::one(); + const FF wire_1_value = this->get_variable(w_l[gate_index]); + const FF wire_2_value = this->get_variable(w_r[gate_index]); + const FF wire_3_value = this->get_variable(w_o[gate_index]); + const FF wire_4_value = this->get_variable(w_4[gate_index]); // T2 = Δ - fr T2 = wire_4_value + wire_4_value; + FF T2 = wire_4_value + wire_4_value; T2 += T2; T2 = wire_3_value - T2; // T3 = 2Δ^2 - fr T3 = T2.sqr(); + FF T3 = T2.sqr(); T3 += T3; // T4 = 9.Δ - fr T4 = T2 + T2; + FF T4 = T2 + T2; T4 += T2; // // T5 = 6.Δ - fr T5 = T4 + T4; + FF T5 = T4 + T4; T4 += T5; // T4 = 9.Δ - 2.Δ^2 - 7 @@ -1067,7 +1080,7 @@ inline fr TurboCircuitBuilder::arithmetic_gate_evaluation(const size_t gate_inde return alpha_base * q_arith[gate_index] * (wire_1_value * (q_m[gate_index] * wire_2_value + q_1[gate_index]) + q_2[gate_index] * wire_2_value + q_3[gate_index] * wire_3_value + - wire_4_value * (q_4[gate_index] + q_5[gate_index] * (wire_4_value - two) * (wire_4_value - fr::one())) + + wire_4_value * (q_4[gate_index] + q_5[gate_index] * (wire_4_value - two) * (wire_4_value - FF::one())) + q_c[gate_index] + (q_arith[gate_index] - 1) * T2); } /** @@ -1078,52 +1091,53 @@ inline fr TurboCircuitBuilder::arithmetic_gate_evaluation(const size_t gate_inde * @param alpha An element used as a separator of individual subrelations * @return fr */ -inline fr TurboCircuitBuilder::range_gate_evaluation(const size_t gate_index, const fr alpha_base, const fr alpha) +template +inline FF TurboCircuitBuilder_::range_gate_evaluation(const size_t gate_index, const FF alpha_base, const FF alpha) { - ASSERT(gate_index < num_gates); + ASSERT(gate_index < this->num_gates); - fr wire_4_shifted; - const fr wire_1_value = get_variable(w_l[gate_index]); - const fr wire_2_value = get_variable(w_r[gate_index]); - const fr wire_3_value = get_variable(w_o[gate_index]); - const fr wire_4_value = get_variable(w_4[gate_index]); - if ((gate_index + 1) < num_gates) { - wire_4_shifted = get_variable(w_4[gate_index + 1]); + FF wire_4_shifted; + const FF wire_1_value = this->get_variable(w_l[gate_index]); + const FF wire_2_value = this->get_variable(w_r[gate_index]); + const FF wire_3_value = this->get_variable(w_o[gate_index]); + const FF wire_4_value = this->get_variable(w_4[gate_index]); + if ((gate_index + 1) < this->num_gates) { + wire_4_shifted = this->get_variable(w_4[gate_index + 1]); } else { - wire_4_shifted = fr::zero(); + wire_4_shifted = FF::zero(); } - constexpr barretenberg::fr minus_two(-2); - constexpr barretenberg::fr minus_three(-3); - fr alpha_a = alpha_base; - fr alpha_b = alpha_a * alpha; - fr alpha_c = alpha_b * alpha; - fr alpha_d = alpha_c * alpha; - - fr delta_1 = wire_4_value + wire_4_value; + constexpr FF minus_two(-2); + constexpr FF minus_three(-3); + FF alpha_a = alpha_base; + FF alpha_b = alpha_a * alpha; + FF alpha_c = alpha_b * alpha; + FF alpha_d = alpha_c * alpha; + + FF delta_1 = wire_4_value + wire_4_value; delta_1 += delta_1; delta_1 = wire_3_value - delta_1; - fr delta_2 = wire_3_value + wire_3_value; + FF delta_2 = wire_3_value + wire_3_value; delta_2 += delta_2; delta_2 = wire_2_value - delta_2; - fr delta_3 = wire_2_value + wire_2_value; + FF delta_3 = wire_2_value + wire_2_value; delta_3 += delta_3; delta_3 = wire_1_value - delta_3; - fr delta_4 = wire_1_value + wire_1_value; + FF delta_4 = wire_1_value + wire_1_value; delta_4 += delta_4; delta_4 = wire_4_shifted - delta_4; // D(D - 1)(D - 2)(D - 3).alpha - fr T0 = delta_1.sqr(); + FF T0 = delta_1.sqr(); T0 -= delta_1; - fr T1 = delta_1 + minus_two; + FF T1 = delta_1 + minus_two; T0 *= T1; T1 = delta_1 + minus_three; T0 *= T1; - fr range_accumulator = T0 * alpha_a; + FF range_accumulator = T0 * alpha_a; T0 = delta_2.sqr(); T0 -= delta_2; @@ -1162,42 +1176,43 @@ inline fr TurboCircuitBuilder::range_gate_evaluation(const size_t gate_index, co * @param alpha The element used as separator for individual subrelations * @return fr */ -inline fr TurboCircuitBuilder::logic_gate_evaluation(const size_t gate_index, const fr alpha_base, const fr alpha) +template +inline FF TurboCircuitBuilder_::logic_gate_evaluation(const size_t gate_index, const FF alpha_base, const FF alpha) { - ASSERT(gate_index < num_gates); - - fr wire_1_shifted; - fr wire_2_shifted; - fr wire_4_shifted; - const fr wire_1_value = get_variable(w_l[gate_index]); - const fr wire_2_value = get_variable(w_r[gate_index]); - const fr wire_3_value = get_variable(w_o[gate_index]); - const fr wire_4_value = get_variable(w_4[gate_index]); - if ((gate_index + 1) < num_gates) { - wire_1_shifted = get_variable(w_l[gate_index + 1]); - wire_2_shifted = get_variable(w_r[gate_index + 1]); - wire_4_shifted = get_variable(w_4[gate_index + 1]); + ASSERT(gate_index < this->num_gates); + + FF wire_1_shifted; + FF wire_2_shifted; + FF wire_4_shifted; + const FF wire_1_value = this->get_variable(w_l[gate_index]); + const FF wire_2_value = this->get_variable(w_r[gate_index]); + const FF wire_3_value = this->get_variable(w_o[gate_index]); + const FF wire_4_value = this->get_variable(w_4[gate_index]); + if ((gate_index + 1) < this->num_gates) { + wire_1_shifted = this->get_variable(w_l[gate_index + 1]); + wire_2_shifted = this->get_variable(w_r[gate_index + 1]); + wire_4_shifted = this->get_variable(w_4[gate_index + 1]); } else { - wire_1_shifted = fr::zero(); - wire_2_shifted = fr::zero(); - wire_4_shifted = fr::zero(); + wire_1_shifted = FF::zero(); + wire_2_shifted = FF::zero(); + wire_4_shifted = FF::zero(); } // Get selector values - const fr q_c_value = q_c[gate_index]; - constexpr fr six(6); - constexpr fr eighty_one(81); - constexpr fr eighty_three(83); - - fr delta_sum; - fr delta_squared_sum; - fr T0; - fr T1; - fr T2; - fr T3; - fr T4; - fr identity; + const FF q_c_value = q_c[gate_index]; + constexpr FF six(6); + constexpr FF eighty_one(81); + constexpr FF eighty_three(83); + + FF delta_sum; + FF delta_squared_sum; + FF T0; + FF T1; + FF T2; + FF T3; + FF T4; + FF identity; T0 = wire_1_value + wire_1_value; T0 += T0; @@ -1330,66 +1345,68 @@ inline fr TurboCircuitBuilder::logic_gate_evaluation(const size_t gate_index, co * @param alpha_powers A vector with alpha_base and alpha_base*α^{i} for enough i * @return fr */ -inline fr TurboCircuitBuilder::fixed_base_gate_evaluation(const size_t gate_index, const std::vector& alpha_powers) +template +inline FF TurboCircuitBuilder_::fixed_base_gate_evaluation(const size_t gate_index, + const std::vector& alpha_powers) { - ASSERT(gate_index < num_gates); + ASSERT(gate_index < this->num_gates); - constexpr barretenberg::fr grumpkin_curve_b(-17); - constexpr barretenberg::fr three(3); + constexpr FF grumpkin_curve_b(-17); + constexpr FF three(3); // Get witness values - fr wire_1_shifted; - fr wire_2_shifted; - fr wire_3_shifted; - fr wire_4_shifted; - const fr wire_1_value = get_variable(w_l[gate_index]); - const fr wire_2_value = get_variable(w_r[gate_index]); - const fr wire_3_value = get_variable(w_o[gate_index]); - const fr wire_4_value = get_variable(w_4[gate_index]); - if ((gate_index + 1) < num_gates) { - wire_1_shifted = get_variable(w_l[gate_index + 1]); - wire_2_shifted = get_variable(w_r[gate_index + 1]); - wire_3_shifted = get_variable(w_o[gate_index + 1]); - wire_4_shifted = get_variable(w_4[gate_index + 1]); + FF wire_1_shifted; + FF wire_2_shifted; + FF wire_3_shifted; + FF wire_4_shifted; + const FF wire_1_value = this->get_variable(w_l[gate_index]); + const FF wire_2_value = this->get_variable(w_r[gate_index]); + const FF wire_3_value = this->get_variable(w_o[gate_index]); + const FF wire_4_value = this->get_variable(w_4[gate_index]); + if ((gate_index + 1) < this->num_gates) { + wire_1_shifted = this->get_variable(w_l[gate_index + 1]); + wire_2_shifted = this->get_variable(w_r[gate_index + 1]); + wire_3_shifted = this->get_variable(w_o[gate_index + 1]); + wire_4_shifted = this->get_variable(w_4[gate_index + 1]); } else { - wire_1_shifted = fr::zero(); - wire_2_shifted = fr::zero(); - wire_3_shifted = fr::zero(); - wire_4_shifted = fr::zero(); + wire_1_shifted = FF::zero(); + wire_2_shifted = FF::zero(); + wire_3_shifted = FF::zero(); + wire_4_shifted = FF::zero(); } // Get selector values - const fr q_c_value = q_c[gate_index]; - const fr q_fixed_base_value = q_fixed_base[gate_index]; - const fr q_m_value = q_m[gate_index]; - const fr q_1_value = q_1[gate_index]; - const fr q_2_value = q_2[gate_index]; - const fr q_3_value = q_3[gate_index]; - const fr q_4_value = q_4[gate_index]; - const fr q_5_value = q_5[gate_index]; + const FF q_c_value = q_c[gate_index]; + const FF q_fixed_base_value = q_fixed_base[gate_index]; + const FF q_m_value = q_m[gate_index]; + const FF q_1_value = q_1[gate_index]; + const FF q_2_value = q_2[gate_index]; + const FF q_3_value = q_3[gate_index]; + const FF q_4_value = q_4[gate_index]; + const FF q_5_value = q_5[gate_index]; // Compute, optimizing multiplications (different from the way we used in widgets, since the linearization // trick is no more) - fr delta = wire_4_shifted - (wire_4_value + wire_4_value + wire_4_value + wire_4_value); - fr delta_squared = delta.sqr(); + FF delta = wire_4_shifted - (wire_4_value + wire_4_value + wire_4_value + wire_4_value); + FF delta_squared = delta.sqr(); // accumulator_identity = (δ + 3)(δ + 1)(δ - 1)(δ - 3) - fr result = (delta - three) * (delta - fr::one()) * (delta + fr::one()) * (delta + three) * alpha_powers[0]; + FF result = (delta - three) * (delta - FF::one()) * (delta + FF::one()) * (delta + three) * alpha_powers[0]; // Originaly q_1 and q_2 multiplicands with x_alpha_identity result += (delta_squared * q_1_value + q_2_value - wire_3_shifted) * alpha_powers[1]; - fr T1_part = wire_2_value * alpha_powers[2]; + FF T1_part = wire_2_value * alpha_powers[2]; // Added q_3 multiplicand result += ((T1_part + T1_part) + (wire_1_shifted - wire_1_value) * alpha_powers[3]) * delta * wire_3_shifted * q_3_value; - fr T0 = wire_1_shifted + wire_1_value + wire_3_shifted; - fr T1 = (wire_3_shifted - wire_1_value).sqr(); + FF T0 = wire_1_shifted + wire_1_value + wire_3_shifted; + FF T1 = (wire_3_shifted - wire_1_value).sqr(); T0 = T0 * T1; T1 = wire_3_shifted.sqr() * wire_3_shifted; - fr T2 = wire_2_value.sqr(); + FF T2 = wire_2_value.sqr(); T1 = T1 + T2; T1 = -(T1 + grumpkin_curve_b); @@ -1410,23 +1427,23 @@ inline fr TurboCircuitBuilder::fixed_base_gate_evaluation(const size_t gate_inde result += (T0 + T1) * alpha_powers[3]; - T0 = wire_4_value - fr::one(); + T0 = wire_4_value - FF::one(); T1 = T0 - wire_3_value; - fr accumulator_init_identity = T0 * T1 * alpha_powers[4]; + FF accumulator_init_identity = T0 * T1 * alpha_powers[4]; // q_4 and q_5 - result += (((wire_3_value * q_4_value + (fr::one() - wire_4_value) * q_5_value) * alpha_powers[5]) + + result += (((wire_3_value * q_4_value + (FF::one() - wire_4_value) * q_5_value) * alpha_powers[5]) + (q_m_value * wire_3_value * alpha_powers[6])) * q_c_value; // x_init_identity = -α^5 * w_1 * w_3 - fr x_init_identity = -(wire_1_value * wire_3_value) * alpha_powers[5]; + FF x_init_identity = -(wire_1_value * wire_3_value) * alpha_powers[5]; // y_init_identity = α^6 * (q_c * (1 - w_4) - w_2 * w_3) - T0 = fr::one() - wire_4_value; + T0 = FF::one() - wire_4_value; T0 = T0 * q_c_value; T1 = wire_2_value * wire_3_value; - fr y_init_identity = (T0 - T1) * alpha_powers[6]; + FF y_init_identity = (T0 - T1) * alpha_powers[6]; result += (accumulator_init_identity + x_init_identity + y_init_identity) * q_c_value; return result * q_fixed_base_value; @@ -1436,11 +1453,11 @@ inline fr TurboCircuitBuilder::fixed_base_gate_evaluation(const size_t gate_inde * * @return true if circuit is correct, false if not. * */ -bool TurboCircuitBuilder::check_circuit() +template bool TurboCircuitBuilder_::check_circuit() { // #define LAZY_CIRCUIT_CHECKS #ifdef LAZY_CIRCUIT_CHECKS - for (size_t i = 0; i < num_gates; i++) { + for (size_t i = 0; i < this->num_gates; i++) { if (!q_arith[i].is_zero() && !lazy_arithmetic_gate_check(i)) { return false; } @@ -1457,15 +1474,15 @@ bool TurboCircuitBuilder::check_circuit() return true; #else // Initialize each of the kernels - const fr alpha_base = fr::random_element(); - const fr alpha = fr::random_element(); - std::vector alpha_powers; + const FF alpha_base = FF::random_element(); + const FF alpha = FF::random_element(); + std::vector alpha_powers; alpha_powers.push_back(alpha_base); for (size_t i = 1; i < 7; i++) { alpha_powers.push_back(alpha_powers[i - 1] * alpha); } - for (size_t i = 0; i < get_num_gates(); i++) { + for (size_t i = 0; i < this->get_num_gates(); i++) { if (!arithmetic_gate_evaluation(i, alpha_base).is_zero()) { #ifndef FUZZING info("Arithmetic gate ", i, " failed"); @@ -1498,5 +1515,5 @@ bool TurboCircuitBuilder::check_circuit() #endif } - +template class TurboCircuitBuilder_; } // namespace proof_system diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp b/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp index af77bf341e..9ec56e68df 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/turbo_circuit_builder.hpp @@ -1,4 +1,5 @@ #pragma once +#include "barretenberg/ecc/curves/bn254/bn254.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" @@ -13,7 +14,8 @@ inline std::vector turbo_selector_names() "q_5", "q_arith", "q_fixed_base", "q_range", "q_logic" }; return result; } -class TurboCircuitBuilder : public CircuitBuilderBase> { +template class TurboCircuitBuilder_ : public CircuitBuilderBase> { + public: static constexpr std::string_view NAME_STRING = "TurboArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::TURBO; @@ -23,34 +25,34 @@ class TurboCircuitBuilder : public CircuitBuilderBase>; - using SelectorVector = std::vector>; - - 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_5 = selectors.q_5; - SelectorVector& q_arith = selectors.q_arith; - SelectorVector& q_fixed_base = selectors.q_fixed_base; - SelectorVector& q_range = selectors.q_range; - SelectorVector& q_logic = selectors.q_logic; - - TurboCircuitBuilder(const size_t size_hint = 0); - TurboCircuitBuilder(TurboCircuitBuilder&& other) = default; - TurboCircuitBuilder& operator=(TurboCircuitBuilder&& other) + 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_5 = this->selectors.q_5; + SelectorVector& q_arith = this->selectors.q_arith; + SelectorVector& q_fixed_base = this->selectors.q_fixed_base; + SelectorVector& q_range = this->selectors.q_range; + SelectorVector& q_logic = this->selectors.q_logic; + + TurboCircuitBuilder_(const size_t size_hint = 0); + TurboCircuitBuilder_(TurboCircuitBuilder_&& other) = default; + TurboCircuitBuilder_& operator=(TurboCircuitBuilder_&& other) { - CircuitBuilderBase>::operator=(std::move(other)); + CircuitBuilderBase>::operator=(std::move(other)); constant_variable_indices = other.constant_variable_indices; return *this; }; - ~TurboCircuitBuilder() {} + ~TurboCircuitBuilder_() {} void create_add_gate(const add_triple& in); @@ -65,16 +67,12 @@ class TurboCircuitBuilder : public CircuitBuilderBase& alpha_powers); - barretenberg::fr logic_gate_evaluation(const size_t index, - const barretenberg::fr alpha_bas, - const barretenberg::fr alpha); - barretenberg::fr range_gate_evaluation(const size_t index, - const barretenberg::fr alpha_bas, - const barretenberg::fr alpha); + FF arithmetic_gate_evaluation(const size_t index, const FF alpha_base); + FF fixed_base_gate_evaluation(const size_t index, const std::vector& alpha_powers); + FF logic_gate_evaluation(const size_t index, const FF alpha_bas, const FF alpha); + FF range_gate_evaluation(const size_t index, const FF alpha_bas, const FF alpha); bool lazy_arithmetic_gate_check(const size_t gate_index); bool lazy_fixed_base_gate_check(const size_t gate_index); @@ -99,31 +97,31 @@ class TurboCircuitBuilder : public CircuitBuilderBasevariables[a_idx] != b && !this->failed()) { + this->failure(msg); } auto b_idx = put_constant_variable(b); - assert_equal(a_idx, b_idx, msg); + this->assert_equal(a_idx, b_idx, msg); } /** * For any type other than uint32_t (presumed to be a witness index), we call normalize first. */ template - void assert_equal_constant(T const& in, const barretenberg::fr& b, std::string const& msg = "assert_equal_constant") + void assert_equal_constant(T const& in, const FF& b, std::string const& msg = "assert_equal_constant") { assert_equal_constant(in.normalize().witness_index, b, msg); } // these are variables that we have used a gate on, to enforce that they are equal to a defined value - std::map constant_variable_indices; + std::map constant_variable_indices; }; -} // namespace proof_system \ No newline at end of file +extern template class TurboCircuitBuilder_; +using TurboCircuitBuilder = TurboCircuitBuilder_; +} // namespace proof_system diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp b/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp index 3c9b063504..b8c65a780d 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.cpp @@ -1,10 +1,8 @@ /** * @file ultra_circuit_builder.cpp * @author Luke (ledwards2225) and Kesha (Rumata888) - * @brief This file contains the implementation of UltraCircuitBuilder class that defines the logic of ultra-style - * circuits and is intended for the use in UltraHonk and UltraPlonk systems - * - * @todo 1) Replace barretenberg::fr with templated FF or Field + * @brief This file contains the implementation of field-agnostic UltraCircuitBuilder class that defines the logic + * of ultra-style circuits and is intended for the use in UltraHonk and UltraPlonk systems * */ #include "ultra_circuit_builder.hpp" @@ -16,7 +14,7 @@ using namespace barretenberg; namespace proof_system { -void UltraCircuitBuilder::finalize_circuit() +template void UltraCircuitBuilder_::finalize_circuit() { /** * First of all, add the gates related to ROM arrays and range lists. @@ -37,7 +35,8 @@ void UltraCircuitBuilder::finalize_circuit() * * Its necessary to include the (n_rom + n_range) gates at this point because if we already have a * proving key, and we just return it without including these ROM and range list gates, the overall - * circuit size would not be correct (resulting in the code crashing while performing FFT operations). + * circuit size would not be correct (resulting in the code crashing while performing FFT + * operations). * * Therefore, we introduce a boolean flag `circuit_finalised` here. Once we add the rom and range gates, * our circuit is finalised, and we must not to execute these functions again. @@ -61,14 +60,14 @@ void UltraCircuitBuilder::finalize_circuit() // polynomials is zero, which is required for them to be shiftable. // TODO(#423)(luke): Add 0 as a PI since PI always start at the 0th index of the wire polynomials? // TODO(luke): may need to reevaluate once aux relation is implemented -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 - w_l.emplace_back(zero_idx); - w_r.emplace_back(zero_idx); - w_o.emplace_back(zero_idx); - w_4.emplace_back(zero_idx); + 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); @@ -81,15 +80,15 @@ void UltraCircuitBuilder::add_gates_to_ensure_all_polys_are_non_zero() q_lookup_type.emplace_back(0); q_elliptic.emplace_back(1); q_aux.emplace_back(1); - ++num_gates; + ++this->num_gates; // Some relations depend on wire shifts so we add another gate with // wires set to 0 to ensure corresponding constraints are satisfied - create_poly_gate({ zero_idx, zero_idx, zero_idx, 0, 0, 0, 0, 0 }); + create_poly_gate({ this->zero_idx, this->zero_idx, this->zero_idx, 0, 0, 0, 0, 0 }); // Add nonzero values in w_4 and q_c (q_4*w_4 + q_c --> 1*1 - 1 = 0) - one_idx = put_constant_variable(barretenberg::fr::one()); - create_big_add_gate({ zero_idx, zero_idx, zero_idx, one_idx, 0, 0, 0, 1, -1 }); + this->one_idx = put_constant_variable(FF::one()); + create_big_add_gate({ this->zero_idx, this->zero_idx, this->zero_idx, this->one_idx, 0, 0, 0, 1, -1 }); // Take care of all polys related to lookups (q_lookup, tables, sorted, etc) // by doing a dummy lookup with a special table. @@ -101,11 +100,11 @@ void UltraCircuitBuilder::add_gates_to_ensure_all_polys_are_non_zero() uint32_t left_value = 3; uint32_t right_value = 3; - fr left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); - fr right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); + FF left_witness_value = fr{ left_value, 0, 0, 0 }.to_montgomery_form(); + FF right_witness_value = fr{ right_value, 0, 0, 0 }.to_montgomery_form(); - uint32_t left_witness_index = add_variable(left_witness_value); - uint32_t right_witness_index = add_variable(right_witness_value); + uint32_t left_witness_index = this->add_variable(left_witness_value); + uint32_t right_witness_index = this->add_variable(right_witness_value); const auto dummy_accumulators = plookup::get_lookup_accumulators( plookup::MultiTableId::HONK_DUMMY_MULTI, left_witness_value, right_witness_value, true); create_gates_from_plookup_accumulators( @@ -120,14 +119,14 @@ void UltraCircuitBuilder::add_gates_to_ensure_all_polys_are_non_zero() * * @param in A structure with variable indexes and selector values for the gate. */ -void UltraCircuitBuilder::create_add_gate(const add_triple& in) +template void UltraCircuitBuilder_::create_add_gate(const add_triple& in) { - assert_valid_variables({ in.a, in.b, in.c }); + 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(zero_idx); + 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); @@ -139,20 +138,21 @@ void UltraCircuitBuilder::create_add_gate(const add_triple& in) q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } /** - * @brief Create a big addition gate, where in.a * in.a_scaling + in.b * in.b_scaling + in.c * in.c_scaling + in.d * - * in.d_scaling + in.const_scaling = 0. If include_next_gate_w_4 is enabled, then thes sum also adds the value of the - * 4-th witness at the next index. + * @brief Create a big addition gate, where in.a * in.a_scaling + in.b * in.b_scaling + in.c * + * in.c_scaling + in.d * in.d_scaling + in.const_scaling = 0. If include_next_gate_w_4 is enabled, then thes sum also + * adds the value of the 4-th witness at the next index. * * @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 */ -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) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + 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); @@ -168,16 +168,16 @@ void UltraCircuitBuilder::create_big_add_gate(const add_quad& in, const bool inc q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } /** - * @brief A legacy method that was used to extract a bit from c-4d by using gate selectors in the Turboplonk, but is - * simulated here for ultraplonk + * @brief A legacy method that was used to extract a bit from c-4d by using gate selectors in the + * Turboplonk, but is simulated here for ultraplonk * * @param in Structure with variables and witness selector values */ -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. @@ -188,13 +188,13 @@ void UltraCircuitBuilder::create_big_add_gate_with_bit_extraction(const add_quad // a + b + c + d + 6 * (extracted bit) = 0 // (extracted bit) is the high bit pulled from c - 4d - assert_valid_variables({ in.a, in.b, in.c, in.d }); + this->assert_valid_variables({ in.a, in.b, in.c, in.d }); - const uint256_t quad = get_variable(in.c) - get_variable(in.d) * 4; + const uint256_t quad = this->get_variable(in.c) - this->get_variable(in.d) * 4; const auto lo_bit = quad & uint256_t(1); const auto hi_bit = (quad & uint256_t(2)) >> 1; - const auto lo_idx = add_variable(lo_bit); - const auto hi_idx = add_variable(hi_bit); + const auto lo_idx = this->add_variable(lo_bit); + const auto hi_idx = this->add_variable(hi_bit); // lo + hi * 2 - c + 4 * d = 0 create_big_add_gate({ lo_idx, @@ -209,13 +209,13 @@ void UltraCircuitBuilder::create_big_add_gate_with_bit_extraction(const add_quad }); // create temporary variable t = in.a * in.a_scaling + 6 * hi_bit - const auto t = get_variable(in.a) * in.a_scaling + fr(hi_bit) * 6; - const auto t_idx = add_variable(t); + const auto t = this->get_variable(in.a) * in.a_scaling + FF(hi_bit) * 6; + const auto t_idx = this->add_variable(t); create_big_add_gate({ in.a, hi_idx, t_idx, - zero_idx, + this->zero_idx, in.a_scaling, 6, -1, @@ -240,9 +240,9 @@ void UltraCircuitBuilder::create_big_add_gate_with_bit_extraction(const add_quad * * @param in Structure containing variables and witness selectors */ -void UltraCircuitBuilder::create_big_mul_gate(const mul_quad& in) +template void UltraCircuitBuilder_::create_big_mul_gate(const mul_quad& in) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + this->assert_valid_variables({ in.a, in.b, in.c, in.d }); w_l.emplace_back(in.a); w_r.emplace_back(in.b); @@ -259,14 +259,14 @@ void UltraCircuitBuilder::create_big_mul_gate(const mul_quad& in) q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } // Creates a width-4 addition gate, where the fourth witness must be a boolean. // Can be used to normalize a 32-bit addition -void UltraCircuitBuilder::create_balanced_add_gate(const add_quad& in) +template void UltraCircuitBuilder_::create_balanced_add_gate(const add_quad& in) { - assert_valid_variables({ in.a, in.b, in.c, in.d }); + this->assert_valid_variables({ in.a, in.b, in.c, in.d }); w_l.emplace_back(in.a); w_r.emplace_back(in.b); @@ -283,7 +283,7 @@ void UltraCircuitBuilder::create_balanced_add_gate(const add_quad& in) q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; // Why 3? TODO: return to this // The purpose of this gate is to do enable lazy 32-bit addition. // Consider a + b = c mod 2^32 @@ -304,14 +304,14 @@ void UltraCircuitBuilder::create_balanced_add_gate(const add_quad& in) * * @param in Structure containing variables and witness selectors */ -void UltraCircuitBuilder::create_mul_gate(const mul_triple& in) +template void UltraCircuitBuilder_::create_mul_gate(const mul_triple& in) { - assert_valid_variables({ in.a, in.b, in.c }); + 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(zero_idx); + w_4.emplace_back(this->zero_idx); q_m.emplace_back(in.mul_scaling); q_1.emplace_back(0); q_2.emplace_back(0); @@ -323,21 +323,21 @@ void UltraCircuitBuilder::create_mul_gate(const mul_triple& in) q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } /** * @brief Generate an arithmetic gate equivalent to x^2 - x = 0, which forces x to be 0 or 1 * - * @param variable_index Variable which needs to be constrained + * @param variable_index the variable which needs to be constrained */ -void UltraCircuitBuilder::create_bool_gate(const uint32_t variable_index) +template void UltraCircuitBuilder_::create_bool_gate(const uint32_t variable_index) { - assert_valid_variables({ variable_index }); + this->assert_valid_variables({ variable_index }); w_l.emplace_back(variable_index); w_r.emplace_back(variable_index); - w_o.emplace_back(zero_idx); - w_4.emplace_back(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(0); @@ -350,22 +350,23 @@ void UltraCircuitBuilder::create_bool_gate(const uint32_t variable_index) q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } /** - * @brief A plonk gate with disabled (set to zero) fourth wire. q_m * a * b + q_1 * a + q_2 * b + q_3 * c + q_const = 0 + * @brief A plonk gate with disabled (set to zero) fourth wire. q_m * a * b + q_1 * a + q_2 * b + q_3 + * * c + q_const = 0 * * @param in Structure containing variables and witness selectors */ -void UltraCircuitBuilder::create_poly_gate(const poly_triple& in) +template void UltraCircuitBuilder_::create_poly_gate(const poly_triple& in) { - assert_valid_variables({ in.a, in.b, in.c }); + 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(zero_idx); + 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); @@ -378,7 +379,7 @@ void UltraCircuitBuilder::create_poly_gate(const poly_triple& in) q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } /** @@ -391,7 +392,7 @@ void UltraCircuitBuilder::create_poly_gate(const poly_triple& in) * added, the resulting point coordinates and the selector values that describe whether the endomorphism is used on the * second point and whether it is negated. */ -void UltraCircuitBuilder::create_ecc_add_gate(const ecc_add_gate& in) +template void UltraCircuitBuilder_::create_ecc_add_gate(const ecc_add_gate& in) { /** * | 1 | 2 | 3 | 4 | @@ -401,27 +402,27 @@ void UltraCircuitBuilder::create_ecc_add_gate(const ecc_add_gate& in) * **/ - assert_valid_variables({ in.x1, in.x2, in.x3, in.y1, in.y2, in.y3 }); + 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[num_gates - 1] == in.x1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (w_o[num_gates - 1] == in.y1); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_3[num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_4[num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_1[num_gates - 1] == 0); - can_fuse_into_previous_gate = can_fuse_into_previous_gate && (q_arith[num_gates - 1] == 0); + 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); if (can_fuse_into_previous_gate) { - q_3[num_gates - 1] = in.endomorphism_coefficient; - q_4[num_gates - 1] = in.endomorphism_coefficient.sqr(); - q_1[num_gates - 1] = in.sign_coefficient; - q_elliptic[num_gates - 1] = 1; + q_3[this->num_gates - 1] = in.endomorphism_coefficient; + q_4[this->num_gates - 1] = in.endomorphism_coefficient.sqr(); + q_1[this->num_gates - 1] = in.sign_coefficient; + q_elliptic[this->num_gates - 1] = 1; } else { - w_l.emplace_back(zero_idx); + w_l.emplace_back(this->zero_idx); w_r.emplace_back(in.x1); w_o.emplace_back(in.y1); - w_4.emplace_back(zero_idx); + w_4.emplace_back(this->zero_idx); q_3.emplace_back(in.endomorphism_coefficient); q_4.emplace_back(in.endomorphism_coefficient.sqr()); q_1.emplace_back(in.sign_coefficient); @@ -434,7 +435,7 @@ void UltraCircuitBuilder::create_ecc_add_gate(const ecc_add_gate& in) q_lookup_type.emplace_back(0); q_elliptic.emplace_back(1); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } w_l.emplace_back(in.x2); @@ -452,7 +453,7 @@ void UltraCircuitBuilder::create_ecc_add_gate(const ecc_add_gate& in) q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } /** @@ -461,14 +462,14 @@ void UltraCircuitBuilder::create_ecc_add_gate(const ecc_add_gate& in) * @param witness_index The index of the witness we are fixing * @param witness_value The value we are fixing it to */ -void UltraCircuitBuilder::fix_witness(const uint32_t witness_index, const barretenberg::fr& witness_value) +template void UltraCircuitBuilder_::fix_witness(const uint32_t witness_index, const FF& witness_value) { - assert_valid_variables({ witness_index }); + this->assert_valid_variables({ witness_index }); w_l.emplace_back(witness_index); - w_r.emplace_back(zero_idx); - w_o.emplace_back(zero_idx); - w_4.emplace_back(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(0); q_1.emplace_back(1); q_2.emplace_back(0); @@ -480,22 +481,22 @@ void UltraCircuitBuilder::fix_witness(const uint32_t witness_index, const barret q_lookup_type.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } -uint32_t UltraCircuitBuilder::put_constant_variable(const barretenberg::fr& variable) +template uint32_t UltraCircuitBuilder_::put_constant_variable(const FF& variable) { if (constant_variable_indices.contains(variable)) { return constant_variable_indices.at(variable); } else { - uint32_t variable_index = add_variable(variable); + uint32_t variable_index = this->add_variable(variable); fix_witness(variable_index, variable); constant_variable_indices.insert({ variable, variable_index }); return variable_index; } } -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) { @@ -510,9 +511,11 @@ plookup::BasicTable& UltraCircuitBuilder::get_table(const plookup::BasicTableId /** * @brief Perform a series of lookups, one for each 'row' in read_values. */ -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 plookup::ReadData& read_values, const uint32_t key_a_index, std::optional key_b_index) { @@ -524,23 +527,23 @@ plookup::ReadData UltraCircuitBuilder::create_gates_from_plookup_accum table.lookup_gates.emplace_back(read_values.key_entries[i]); - const auto first_idx = (i == 0) ? key_a_index : add_variable(read_values[plookup::ColumnIdx::C1][i]); + const auto first_idx = (i == 0) ? key_a_index : this->add_variable(read_values[plookup::ColumnIdx::C1][i]); const auto second_idx = (i == 0 && (key_b_index.has_value())) ? key_b_index.value() - : add_variable(read_values[plookup::ColumnIdx::C2][i]); - const auto third_idx = add_variable(read_values[plookup::ColumnIdx::C3][i]); + : this->add_variable(read_values[plookup::ColumnIdx::C2][i]); + const auto third_idx = this->add_variable(read_values[plookup::ColumnIdx::C3][i]); read_data[plookup::ColumnIdx::C1].push_back(first_idx); read_data[plookup::ColumnIdx::C2].push_back(second_idx); read_data[plookup::ColumnIdx::C3].push_back(third_idx); - assert_valid_variables({ first_idx, second_idx, third_idx }); + this->assert_valid_variables({ first_idx, second_idx, third_idx }); - q_lookup_type.emplace_back(fr(1)); - q_3.emplace_back(fr(table.table_index)); + 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(zero_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])); @@ -550,7 +553,7 @@ plookup::ReadData UltraCircuitBuilder::create_gates_from_plookup_accum q_sort.emplace_back(0); q_elliptic.emplace_back(0); q_aux.emplace_back(0); - ++num_gates; + ++this->num_gates; } return read_data; } @@ -558,8 +561,8 @@ plookup::ReadData UltraCircuitBuilder::create_gates_from_plookup_accum /** * Generalized Permutation Methods **/ - -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; @@ -574,12 +577,12 @@ UltraCircuitBuilder::RangeList UltraCircuitBuilder::create_range_list(const uint result.variable_indices.reserve((uint32_t)num_multiples_of_three); for (uint64_t i = 0; i <= num_multiples_of_three; ++i) { - const uint32_t index = add_variable(i * DEFAULT_PLOOKUP_RANGE_STEP_SIZE); + const uint32_t index = this->add_variable(i * DEFAULT_PLOOKUP_RANGE_STEP_SIZE); result.variable_indices.emplace_back(index); assign_tag(index, result.range_tag); } { - const uint32_t index = add_variable(target_range); + const uint32_t index = this->add_variable(target_range); result.variable_indices.emplace_back(index); assign_tag(index, result.range_tag); } @@ -590,20 +593,22 @@ UltraCircuitBuilder::RangeList UltraCircuitBuilder::create_range_list(const uint } // range constraint a value by decomposing it into limbs whose size should be the default range constraint size -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) { - assert_valid_variables({ variable_index }); + this->assert_valid_variables({ variable_index }); ASSERT(num_bits > 0); - uint256_t val = (uint256_t)(get_variable(variable_index)); + uint256_t val = (uint256_t)(this->get_variable(variable_index)); // If the value is out of range, set the composer error to the given msg. - if (val.get_msb() >= num_bits && !failed()) { - failure(msg); + if (val.get_msb() >= num_bits && !this->failed()) { + this->failure(msg); } const uint64_t sublimb_mask = (1ULL << target_range_bitnum) - 1; @@ -635,7 +640,7 @@ std::vector UltraCircuitBuilder::decompose_into_default_range(const ui accumulator = accumulator >> target_range_bitnum; } for (size_t i = 0; i < sublimbs.size(); ++i) { - const auto limb_idx = add_variable(sublimbs[i]); + const auto limb_idx = this->add_variable(sublimbs[i]); sublimb_indices.emplace_back(limb_idx); if ((i == sublimbs.size() - 1) && has_remainder_bits) { create_new_range_constraint(limb_idx, last_limb_range); @@ -663,9 +668,9 @@ std::vector UltraCircuitBuilder::decompose_into_default_range(const ui real_limbs[2] ? sublimbs[3 * i + 2] : 0, }; const uint32_t new_limbs[3]{ - real_limbs[0] ? sublimb_indices[3 * i] : zero_idx, - real_limbs[1] ? sublimb_indices[3 * i + 1] : zero_idx, - real_limbs[2] ? sublimb_indices[3 * i + 2] : zero_idx, + real_limbs[0] ? sublimb_indices[3 * i] : this->zero_idx, + real_limbs[1] ? sublimb_indices[3 * i + 1] : this->zero_idx, + real_limbs[2] ? sublimb_indices[3 * i + 2] : this->zero_idx, }; const uint64_t shifts[3]{ target_range_bitnum * (3 * i), @@ -689,7 +694,7 @@ std::vector UltraCircuitBuilder::decompose_into_default_range(const ui 0, }, ((i == num_limb_triples - 1) ? false : true)); - accumulator_idx = add_variable(new_accumulator); + accumulator_idx = this->add_variable(new_accumulator); accumulator = new_accumulator; } return sublimb_indices; @@ -704,21 +709,22 @@ std::vector UltraCircuitBuilder::decompose_into_default_range(const ui * @param variable_index * @param target_range */ -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(get_variable(variable_index)).data[0] > target_range) { - if (!failed()) { - failure(msg); + if (uint256_t(this->get_variable(variable_index)).data[0] > target_range) { + if (!this->failed()) { + this->failure(msg); } } if (range_lists.count(target_range) == 0) { range_lists.insert({ target_range, create_range_list(target_range) }); } - const auto existing_tag = real_variable_tags[real_variable_index[variable_index]]; + const auto existing_tag = this->real_variable_tags[this->real_variable_index[variable_index]]; auto& list = range_lists[target_range]; // If the variable's tag matches the target range list's tag, do nothing. @@ -737,10 +743,10 @@ void UltraCircuitBuilder::create_new_range_constraint(const uint32_t variable_in // The range constraint we are trying to impose is more restrictive than the existing range // constraint. It would be difficult to remove an existing range check. Instead deep-copy the // variable and apply a range check to new variable - const uint32_t copied_witness = add_variable(get_variable(variable_index)); + const uint32_t copied_witness = this->add_variable(this->get_variable(variable_index)); create_add_gate({ .a = variable_index, .b = copied_witness, - .c = zero_idx, + .c = this->zero_idx, .a_scaling = 1, .b_scaling = -1, .c_scaling = 0, @@ -758,9 +764,9 @@ void UltraCircuitBuilder::create_new_range_constraint(const uint32_t variable_in } } -void UltraCircuitBuilder::process_range_list(RangeList& list) +template void UltraCircuitBuilder_::process_range_list(RangeList& list) { - assert_valid_variables(list.variable_indices); + this->assert_valid_variables(list.variable_indices); ASSERT(list.variable_indices.size() > 0); @@ -768,7 +774,7 @@ void UltraCircuitBuilder::process_range_list(RangeList& list) // applied on a variable after it was range constrained, this makes sure the indices in list point to the updated // index in the range list so the set equivalence does not fail for (uint32_t& x : list.variable_indices) { - x = real_variable_index[x]; + x = this->real_variable_index[x]; } // remove duplicate witness indices to prevent the sorted list set size being wrong! std::sort(list.variable_indices.begin(), list.variable_indices.end()); @@ -781,7 +787,7 @@ void UltraCircuitBuilder::process_range_list(RangeList& list) std::vector sorted_list; sorted_list.reserve(list.variable_indices.size()); for (const auto variable_index : list.variable_indices) { - const auto& field_element = get_variable(variable_index); + const auto& field_element = this->get_variable(variable_index); const uint32_t shrinked_value = (uint32_t)field_element.from_montgomery_form().data[0]; sorted_list.emplace_back(shrinked_value); } @@ -802,17 +808,17 @@ void UltraCircuitBuilder::process_range_list(RangeList& list) padding += gate_width; } for (size_t i = 0; i < padding; ++i) { - indices.emplace_back(zero_idx); + indices.emplace_back(this->zero_idx); } for (const auto sorted_value : sorted_list) { - const uint32_t index = add_variable(sorted_value); + const uint32_t index = this->add_variable(sorted_value); assign_tag(index, list.tau_tag); indices.emplace_back(index); } create_sort_constraint_with_edges(indices, 0, list.target_range); } -void UltraCircuitBuilder::process_range_lists() +template void UltraCircuitBuilder_::process_range_lists() { for (auto& i : range_lists) { process_range_list(i.second); @@ -832,11 +838,12 @@ 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) -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); - assert_valid_variables(variable_index); + this->assert_valid_variables(variable_index); for (size_t i = 0; i < variable_index.size(); i += gate_width) { @@ -844,7 +851,7 @@ void UltraCircuitBuilder::create_sort_constraint(const std::vector& va w_r.emplace_back(variable_index[i + 1]); w_o.emplace_back(variable_index[i + 2]); w_4.emplace_back(variable_index[i + 3]); - ++num_gates; + ++this->num_gates; q_m.emplace_back(0); q_1.emplace_back(0); q_2.emplace_back(0); @@ -859,10 +866,10 @@ void UltraCircuitBuilder::create_sort_constraint(const std::vector& va } // 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(zero_idx); - w_o.emplace_back(zero_idx); - w_4.emplace_back(zero_idx); - ++num_gates; + w_r.emplace_back(this->zero_idx); + w_o.emplace_back(this->zero_idx); + w_4.emplace_back(this->zero_idx); + ++this->num_gates; q_m.emplace_back(0); q_1.emplace_back(0); q_2.emplace_back(0); @@ -878,23 +885,24 @@ void UltraCircuitBuilder::create_sort_constraint(const std::vector& va // useful to put variables in the witness that aren't already used - e.g. the dummy variables of the range constraint in // multiples of three -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; const uint64_t padding = (gate_width - (padded_list.size() % gate_width)) % gate_width; for (uint64_t i = 0; i < padding; ++i) { - padded_list.emplace_back(zero_idx); + padded_list.emplace_back(this->zero_idx); } - assert_valid_variables(variable_index); - assert_valid_variables(padded_list); + this->assert_valid_variables(variable_index); + 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]); - ++num_gates; + ++this->num_gates; q_m.emplace_back(0); q_1.emplace_back(0); q_2.emplace_back(0); @@ -910,21 +918,22 @@ void UltraCircuitBuilder::create_dummy_constraints(const std::vector& } // Check for a sequence of variables that neighboring differences are at most 3 (used for batched range checks) -void UltraCircuitBuilder::create_sort_constraint_with_edges(const std::vector& variable_index, - const fr& start, - const fr& 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; ASSERT(variable_index.size() % gate_width == 0 && variable_index.size() > gate_width); - assert_valid_variables(variable_index); + 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]); - ++num_gates; + ++this->num_gates; q_m.emplace_back(0); q_1.emplace_back(1); q_2.emplace_back(0); @@ -943,7 +952,7 @@ void UltraCircuitBuilder::create_sort_constraint_with_edges(const std::vectornum_gates; q_m.emplace_back(0); q_1.emplace_back(0); q_2.emplace_back(0); @@ -962,7 +971,7 @@ void UltraCircuitBuilder::create_sort_constraint_with_edges(const std::vectornum_gates; q_m.emplace_back(0); q_1.emplace_back(0); q_2.emplace_back(0); @@ -979,10 +988,10 @@ void UltraCircuitBuilder::create_sort_constraint_with_edges(const std::vectorzero_idx); + w_o.emplace_back(this->zero_idx); + w_4.emplace_back(this->zero_idx); + ++this->num_gates; q_m.emplace_back(0); q_1.emplace_back(1); q_2.emplace_back(0); @@ -997,7 +1006,9 @@ void UltraCircuitBuilder::create_sort_constraint_with_edges(const 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; @@ -1010,45 +1021,44 @@ std::vector UltraCircuitBuilder::decompose_into_default_range_better_f return sums; } - const uint256_t val = (uint256_t)(get_variable(variable_index)); + const uint256_t val = (uint256_t)(this->get_variable(variable_index)); // check witness value is indeed in range (commented out cause interferes with negative tests) - // ASSERT(val < ((uint256_t)1 << num_bits) - 1); // Q:ask Zac what happens with wrapping when converting fr to - // uint256 - // ASSERT(limb_num % 3 == 0); // TODO: write version of method that doesn't need this + // ASSERT(val < ((uint256_t)1 << num_bits) - 1); // Q:ask Zac what happens with wrapping when converting scalar + // field to uint256 ASSERT(limb_num % 3 == 0); // TODO: write version of method that doesn't need this std::vector val_limbs; std::vector val_slices; for (size_t i = 0; i < limb_num; i++) { val_slices.emplace_back( - barretenberg::fr(val.slice(DEFAULT_PLOOKUP_RANGE_BITNUM * i, DEFAULT_PLOOKUP_RANGE_BITNUM * (i + 1) - 1))); - val_limbs.emplace_back(add_variable(val_slices[i])); + FF(val.slice(DEFAULT_PLOOKUP_RANGE_BITNUM * i, DEFAULT_PLOOKUP_RANGE_BITNUM * (i + 1) - 1))); + val_limbs.emplace_back(this->add_variable(val_slices[i])); create_new_range_constraint(val_limbs[i], DEFAULT_PLOOKUP_RANGE_SIZE); } uint64_t last_limb_range = ((uint64_t)1 << last_limb_size) - 1; - fr last_slice(0); - uint32_t last_limb(zero_idx); + FF last_slice(0); + uint32_t last_limb(this->zero_idx); size_t total_limb_num = limb_num; if (last_limb_size > 0) { - val_slices.emplace_back(fr(val.slice(num_bits - last_limb_size, num_bits))); - val_limbs.emplace_back(add_variable(last_slice)); + val_slices.emplace_back(FF(val.slice(num_bits - last_limb_size, num_bits))); + val_limbs.emplace_back(this->add_variable(last_slice)); create_new_range_constraint(last_limb, last_limb_range); total_limb_num++; } // pad slices and limbs in case they are not 2 mod 3 if (total_limb_num % 3 == 1) { - val_limbs.emplace_back(zero_idx); // TODO: check this is zero + val_limbs.emplace_back(this->zero_idx); // TODO: check this is zero val_slices.emplace_back(0); total_limb_num++; } - fr shift = fr(1 << DEFAULT_PLOOKUP_RANGE_BITNUM); - fr second_shift = shift * shift; - sums.emplace_back(add_variable(val_slices[0] + shift * val_slices[1] + second_shift * val_slices[2])); + FF shift = FF(1 << DEFAULT_PLOOKUP_RANGE_BITNUM); + FF second_shift = shift * shift; + sums.emplace_back(this->add_variable(val_slices[0] + shift * val_slices[1] + second_shift * val_slices[2])); create_big_add_gate({ val_limbs[0], val_limbs[1], val_limbs[2], sums[0], 1, shift, second_shift, -1, 0 }); - fr cur_shift = (shift * second_shift); - fr cur_second_shift = cur_shift * shift; + FF cur_shift = (shift * second_shift); + FF cur_second_shift = cur_shift * shift; for (size_t i = 3; i < total_limb_num; i = i + 2) { - sums.emplace_back(add_variable(get_variable(sums[sums.size() - 1]) + cur_shift * val_slices[i] + - cur_second_shift * val_slices[i + 1])); + sums.emplace_back(this->add_variable(this->get_variable(sums[sums.size() - 1]) + cur_shift * val_slices[i] + + cur_second_shift * val_slices[i + 1])); create_big_add_gate({ sums[sums.size() - 2], val_limbs[i], val_limbs[i + 1], @@ -1061,7 +1071,7 @@ std::vector UltraCircuitBuilder::decompose_into_default_range_better_f cur_shift *= second_shift; cur_second_shift *= second_shift; } - assert_equal(sums[sums.size() - 1], variable_index, msg); + this->assert_equal(sums[sums.size() - 1], variable_index, msg); return sums; } @@ -1092,7 +1102,7 @@ std::vector UltraCircuitBuilder::decompose_into_default_range_better_f * * @param type */ -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); @@ -1252,10 +1262,11 @@ void UltraCircuitBuilder::apply_aux_selectors(const AUX_SELECTORS type) * 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 **/ -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 @@ -1264,17 +1275,21 @@ void UltraCircuitBuilder::range_constrain_two_limbs(const uint32_t lo_idx, // Sometimes we try to use limbs that are too large. It's easier to catch this issue here const auto get_sublimbs = [&](const uint32_t& limb_idx, const std::array& sublimb_masks) { - const uint256_t limb = get_variable(limb_idx); + const uint256_t limb = this->get_variable(limb_idx); // we can use constant 2^14 - 1 mask here. If the sublimb value exceeds the expected value then witness will // fail the range check below // We also use zero_idx to substitute variables that should be zero constexpr uint256_t MAX_SUBLIMB_MASK = (uint256_t(1) << 14) - 1; std::array sublimb_indices; - sublimb_indices[0] = sublimb_masks[0] != 0 ? add_variable(limb & MAX_SUBLIMB_MASK) : zero_idx; - sublimb_indices[1] = sublimb_masks[1] != 0 ? add_variable((limb >> 14) & MAX_SUBLIMB_MASK) : zero_idx; - sublimb_indices[2] = sublimb_masks[2] != 0 ? add_variable((limb >> 28) & MAX_SUBLIMB_MASK) : zero_idx; - sublimb_indices[3] = sublimb_masks[3] != 0 ? add_variable((limb >> 42) & MAX_SUBLIMB_MASK) : zero_idx; - sublimb_indices[4] = sublimb_masks[4] != 0 ? add_variable((limb >> 56) & MAX_SUBLIMB_MASK) : zero_idx; + sublimb_indices[0] = sublimb_masks[0] != 0 ? this->add_variable(limb & MAX_SUBLIMB_MASK) : this->zero_idx; + sublimb_indices[1] = + sublimb_masks[1] != 0 ? this->add_variable((limb >> 14) & MAX_SUBLIMB_MASK) : this->zero_idx; + sublimb_indices[2] = + sublimb_masks[2] != 0 ? this->add_variable((limb >> 28) & MAX_SUBLIMB_MASK) : this->zero_idx; + sublimb_indices[3] = + sublimb_masks[3] != 0 ? this->add_variable((limb >> 42) & MAX_SUBLIMB_MASK) : this->zero_idx; + sublimb_indices[4] = + sublimb_masks[4] != 0 ? this->add_variable((limb >> 56) & MAX_SUBLIMB_MASK) : this->zero_idx; return sublimb_indices; }; @@ -1315,7 +1330,7 @@ void UltraCircuitBuilder::range_constrain_two_limbs(const uint32_t lo_idx, apply_aux_selectors(AUX_SELECTORS::LIMB_ACCUMULATE_1); apply_aux_selectors(AUX_SELECTORS::LIMB_ACCUMULATE_2); apply_aux_selectors(AUX_SELECTORS::NONE); - num_gates += 3; + this->num_gates += 3; for (size_t i = 0; i < 5; i++) { if (lo_masks[i] != 0) { @@ -1337,18 +1352,20 @@ void UltraCircuitBuilder::range_constrain_two_limbs(const uint32_t lo_idx, * @param num_limb_bits The range we want to constrain the original limb to * @return std::array The indices of new limbs. */ -std::array UltraCircuitBuilder::decompose_non_native_field_double_width_limb(const uint32_t limb_idx, - const size_t num_limb_bits) + +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(get_variable_reference(limb_idx)) < (uint256_t(1) << num_limb_bits)); - constexpr barretenberg::fr LIMB_MASK = (uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS) - 1; - const uint256_t value = get_variable(limb_idx); + ASSERT(uint256_t(this->get_variable_reference(limb_idx)) < (uint256_t(1) << num_limb_bits)); + constexpr FF LIMB_MASK = (uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS) - 1; + const uint256_t value = this->get_variable(limb_idx); const uint256_t low = value & LIMB_MASK; const uint256_t hi = value >> DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; ASSERT(low + (hi << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS) == value); - const uint32_t low_idx = add_variable(low); - const uint32_t hi_idx = add_variable(hi); + const uint32_t low_idx = this->add_variable(low); + const uint32_t hi_idx = this->add_variable(hi); ASSERT(num_limb_bits > DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); const size_t lo_bits = DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; @@ -1374,61 +1391,61 @@ std::array UltraCircuitBuilder::decompose_non_native_field_double_w * * N.B.: This method does NOT evaluate the prime field component of non-native field multiplications. **/ -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) { std::array a{ - get_variable(input.a[0]), - get_variable(input.a[1]), - get_variable(input.a[2]), - get_variable(input.a[3]), + this->get_variable(input.a[0]), + this->get_variable(input.a[1]), + this->get_variable(input.a[2]), + this->get_variable(input.a[3]), }; std::array b{ - get_variable(input.b[0]), - get_variable(input.b[1]), - get_variable(input.b[2]), - get_variable(input.b[3]), + this->get_variable(input.b[0]), + this->get_variable(input.b[1]), + this->get_variable(input.b[2]), + this->get_variable(input.b[3]), }; std::array q{ - get_variable(input.q[0]), - get_variable(input.q[1]), - get_variable(input.q[2]), - get_variable(input.q[3]), + this->get_variable(input.q[0]), + this->get_variable(input.q[1]), + this->get_variable(input.q[2]), + this->get_variable(input.q[3]), }; std::array r{ - get_variable(input.r[0]), - get_variable(input.r[1]), - get_variable(input.r[2]), - get_variable(input.r[3]), + this->get_variable(input.r[0]), + this->get_variable(input.r[1]), + this->get_variable(input.r[2]), + this->get_variable(input.r[3]), }; - constexpr barretenberg::fr LIMB_SHIFT = uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; - constexpr barretenberg::fr LIMB_SHIFT_2 = uint256_t(1) << (2 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); - constexpr barretenberg::fr LIMB_SHIFT_3 = uint256_t(1) << (3 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); - constexpr barretenberg::fr LIMB_RSHIFT = - barretenberg::fr(1) / barretenberg::fr(uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); - constexpr barretenberg::fr LIMB_RSHIFT_2 = - barretenberg::fr(1) / barretenberg::fr(uint256_t(1) << (2 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS)); - - barretenberg::fr lo_0 = a[0] * b[0] - r[0] + (a[1] * b[0] + a[0] * b[1]) * LIMB_SHIFT; - barretenberg::fr lo_1 = (lo_0 + q[0] * input.neg_modulus[0] + - (q[1] * input.neg_modulus[0] + q[0] * input.neg_modulus[1] - r[1]) * LIMB_SHIFT) * - LIMB_RSHIFT_2; - - barretenberg::fr hi_0 = a[2] * b[0] + a[0] * b[2] + (a[0] * b[3] + a[3] * b[0] - r[3]) * LIMB_SHIFT; - barretenberg::fr hi_1 = hi_0 + a[1] * b[1] - r[2] + (a[1] * b[2] + a[2] * b[1]) * LIMB_SHIFT; - barretenberg::fr hi_2 = (hi_1 + lo_1 + q[2] * input.neg_modulus[0] + - (q[3] * input.neg_modulus[0] + q[2] * input.neg_modulus[1]) * LIMB_SHIFT); - barretenberg::fr hi_3 = (hi_2 + (q[0] * input.neg_modulus[3] + q[1] * input.neg_modulus[2]) * LIMB_SHIFT + - (q[0] * input.neg_modulus[2] + q[1] * input.neg_modulus[1])) * - LIMB_RSHIFT_2; - - const uint32_t lo_0_idx = add_variable(lo_0); - const uint32_t lo_1_idx = add_variable(lo_1); - const uint32_t hi_0_idx = add_variable(hi_0); - const uint32_t hi_1_idx = add_variable(hi_1); - const uint32_t hi_2_idx = add_variable(hi_2); - const uint32_t hi_3_idx = add_variable(hi_3); + constexpr FF LIMB_SHIFT = uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; + constexpr FF LIMB_SHIFT_2 = uint256_t(1) << (2 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); + constexpr FF LIMB_SHIFT_3 = uint256_t(1) << (3 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); + constexpr FF LIMB_RSHIFT = FF(1) / FF(uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); + constexpr FF LIMB_RSHIFT_2 = FF(1) / FF(uint256_t(1) << (2 * DEFAULT_NON_NATIVE_FIELD_LIMB_BITS)); + + FF lo_0 = a[0] * b[0] - r[0] + (a[1] * b[0] + a[0] * b[1]) * LIMB_SHIFT; + FF lo_1 = (lo_0 + q[0] * input.neg_modulus[0] + + (q[1] * input.neg_modulus[0] + q[0] * input.neg_modulus[1] - r[1]) * LIMB_SHIFT) * + LIMB_RSHIFT_2; + + FF hi_0 = a[2] * b[0] + a[0] * b[2] + (a[0] * b[3] + a[3] * b[0] - r[3]) * LIMB_SHIFT; + FF hi_1 = hi_0 + a[1] * b[1] - r[2] + (a[1] * b[2] + a[2] * b[1]) * LIMB_SHIFT; + FF hi_2 = (hi_1 + lo_1 + q[2] * input.neg_modulus[0] + + (q[3] * input.neg_modulus[0] + q[2] * input.neg_modulus[1]) * LIMB_SHIFT); + FF hi_3 = (hi_2 + (q[0] * input.neg_modulus[3] + q[1] * input.neg_modulus[2]) * LIMB_SHIFT + + (q[0] * input.neg_modulus[2] + q[1] * input.neg_modulus[1])) * + LIMB_RSHIFT_2; + + const uint32_t lo_0_idx = this->add_variable(lo_0); + const uint32_t lo_1_idx = this->add_variable(lo_1); + const uint32_t hi_0_idx = this->add_variable(hi_0); + const uint32_t hi_1_idx = this->add_variable(hi_1); + const uint32_t hi_2_idx = this->add_variable(hi_2); + const uint32_t hi_3_idx = this->add_variable(hi_3); // Sometimes we have already applied range constraints on the quotient and remainder if (range_constrain_quotient_and_remainder) { @@ -1473,25 +1490,25 @@ std::array UltraCircuitBuilder::evaluate_non_native_field_multiplic w_o.emplace_back(input.r[0]); w_4.emplace_back(lo_0_idx); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_1); - ++num_gates; + ++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]); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_2); - ++num_gates; + ++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); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_3); - ++num_gates; + ++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); apply_aux_selectors(AUX_SELECTORS::NONE); - ++num_gates; + ++this->num_gates; /** * product gate 6 @@ -1538,13 +1555,13 @@ std::array UltraCircuitBuilder::evaluate_non_native_field_multiplic * Iterates over the cached_non_native_field_multiplication objects, * removes duplicates, and instantiates the remainder as constraints` */ -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]; for (size_t j = 0; j < 5; ++j) { - c.a[j] = real_variable_index[c.a[j]]; - c.b[j] = real_variable_index[c.b[j]]; + c.a[j] = this->real_variable_index[c.a[j]]; + c.b[j] = this->real_variable_index[c.b[j]]; } } std::sort(cached_partial_non_native_field_multiplications.begin(), @@ -1561,28 +1578,28 @@ void UltraCircuitBuilder::process_non_native_field_multiplications() w_l.emplace_back(input.a[1]); w_r.emplace_back(input.b[1]); - w_o.emplace_back(zero_idx); + w_o.emplace_back(this->zero_idx); w_4.emplace_back(input.lo_0); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_1); - ++num_gates; + ++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]); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_2); - ++num_gates; + ++this->num_gates; w_l.emplace_back(input.a[2]); w_r.emplace_back(input.b[2]); - w_o.emplace_back(zero_idx); + w_o.emplace_back(this->zero_idx); w_4.emplace_back(input.hi_0); apply_aux_selectors(AUX_SELECTORS::NON_NATIVE_FIELD_3); - ++num_gates; + ++this->num_gates; w_l.emplace_back(input.a[1]); w_r.emplace_back(input.b[1]); - w_o.emplace_back(zero_idx); + w_o.emplace_back(this->zero_idx); w_4.emplace_back(input.hi_1); apply_aux_selectors(AUX_SELECTORS::NONE); - ++num_gates; + ++this->num_gates; ++it; } } @@ -1594,33 +1611,35 @@ void UltraCircuitBuilder::process_non_native_field_multiplications() * limbs with size DEFAULT_NON_NATIVE_FIELD_LIMB_BITS * **/ -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) { std::array a{ - get_variable(input.a[0]), - get_variable(input.a[1]), - get_variable(input.a[2]), - get_variable(input.a[3]), + this->get_variable(input.a[0]), + this->get_variable(input.a[1]), + this->get_variable(input.a[2]), + this->get_variable(input.a[3]), }; std::array b{ - get_variable(input.b[0]), - get_variable(input.b[1]), - get_variable(input.b[2]), - get_variable(input.b[3]), + this->get_variable(input.b[0]), + this->get_variable(input.b[1]), + this->get_variable(input.b[2]), + this->get_variable(input.b[3]), }; - constexpr barretenberg::fr LIMB_SHIFT = uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; + constexpr FF LIMB_SHIFT = uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS; - barretenberg::fr lo_0 = a[0] * b[0] + (a[1] * b[0] + a[0] * b[1]) * LIMB_SHIFT; + FF lo_0 = a[0] * b[0] + (a[1] * b[0] + a[0] * b[1]) * LIMB_SHIFT; - barretenberg::fr hi_0 = a[2] * b[0] + a[0] * b[2] + (a[0] * b[3] + a[3] * b[0]) * LIMB_SHIFT; - barretenberg::fr hi_1 = hi_0 + a[1] * b[1] + (a[1] * b[2] + a[2] * b[1]) * LIMB_SHIFT; + FF hi_0 = a[2] * b[0] + a[0] * b[2] + (a[0] * b[3] + a[3] * b[0]) * LIMB_SHIFT; + FF hi_1 = hi_0 + a[1] * b[1] + (a[1] * b[2] + a[2] * b[1]) * LIMB_SHIFT; - const uint32_t lo_0_idx = add_variable(lo_0); - const uint32_t hi_0_idx = add_variable(hi_0); - const uint32_t hi_1_idx = add_variable(hi_1); + const uint32_t lo_0_idx = this->add_variable(lo_0); + const uint32_t hi_0_idx = this->add_variable(hi_0); + const uint32_t hi_1_idx = this->add_variable(hi_1); // Add witnesses into the multiplication cache // (when finalising the circuit, we will remove duplicates; several dups produced by biggroup.hpp methods) @@ -1639,12 +1658,10 @@ std::array UltraCircuitBuilder::queue_partial_non_native_field_mult * Uses a sneaky extra mini-addition gate in `plookup_arithmetic_widget.hpp` to add two non-native * field elements in 4 gates (would normally take 5) **/ -std::array UltraCircuitBuilder::evaluate_non_native_field_addition( - add_simple limb0, - add_simple limb1, - add_simple limb2, - add_simple limb3, - std::tuple limbp) + +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; const auto& x_1 = std::get<0>(limb1).first; @@ -1676,17 +1693,17 @@ std::array UltraCircuitBuilder::evaluate_non_native_field_addition( const auto& addconstp = std::get<2>(limbp); // get value of result limbs - const auto z_0value = get_variable(x_0) * x_mulconst0 + get_variable(y_0) * y_mulconst0 + addconst0; - const auto z_1value = get_variable(x_1) * x_mulconst1 + get_variable(y_1) * y_mulconst1 + addconst1; - const auto z_2value = get_variable(x_2) * x_mulconst2 + get_variable(y_2) * y_mulconst2 + addconst2; - const auto z_3value = get_variable(x_3) * x_mulconst3 + get_variable(y_3) * y_mulconst3 + addconst3; - const auto z_pvalue = get_variable(x_p) + get_variable(y_p) + addconstp; - - const auto z_0 = add_variable(z_0value); - const auto z_1 = add_variable(z_1value); - const auto z_2 = add_variable(z_2value); - const auto z_3 = add_variable(z_3value); - const auto z_p = add_variable(z_pvalue); + const auto z_0value = this->get_variable(x_0) * x_mulconst0 + this->get_variable(y_0) * y_mulconst0 + addconst0; + const auto z_1value = this->get_variable(x_1) * x_mulconst1 + this->get_variable(y_1) * y_mulconst1 + addconst1; + const auto z_2value = this->get_variable(x_2) * x_mulconst2 + this->get_variable(y_2) * y_mulconst2 + addconst2; + const auto z_3value = this->get_variable(x_3) * x_mulconst3 + this->get_variable(y_3) * y_mulconst3 + addconst3; + const auto z_pvalue = this->get_variable(x_p) + this->get_variable(y_p) + addconstp; + + const auto z_0 = this->add_variable(z_0value); + const auto z_1 = this->add_variable(z_1value); + const auto z_2 = this->add_variable(z_2value); + const auto z_3 = this->add_variable(z_3value); + const auto z_p = this->add_variable(z_pvalue); /** * we want the following layout in program memory @@ -1717,7 +1734,7 @@ std::array UltraCircuitBuilder::evaluate_non_native_field_addition( w_l.emplace_back(x_3); w_r.emplace_back(y_3); w_o.emplace_back(z_3); - w_4.emplace_back(zero_idx); + w_4.emplace_back(this->zero_idx); q_m.emplace_back(addconstp); q_1.emplace_back(0); @@ -1759,18 +1776,15 @@ std::array UltraCircuitBuilder::evaluate_non_native_field_addition( q_aux.emplace_back(0); } - num_gates += 4; + this->num_gates += 4; return std::array{ z_0, z_1, z_2, z_3, z_p, }; } -std::array UltraCircuitBuilder::evaluate_non_native_field_subtraction( - add_simple limb0, - add_simple limb1, - add_simple limb2, - add_simple limb3, - std::tuple limbp) +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; const auto& x_1 = std::get<0>(limb1).first; @@ -1802,17 +1816,17 @@ std::array UltraCircuitBuilder::evaluate_non_native_field_subtracti const auto& addconstp = std::get<2>(limbp); // get value of result limbs - const auto z_0value = get_variable(x_0) * x_mulconst0 - get_variable(y_0) * y_mulconst0 + addconst0; - const auto z_1value = get_variable(x_1) * x_mulconst1 - get_variable(y_1) * y_mulconst1 + addconst1; - const auto z_2value = get_variable(x_2) * x_mulconst2 - get_variable(y_2) * y_mulconst2 + addconst2; - const auto z_3value = get_variable(x_3) * x_mulconst3 - get_variable(y_3) * y_mulconst3 + addconst3; - const auto z_pvalue = get_variable(x_p) - get_variable(y_p) + addconstp; - - const auto z_0 = add_variable(z_0value); - const auto z_1 = add_variable(z_1value); - const auto z_2 = add_variable(z_2value); - const auto z_3 = add_variable(z_3value); - const auto z_p = add_variable(z_pvalue); + const auto z_0value = this->get_variable(x_0) * x_mulconst0 - this->get_variable(y_0) * y_mulconst0 + addconst0; + const auto z_1value = this->get_variable(x_1) * x_mulconst1 - this->get_variable(y_1) * y_mulconst1 + addconst1; + const auto z_2value = this->get_variable(x_2) * x_mulconst2 - this->get_variable(y_2) * y_mulconst2 + addconst2; + const auto z_3value = this->get_variable(x_3) * x_mulconst3 - this->get_variable(y_3) * y_mulconst3 + addconst3; + const auto z_pvalue = this->get_variable(x_p) - this->get_variable(y_p) + addconstp; + + const auto z_0 = this->add_variable(z_0value); + const auto z_1 = this->add_variable(z_1value); + const auto z_2 = this->add_variable(z_2value); + const auto z_3 = this->add_variable(z_3value); + const auto z_p = this->add_variable(z_pvalue); /** * we want the following layout in program memory @@ -1842,7 +1856,7 @@ std::array UltraCircuitBuilder::evaluate_non_native_field_subtracti w_l.emplace_back(x_3); w_r.emplace_back(y_3); w_o.emplace_back(z_3); - w_4.emplace_back(zero_idx); + w_4.emplace_back(this->zero_idx); q_m.emplace_back(-addconstp); q_1.emplace_back(0); @@ -1883,29 +1897,30 @@ std::array UltraCircuitBuilder::evaluate_non_native_field_subtracti q_aux.emplace_back(0); } - num_gates += 4; + this->num_gates += 4; return std::array{ z_0, z_1, z_2, z_3, z_p, }; } /** - * @brief Gate that 'reads' from a ROM table. + * @brief + * Gate that'reads' from a ROM table. * i.e. table index is a witness not precomputed * * @param record Stores details of this read operation. Mutated by this fn! */ -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 = add_variable(0); + 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); - record.gate_index = num_gates; - ++num_gates; + record.gate_index = this->num_gates; + ++this->num_gates; } /** @@ -1915,16 +1930,16 @@ void UltraCircuitBuilder::create_ROM_gate(RomRecord& record) * * @param record Stores details of this read operation. Mutated by this fn! */ -void UltraCircuitBuilder::create_sorted_ROM_gate(RomRecord& record) +template void UltraCircuitBuilder_::create_sorted_ROM_gate(RomRecord& record) { - record.record_witness = add_variable(0); + 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); - record.gate_index = num_gates; - ++num_gates; + record.gate_index = this->num_gates; + ++this->num_gates; } /** @@ -1937,7 +1952,8 @@ void UltraCircuitBuilder::create_sorted_ROM_gate(RomRecord& record) * @param array_size The size of region in elements * @return size_t The index of the element */ -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) { @@ -1954,40 +1970,41 @@ size_t UltraCircuitBuilder::create_ROM_array(const size_t array_size) * * @param record Stores details of this read operation. Mutated by this fn! */ -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, // we will be applying copy constraints + set membership constraints. // Later on during proof construction we will compute the record wire value + assign it - record.record_witness = add_variable(0); + 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); - record.gate_index = num_gates; - ++num_gates; + record.gate_index = this->num_gates; + ++this->num_gates; } /** - * @brief Gate that performs consistency checks to validate that a claimed RAM read/write value is correct + * @brief Gate that performs consistency checks to validate that a claimed RAM read/write value is + * correct * * @details sorted RAM gates are generated sequentially, each RAM record is sorted first by index then by timestamp * * @param record Stores details of this read operation. Mutated by this fn! */ -void UltraCircuitBuilder::create_sorted_RAM_gate(RamRecord& record) +template void UltraCircuitBuilder_::create_sorted_RAM_gate(RamRecord& record) { - record.record_witness = add_variable(0); + 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); - record.gate_index = num_gates; - ++num_gates; + record.gate_index = this->num_gates; + ++this->num_gates; } /** @@ -1996,10 +2013,11 @@ void UltraCircuitBuilder::create_sorted_RAM_gate(RamRecord& record) * * @param record Stores details of this read operation. Mutated by this fn! */ -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 = add_variable(0); - record.gate_index = num_gates; + record.record_witness = this->add_variable(0); + record.gate_index = this->num_gates; create_big_add_gate({ record.index_witness, @@ -2010,7 +2028,7 @@ void UltraCircuitBuilder::create_final_sorted_RAM_gate(RamRecord& record, const 0, 0, 0, - -fr((uint64_t)ram_array_size - 1), + -FF((uint64_t)ram_array_size - 1), }); } @@ -2024,7 +2042,7 @@ void UltraCircuitBuilder::create_final_sorted_RAM_gate(RamRecord& record, const * @param array_size The size of region in elements * @return size_t The index of the element */ -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) { @@ -2041,11 +2059,14 @@ size_t UltraCircuitBuilder::create_RAM_array(const size_t array_size) * @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 */ -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]; - const uint32_t index_witness = (index_value == 0) ? zero_idx : put_constant_variable((uint64_t)index_value); + const uint32_t index_witness = (index_value == 0) ? this->zero_idx : put_constant_variable((uint64_t)index_value); ASSERT(ram_array.state.size() > index_value); ASSERT(ram_array.state[index_value] == UNINITIALIZED_MEMORY_RECORD); RamRecord new_record{ .index_witness = index_witness, @@ -2062,15 +2083,16 @@ void UltraCircuitBuilder::init_RAM_element(const size_t ram_id, const size_t ind ram_array.records.emplace_back(new_record); } -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]; - const uint32_t index = static_cast(uint256_t(get_variable(index_witness))); + const uint32_t index = static_cast(uint256_t(this->get_variable(index_witness))); ASSERT(ram_array.state.size() > index); ASSERT(ram_array.state[index] != UNINITIALIZED_MEMORY_RECORD); - const auto value = get_variable(ram_array.state[index]); - const uint32_t value_witness = add_variable(value); + const auto value = this->get_variable(ram_array.state[index]); + const uint32_t value_witness = this->add_variable(value); RamRecord new_record{ .index_witness = index_witness, .timestamp_witness = put_constant_variable((uint64_t)ram_array.access_count), @@ -2090,13 +2112,14 @@ uint32_t UltraCircuitBuilder::read_RAM_array(const size_t ram_id, const uint32_t return value_witness; } -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]; - const uint32_t index = static_cast(uint256_t(get_variable(index_witness))); + const uint32_t index = static_cast(uint256_t(this->get_variable(index_witness))); ASSERT(ram_array.state.size() > index); ASSERT(ram_array.state[index] != UNINITIALIZED_MEMORY_RECORD); @@ -2132,11 +2155,14 @@ 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 */ -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]; - const uint32_t index_witness = (index_value == 0) ? zero_idx : put_constant_variable((uint64_t)index_value); + const uint32_t index_witness = (index_value == 0) ? this->zero_idx : put_constant_variable((uint64_t)index_value); ASSERT(rom_array.state.size() > index_value); ASSERT(rom_array.state[index_value][0] == UNINITIALIZED_MEMORY_RECORD); /** @@ -2154,13 +2180,13 @@ void UltraCircuitBuilder::set_ROM_element(const size_t rom_id, const size_t inde RomRecord new_record{ .index_witness = index_witness, .value_column1_witness = value_witness, - .value_column2_witness = zero_idx, + .value_column2_witness = this->zero_idx, .index = static_cast(index_value), .record_witness = 0, .gate_index = 0, }; rom_array.state[index_value][0] = value_witness; - rom_array.state[index_value][1] = zero_idx; + rom_array.state[index_value][1] = this->zero_idx; create_ROM_gate(new_record); rom_array.records.emplace_back(new_record); } @@ -2172,13 +2198,14 @@ void UltraCircuitBuilder::set_ROM_element(const size_t rom_id, const size_t inde * @param index_value Index in the array * @param value_witnesses The witnesses to put in the slot */ -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]; - const uint32_t index_witness = (index_value == 0) ? zero_idx : put_constant_variable((uint64_t)index_value); + const uint32_t index_witness = (index_value == 0) ? this->zero_idx : put_constant_variable((uint64_t)index_value); ASSERT(rom_array.state.size() > index_value); ASSERT(rom_array.state[index_value][0] == UNINITIALIZED_MEMORY_RECORD); RomRecord new_record{ @@ -2202,19 +2229,20 @@ 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 */ -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]; - const uint32_t index = static_cast(uint256_t(get_variable(index_witness))); + const uint32_t index = static_cast(uint256_t(this->get_variable(index_witness))); ASSERT(rom_array.state.size() > index); ASSERT(rom_array.state[index][0] != UNINITIALIZED_MEMORY_RECORD); - const auto value = get_variable(rom_array.state[index][0]); - const uint32_t value_witness = add_variable(value); + const auto value = this->get_variable(rom_array.state[index][0]); + const uint32_t value_witness = this->add_variable(value); RomRecord new_record{ .index_witness = index_witness, .value_column1_witness = value_witness, - .value_column2_witness = zero_idx, + .value_column2_witness = this->zero_idx, .index = index, .record_witness = 0, .gate_index = 0, @@ -2233,20 +2261,22 @@ uint32_t UltraCircuitBuilder::read_ROM_array(const size_t rom_id, const uint32_t * @param index_witness The witness containing the index in the array * @return std::array A pair of indexes of witness variables of cell values */ -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; - const uint32_t index = static_cast(uint256_t(get_variable(index_witness))); + const uint32_t index = static_cast(uint256_t(this->get_variable(index_witness))); ASSERT(rom_arrays.size() > rom_id); RomTranscript& rom_array = rom_arrays[rom_id]; ASSERT(rom_array.state.size() > index); ASSERT(rom_array.state[index][0] != UNINITIALIZED_MEMORY_RECORD); ASSERT(rom_array.state[index][1] != UNINITIALIZED_MEMORY_RECORD); - const auto value1 = get_variable(rom_array.state[index][0]); - const auto value2 = get_variable(rom_array.state[index][1]); - value_witnesses[0] = add_variable(value1); - value_witnesses[1] = add_variable(value2); + const auto value1 = this->get_variable(rom_array.state[index][0]); + const auto value2 = this->get_variable(rom_array.state[index][1]); + value_witnesses[0] = this->add_variable(value1); + value_witnesses[1] = this->add_variable(value2); RomRecord new_record{ .index_witness = index_witness, .value_column1_witness = value_witnesses[0], @@ -2268,7 +2298,7 @@ std::array UltraCircuitBuilder::read_ROM_array_pair(const size_t ro * @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 */ -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]; @@ -2280,7 +2310,7 @@ void UltraCircuitBuilder::process_ROM_array(const size_t rom_id) // Make sure that every cell has been initialized for (size_t i = 0; i < rom_array.state.size(); ++i) { if (rom_array.state[i][0] == UNINITIALIZED_MEMORY_RECORD) { - set_ROM_element_pair(rom_id, static_cast(i), { zero_idx, zero_idx }); + set_ROM_element_pair(rom_id, static_cast(i), { this->zero_idx, this->zero_idx }); } } @@ -2292,11 +2322,11 @@ void UltraCircuitBuilder::process_ROM_array(const size_t rom_id) for (const RomRecord& record : rom_array.records) { const auto index = record.index; - const auto value1 = get_variable(record.value_column1_witness); - const auto value2 = get_variable(record.value_column2_witness); - const auto index_witness = add_variable(fr((uint64_t)index)); - const auto value1_witness = add_variable(value1); - const auto value2_witness = add_variable(value2); + const auto value1 = this->get_variable(record.value_column1_witness); + const auto value2 = this->get_variable(record.value_column2_witness); + const auto index_witness = this->add_variable(FF((uint64_t)index)); + const auto value1_witness = this->add_variable(value1); + const auto value2_witness = this->add_variable(value2); RomRecord sorted_record{ .index_witness = index_witness, .value_column1_witness = value1_witness, @@ -2329,14 +2359,14 @@ void UltraCircuitBuilder::process_ROM_array(const size_t rom_id) // If we add a dummy gate at the end of the sorted list, where we force the first wire to // equal `m + 1`, where `m` is the maximum allowed index in the sorted list, // we have validated that all ROM reads are correctly constrained - fr max_index_value((uint64_t)rom_array.state.size()); - uint32_t max_index = add_variable(max_index_value); + FF max_index_value((uint64_t)rom_array.state.size()); + uint32_t max_index = this->add_variable(max_index_value); create_big_add_gate( { max_index, - zero_idx, - zero_idx, - zero_idx, + this->zero_idx, + this->zero_idx, + this->zero_idx, 1, 0, 0, @@ -2354,7 +2384,7 @@ void UltraCircuitBuilder::process_ROM_array(const size_t rom_id) * @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 */ -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; @@ -2368,7 +2398,7 @@ void UltraCircuitBuilder::process_RAM_array(const size_t ram_id) // different public iputs will produce different circuit constraints. for (size_t i = 0; i < ram_array.state.size(); ++i) { if (ram_array.state[i] == UNINITIALIZED_MEMORY_RECORD) { - init_RAM_element(ram_id, static_cast(i), zero_idx); + init_RAM_element(ram_id, static_cast(i), this->zero_idx); } } @@ -2385,10 +2415,10 @@ void UltraCircuitBuilder::process_RAM_array(const size_t ram_id) const RamRecord& record = ram_array.records[i]; const auto index = record.index; - const auto value = get_variable(record.value_witness); - const auto index_witness = add_variable(fr((uint64_t)index)); - const auto timestamp_witess = add_variable(record.timestamp); - const auto value_witness = add_variable(value); + const auto value = this->get_variable(record.value_witness); + const auto index_witness = this->add_variable(FF((uint64_t)index)); + const auto timestamp_witess = this->add_variable(record.timestamp); + const auto value_witness = this->add_variable(value); RamRecord sorted_record{ .index_witness = index_witness, .timestamp_witness = timestamp_witess, @@ -2453,20 +2483,20 @@ void UltraCircuitBuilder::process_RAM_array(const size_t ram_id) const bool share_index = current.index == next.index; - fr timestamp_delta = 0; + FF timestamp_delta = 0; if (share_index) { ASSERT(next.timestamp > current.timestamp); - timestamp_delta = fr(next.timestamp - current.timestamp); + timestamp_delta = FF(next.timestamp - current.timestamp); } - uint32_t timestamp_delta_witness = add_variable(timestamp_delta); + 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(zero_idx); - ++num_gates; + w_4.emplace_back(this->zero_idx); + ++this->num_gates; // store timestamp offsets for later. Need to apply range checks to them, but calling // `create_new_range_constraint` can add gates. Would ruin the structure of our sorted timestamp list. @@ -2479,8 +2509,8 @@ void UltraCircuitBuilder::process_RAM_array(const size_t ram_id) create_big_add_gate({ last.index_witness, last.timestamp_witness, - zero_idx, - zero_idx, + this->zero_idx, + this->zero_idx, 0, 0, 0, @@ -2494,13 +2524,13 @@ void UltraCircuitBuilder::process_RAM_array(const size_t ram_id) } } -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); } } -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); @@ -2574,25 +2604,26 @@ void UltraCircuitBuilder::process_RAM_arrays() * @param alpha * @return fr */ -inline fr UltraCircuitBuilder::compute_arithmetic_identity(fr q_arith_value, - fr q_1_value, - fr q_2_value, - fr q_3_value, - fr q_4_value, - fr q_m_value, - fr q_c_value, - fr w_1_value, - fr w_2_value, - fr w_3_value, - fr w_4_value, - fr w_1_shifted_value, - fr w_4_shifted_value, - fr alpha_base, - fr alpha) const +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 { - constexpr fr neg_half = fr(-2).invert(); + constexpr FF neg_half = FF(-2).invert(); // The main arithmetic identity that gets activated for q_arith_value == 1 - fr arithmetic_identity = w_2_value; + FF arithmetic_identity = w_2_value; arithmetic_identity *= q_m_value; arithmetic_identity *= (q_arith_value - 3); arithmetic_identity *= neg_half; @@ -2604,13 +2635,13 @@ inline fr UltraCircuitBuilder::compute_arithmetic_identity(fr q_arith_value, arithmetic_identity += q_c_value; // The additional small addition identity - fr extra_small_addition_identity = w_1_value + w_4_value - w_1_shifted_value + q_m_value; + FF extra_small_addition_identity = w_1_value + w_4_value - w_1_shifted_value + q_m_value; extra_small_addition_identity *= alpha; extra_small_addition_identity *= (q_arith_value - 2); // The concatenation of small addition identity + shifted w_4 value that can be enabled separately + the main // arithemtic identity - fr final_identity = extra_small_addition_identity + w_4_shifted_value; + FF final_identity = extra_small_addition_identity + w_4_shifted_value; final_identity *= (q_arith_value - 1); final_identity += arithmetic_identity; final_identity *= q_arith_value; @@ -2638,27 +2669,28 @@ inline fr UltraCircuitBuilder::compute_arithmetic_identity(fr q_arith_value, * @param alpha * @return fr */ -inline fr UltraCircuitBuilder::compute_genperm_sort_identity(fr q_sort_value, - fr w_1_value, - fr w_2_value, - fr w_3_value, - fr w_4_value, - fr w_1_shifted_value, - fr alpha_base, - fr alpha) const +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 { // Power of alpha to separate individual delta relations // TODO(kesha): This is a repeated computation which can be efficiently optimized - const fr alpha_a = alpha_base; - const fr alpha_b = alpha_a * alpha; - const fr alpha_c = alpha_b * alpha; - const fr alpha_d = alpha_c * alpha; + const FF alpha_a = alpha_base; + const FF alpha_b = alpha_a * alpha; + const FF alpha_c = alpha_b * alpha; + const FF alpha_d = alpha_c * alpha; // (second - first)*(second - first - 1)*(second - first - 2)*(second - first - 3) - auto neighbour_difference = [](const fr first, const fr second) { - constexpr fr minus_two(-2); - constexpr fr minus_three(-3); - const fr delta = second - first; + auto neighbour_difference = [](const FF first, const FF second) { + constexpr FF minus_two(-2); + constexpr FF minus_three(-3); + const FF delta = second - first; return (delta.sqr() - delta) * (delta + minus_two) * (delta + minus_three); }; @@ -2733,37 +2765,38 @@ inline fr UltraCircuitBuilder::compute_genperm_sort_identity(fr q_sort_value, * @param w_4_shifted_value y₃ * @return fr */ -inline fr UltraCircuitBuilder::compute_elliptic_identity(fr q_elliptic_value, - fr q_1_value, - fr q_3_value, - fr q_4_value, - fr w_2_value, - fr w_3_value, - fr w_1_shifted_value, - fr w_2_shifted_value, - fr w_3_shifted_value, - fr w_4_shifted_value, - fr alpha_base, - fr alpha) const +template +inline FF UltraCircuitBuilder_::compute_elliptic_identity(FF q_elliptic_value, + FF q_1_value, + FF q_3_value, + FF q_4_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 { // TODO(kesha): Can this be implemented more efficiently? // It seems that Zac wanted to group the elements by selectors to use several linear terms initially, // but in the end we are using one, so there is no reason why we can't optimize computation in another way - const fr x_1 = w_2_value; - const fr y_1 = w_3_value; - const fr x_2 = w_1_shifted_value; - const fr y_2 = w_4_shifted_value; - const fr x_3 = w_2_shifted_value; - const fr y_3 = w_3_shifted_value; - const fr q_beta = q_3_value; - const fr q_beta_sqr = q_4_value; - const fr q_sign = q_1_value; - - fr beta_term = -x_2 * x_1 * (x_3 + x_3 + x_1); // -x_1 * x_2 * (2 * x_3 + x_1) - fr beta_sqr_term = x_2.sqr(); // x_2^2 - fr leftovers = beta_sqr_term; // x_2^2 + const FF x_1 = w_2_value; + const FF y_1 = w_3_value; + const FF x_2 = w_1_shifted_value; + const FF y_2 = w_4_shifted_value; + const FF x_3 = w_2_shifted_value; + const FF y_3 = w_3_shifted_value; + const FF q_beta = q_3_value; + const FF q_beta_sqr = q_4_value; + const FF q_sign = q_1_value; + + FF beta_term = -x_2 * x_1 * (x_3 + x_3 + x_1); // -x_1 * x_2 * (2 * x_3 + x_1) + FF beta_sqr_term = x_2.sqr(); // x_2^2 + FF leftovers = beta_sqr_term; // x_2^2 beta_sqr_term *= (x_3 - x_1); // x_2^2 * (x_3 - x_1) - fr sign_term = y_2 * y_1; // y_1 * y_2 + FF sign_term = y_2 * y_1; // y_1 * y_2 sign_term += sign_term; // 2 * y_1 * y_2 beta_term *= q_beta; // -β * x_1 * x_2 * (2 * x_3 + x_1) beta_sqr_term *= q_beta_sqr; // β^2 * x_2^2 * (x_3 - x_1) @@ -2773,7 +2806,7 @@ inline fr UltraCircuitBuilder::compute_elliptic_identity(fr q_elliptic_value, leftovers -= (y_2.sqr() + y_1.sqr()); // x_2^3 + x_1 * (x_3 + x_1) - y_2^2 - y_1^2 // Can be found in class description - fr x_identity = beta_term + beta_sqr_term + sign_term + leftovers; + FF x_identity = beta_term + beta_sqr_term + sign_term + leftovers; x_identity *= alpha_base; beta_term = x_2 * (y_3 + y_1) * q_beta; // β * x_2 * (y_3 + y_1) @@ -2781,7 +2814,7 @@ inline fr UltraCircuitBuilder::compute_elliptic_identity(fr q_elliptic_value, // TODO: remove extra additions if we decide to stay with this implementation leftovers = -x_1 * (y_3 + y_1) + y_1 * (x_1 - x_3); // -x_1 * y_3 - x_1 * y_1 + y_1 * x_1 - y_1 * x_3 - fr y_identity = beta_term + sign_term + leftovers; + FF y_identity = beta_term + sign_term + leftovers; y_identity *= alpha_base * alpha; return q_elliptic_value * (x_identity + y_identity); @@ -2818,29 +2851,30 @@ inline fr UltraCircuitBuilder::compute_elliptic_identity(fr q_elliptic_value, * */ -inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, - fr q_arith_value, - fr q_1_value, - fr q_2_value, - fr q_3_value, - fr q_4_value, - fr q_m_value, - fr q_c_value, - fr w_1_value, - fr w_2_value, - fr w_3_value, - fr w_4_value, - fr w_1_shifted_value, - fr w_2_shifted_value, - fr w_3_shifted_value, - fr w_4_shifted_value, - fr alpha_base, - fr alpha, - fr eta) const +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 { - constexpr barretenberg::fr LIMB_SIZE(uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); + constexpr FF LIMB_SIZE(uint256_t(1) << DEFAULT_NON_NATIVE_FIELD_LIMB_BITS); // TODO(kesha): Replace with a constant defined in header - constexpr barretenberg::fr SUBLIMB_SHIFT(uint256_t(1) << 14); + constexpr FF SUBLIMB_SHIFT(uint256_t(1) << 14); // Non-native field arithmetic gate relations // a{a_0, ..., a_3}⋅b{b_0,...,b_3} + q{q_0,..., q_3}⋅neg_p{neg_p_0,...,neg_p_3} - r{r_0,...,r_3} = 0 mod 2²⁷² @@ -2849,10 +2883,10 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, // For native gate_1: limb_subproduct = a_1 ⋅ b_0 + a_0 ⋅ b_1 // For native gate_2: limb_subproduct = a_0 ⋅ b_2 + a_2 ⋅ b_0 // For native gate_3: limb_subproduct = a_2 ⋅ b_1 + a_1 ⋅ b_2 - fr limb_subproduct = w_1_value * w_2_shifted_value + w_1_shifted_value * w_2_value; + FF limb_subproduct = w_1_value * w_2_shifted_value + w_1_shifted_value * w_2_value; // ( a_0 ⋅ b_3 + a_3 ⋅ b_0 - r_3 ) - fr non_native_field_gate_2 = (w_1_value * w_4_value + w_2_value * w_3_value - w_3_shifted_value); + FF non_native_field_gate_2 = (w_1_value * w_4_value + w_2_value * w_3_value - w_3_shifted_value); // ( a_0 ⋅ b_3 + a_3 ⋅ b_0 - r_3 ) << 68 non_native_field_gate_2 *= LIMB_SIZE; // ( a_0 ⋅ b_3 + a_3 ⋅ b_0 - r_3 ) << 68 - hi_0 @@ -2865,13 +2899,13 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, // ( a_1 ⋅ b_0 + a_0 ⋅ b_1 ) << 68 + ( a_0 ⋅ b_0 ) limb_subproduct += (w_1_shifted_value * w_2_shifted_value); - fr non_native_field_gate_1 = limb_subproduct; + FF non_native_field_gate_1 = limb_subproduct; // ( a_1 ⋅ b_0 + a_0 ⋅ b_1 ) << 68 + ( a_0 ⋅ b_0 ) non_native_field_gate_1 -= (w_3_value + w_4_value); non_native_field_gate_1 *= q_3_value; // ( a_2 ⋅ b_1 + a_1 ⋅ b_2 ) << 68 + ( a_1 ⋅ b_1 ) - fr non_native_field_gate_3 = limb_subproduct; + FF non_native_field_gate_3 = limb_subproduct; // ( a_2 ⋅ b_1 + a_1 ⋅ b_2 ) << 68 + ( a_1 ⋅ b_1 ) + hi_0 non_native_field_gate_3 += w_4_value; // ( a_2 ⋅ b_1 + a_1 ⋅ b_2 ) << 68 + ( a_1 ⋅ b_1 ) + hi_0 - r_2 - hi_1 @@ -2879,7 +2913,7 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, non_native_field_gate_3 *= q_m_value; // Accumulate the 3 gates and multiply by q_2 - fr non_native_field_identity = non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3; + FF non_native_field_identity = non_native_field_gate_1 + non_native_field_gate_2 + non_native_field_gate_3; non_native_field_identity *= q_2_value; // Accummulator limbs. These are activated with (q_3)&( q_4 | q_m). @@ -2888,7 +2922,7 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, // // w_4 == (w_2_shifted << 56) | (w_1_shifted << 42) | (w_3 << 28) | (w_2 << 14) | // w_1 - fr limb_accumulator_1 = w_2_shifted_value; + FF limb_accumulator_1 = w_2_shifted_value; limb_accumulator_1 *= SUBLIMB_SHIFT; limb_accumulator_1 += w_1_shifted_value; limb_accumulator_1 *= SUBLIMB_SHIFT; @@ -2901,7 +2935,7 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, limb_accumulator_1 *= q_4_value; // w_4_shifted == (w_3_shifted << 56) | (w_2_shifted << 42) | (w_1_shifted << 28) | (w_4 << 14) | w_3 - fr limb_accumulator_2 = w_3_shifted_value; + FF limb_accumulator_2 = w_3_shifted_value; limb_accumulator_2 *= SUBLIMB_SHIFT; limb_accumulator_2 += w_2_shifted_value; limb_accumulator_2 *= SUBLIMB_SHIFT; @@ -2913,7 +2947,7 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, limb_accumulator_2 -= w_4_shifted_value; limb_accumulator_2 *= q_m_value; - fr limb_accumulator_identity = limb_accumulator_1 + limb_accumulator_2; + FF limb_accumulator_identity = limb_accumulator_1 + limb_accumulator_2; limb_accumulator_identity *= q_3_value; /** @@ -2959,14 +2993,14 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, * For ROM gates, qc = 0 */ - fr memory_record_check = w_3_value; + FF memory_record_check = w_3_value; memory_record_check *= eta; memory_record_check += w_2_value; memory_record_check *= eta; memory_record_check += w_1_value; memory_record_check *= eta; memory_record_check += q_c_value; - fr partial_record_check = memory_record_check; // used in RAM consistency check + FF partial_record_check = memory_record_check; // used in RAM consistency check memory_record_check = memory_record_check - w_4_value; /** @@ -2983,15 +3017,15 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, * */ - fr index_delta = w_1_shifted_value - w_1_value; - fr record_delta = w_4_shifted_value - w_4_value; + FF index_delta = w_1_shifted_value - w_1_value; + FF record_delta = w_4_shifted_value - w_4_value; // (index_delta - 1) ⋅ (index_delta) - fr index_is_monotonically_increasing = index_delta.sqr() - index_delta; + FF index_is_monotonically_increasing = index_delta.sqr() - index_delta; // (1 - index_delta) ⋅ (record_delta) - fr adjacent_values_match_if_adjacent_indices_match = (fr(1) - index_delta) * record_delta; + FF adjacent_values_match_if_adjacent_indices_match = (FF(1) - index_delta) * record_delta; - fr ROM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match; + FF ROM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match; ROM_consistency_check_identity *= alpha; ROM_consistency_check_identity += index_is_monotonically_increasing; ROM_consistency_check_identity *= alpha; @@ -3017,11 +3051,11 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized * with a WRITE operation. */ - fr access_type = (w_4_value - partial_record_check); // will be 0 or 1 for honest Prover - fr access_check = access_type.sqr() - access_type; // check value is 0 or 1 + FF access_type = (w_4_value - partial_record_check); // will be 0 or 1 for honest Prover + FF access_check = access_type.sqr() - access_type; // check value is 0 or 1 // TODO: oof nasty compute here. If we sorted in reverse order we could re-use `partial_record_check` - fr next_gate_access_type = w_3_shifted_value; + FF next_gate_access_type = w_3_shifted_value; next_gate_access_type *= eta; next_gate_access_type += w_2_shifted_value; next_gate_access_type *= eta; @@ -3029,19 +3063,19 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, next_gate_access_type *= eta; next_gate_access_type = w_4_shifted_value - next_gate_access_type; - fr value_delta = w_3_shifted_value - w_3_value; - fr adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = - (fr(1) - index_delta) * value_delta * (fr(1) - next_gate_access_type); + FF value_delta = w_3_shifted_value - w_3_value; + FF adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = + (FF(1) - index_delta) * value_delta * (FF(1) - next_gate_access_type); // We can't apply the RAM consistency check identity on the final entry in the sorted list (the wires in the // next gate would make the identity fail). // We need to validate that its 'access type' bool is correct. Can't do // with an arithmetic gate because of the `eta` factors. We need to check that the *next* gate's access type is // correct, to cover this edge case - fr next_gate_access_type_is_boolean = next_gate_access_type.sqr() - next_gate_access_type; + FF next_gate_access_type_is_boolean = next_gate_access_type.sqr() - next_gate_access_type; // Putting it all together... - fr RAM_consistency_check_identity = + FF RAM_consistency_check_identity = adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation; RAM_consistency_check_identity *= alpha; RAM_consistency_check_identity += index_is_monotonically_increasing; @@ -3061,21 +3095,21 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, * Iff delta_index == 0, timestamp_check = timestamp_{i + 1} - timestamp_i * Else timestamp_check = 0 */ - fr timestamp_delta = w_2_shifted_value - w_2_value; - fr RAM_timestamp_check_identity = (fr(1) - index_delta) * timestamp_delta - w_3_value; + FF timestamp_delta = w_2_shifted_value - w_2_value; + FF RAM_timestamp_check_identity = (FF(1) - index_delta) * timestamp_delta - w_3_value; /** * The complete RAM/ROM memory identity * */ - fr memory_identity = ROM_consistency_check_identity * q_2_value; + FF memory_identity = ROM_consistency_check_identity * q_2_value; memory_identity += RAM_timestamp_check_identity * q_4_value; memory_identity += memory_record_check * q_m_value; memory_identity *= q_1_value; memory_identity += (RAM_consistency_check_identity * q_arith_value); - fr auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; + FF auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; auxiliary_identity *= q_aux_value; auxiliary_identity *= alpha_base; @@ -3091,7 +3125,7 @@ inline fr UltraCircuitBuilder::compute_auxilary_identity(fr q_aux_value, * @return true * @return false */ -bool UltraCircuitBuilder::check_circuit() +template bool UltraCircuitBuilder_::check_circuit() { bool result = true; CircuitDataBackup circuit_backup = CircuitDataBackup::store_prefinilized_state(this); @@ -3100,12 +3134,12 @@ bool UltraCircuitBuilder::check_circuit() finalize_circuit(); // Sample randomness - const fr arithmetic_base = fr::random_element(); - const fr elliptic_base = fr::random_element(); - const fr genperm_sort_base = fr::random_element(); - const fr auxillary_base = fr::random_element(); - const fr alpha = fr::random_element(); - const fr eta = fr::random_element(); + const FF arithmetic_base = FF::random_element(); + const FF elliptic_base = FF::random_element(); + const FF genperm_sort_base = FF::random_element(); + const FF auxillary_base = FF::random_element(); + const FF alpha = FF::random_element(); + const FF eta = FF::random_element(); // We need to get all memory std::unordered_set memory_read_record_gates; @@ -3119,12 +3153,11 @@ bool UltraCircuitBuilder::check_circuit() // A hashing implementation for quick simulation lookups struct HashFrTuple { - const barretenberg::fr mult_const = barretenberg::fr(uint256_t(0x1337, 0x1336, 0x1335, 0x1334)); - const barretenberg::fr mc_sqr = mult_const.sqr(); - const barretenberg::fr mc_cube = mult_const * mc_sqr; + const FF mult_const = FF(uint256_t(0x1337, 0x1336, 0x1335, 0x1334)); + const FF mc_sqr = mult_const.sqr(); + const FF mc_cube = mult_const * mc_sqr; - size_t operator()( - const std::tuple& entry) const + size_t operator()(const std::tuple& entry) const { return (size_t)((std::get<0>(entry) + mult_const * std::get<1>(entry) + mc_sqr * std::get<2>(entry) + mc_cube * std::get<3>(entry)) @@ -3136,21 +3169,16 @@ bool UltraCircuitBuilder::check_circuit() // Equality checks for lookup tuples struct EqualFrTuple { - bool operator()( - const std::tuple& entry1, - const std::tuple& entry2) const + bool operator()(const std::tuple& entry1, const std::tuple& entry2) const { return entry1 == entry2; } }; // The set of all lookup tuples that are in the tables - std::unordered_set, - HashFrTuple, - EqualFrTuple> - table_hash; + std::unordered_set, HashFrTuple, EqualFrTuple> table_hash; // Prepare the lookup set for use in the circuit for (auto& table : lookup_tables) { - const fr table_index(table.table_index); + const FF table_index(table.table_index); for (size_t i = 0; i < table.size; ++i) { const auto components = std::make_tuple(table.column_1[i], table.column_2[i], table.column_3[i], table_index); @@ -3160,47 +3188,47 @@ bool UltraCircuitBuilder::check_circuit() // We use a running tag product mechanism to ensure tag correctness // This is the product of (value + γ ⋅ tag) - fr left_tag_product = fr::one(); + FF left_tag_product = FF::one(); // This is the product of (value + γ ⋅ tau[tag]) - fr right_tag_product = fr::one(); + FF right_tag_product = FF::one(); // Randomness for the tag check - const fr tag_gamma = fr::random_element(); + const FF tag_gamma = FF::random_element(); // We need to include each variable only once std::unordered_set encountered_variables; // Function to quickly update tag products and encountered variable set by index and value - auto update_tag_check_information = [&](size_t variable_index, fr value) { - size_t real_index = real_variable_index[variable_index]; + auto update_tag_check_information = [&](size_t variable_index, FF value) { + size_t real_index = this->real_variable_index[variable_index]; // Check to ensure that we are not including a variable twice if (encountered_variables.contains(real_index)) { return; } - size_t tag_in = real_variable_tags[real_index]; + size_t tag_in = this->real_variable_tags[real_index]; if (tag_in != DUMMY_TAG) { - size_t tag_out = tau.at((uint32_t)tag_in); - left_tag_product *= value + tag_gamma * fr(tag_in); - right_tag_product *= value + tag_gamma * fr(tag_out); + size_t tag_out = this->tau.at((uint32_t)tag_in); + left_tag_product *= value + tag_gamma * FF(tag_in); + right_tag_product *= value + tag_gamma * FF(tag_out); encountered_variables.insert(real_index); } }; // For each gate - for (size_t i = 0; i < num_gates; i++) { - fr q_arith_value; - fr q_aux_value; - fr q_elliptic_value; - fr q_sort_value; - fr q_lookup_type_value; - fr q_1_value; - fr q_2_value; - fr q_3_value; - fr q_4_value; - fr q_m_value; - fr q_c_value; - fr w_1_value; - fr w_2_value; - fr w_3_value; - fr w_4_value; - fr w_4_index; + for (size_t i = 0; i < this->num_gates; i++) { + FF q_arith_value; + FF q_aux_value; + FF q_elliptic_value; + FF q_sort_value; + FF q_lookup_type_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_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]; @@ -3213,13 +3241,13 @@ bool UltraCircuitBuilder::check_circuit() q_4_value = q_4[i]; q_m_value = q_m[i]; q_c_value = q_c[i]; - w_1_value = get_variable(w_l[i]); + w_1_value = this->get_variable(w_l[i]); update_tag_check_information(w_l[i], w_1_value); - w_2_value = get_variable(w_r[i]); + w_2_value = this->get_variable(w_r[i]); update_tag_check_information(w_r[i], w_2_value); - w_3_value = get_variable(w_o[i]); + w_3_value = this->get_variable(w_o[i]); update_tag_check_information(w_o[i], w_3_value); - w_4_value = get_variable(w_4[i]); + w_4_value = this->get_variable(w_4[i]); // We need to wait before updating tag product for w_4 w_4_index = w_4[i]; @@ -3228,32 +3256,32 @@ bool UltraCircuitBuilder::check_circuit() w_4_value = ((w_3_value * eta + w_2_value) * eta + w_1_value) * eta; } if (memory_write_record_gates.contains(i)) { - w_4_value = ((w_3_value * eta + w_2_value) * eta + w_1_value) * eta + fr::one(); + w_4_value = ((w_3_value * eta + w_2_value) * eta + w_1_value) * eta + FF::one(); } // Now we can update the tag product for w_4 update_tag_check_information((uint32_t)w_4_index, w_4_value); - fr w_1_shifted_value; - fr w_2_shifted_value; - fr w_3_shifted_value; - fr w_4_shifted_value; - if (i < (num_gates - 1)) { - - w_1_shifted_value = get_variable(w_l[i + 1]); - w_2_shifted_value = get_variable(w_r[i + 1]); - w_3_shifted_value = get_variable(w_o[i + 1]); - w_4_shifted_value = get_variable(w_4[i + 1]); + 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(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]); } else { - w_1_shifted_value = fr::zero(); - w_2_shifted_value = fr::zero(); - w_3_shifted_value = fr::zero(); - w_4_shifted_value = fr::zero(); + w_1_shifted_value = FF::zero(); + w_2_shifted_value = FF::zero(); + w_3_shifted_value = FF::zero(); + w_4_shifted_value = FF::zero(); } if (memory_read_record_gates.contains(i + 1)) { w_4_shifted_value = ((w_3_shifted_value * eta + w_2_shifted_value) * eta + w_1_shifted_value) * eta; } if (memory_write_record_gates.contains(i + 1)) { w_4_shifted_value = - ((w_3_shifted_value * eta + w_2_shifted_value) * eta + w_1_shifted_value) * eta + fr::one(); + ((w_3_shifted_value * eta + w_2_shifted_value) * eta + w_1_shifted_value) * eta + FF::one(); } if (!compute_arithmetic_identity(q_arith_value, q_1_value, @@ -3359,5 +3387,5 @@ bool UltraCircuitBuilder::check_circuit() circuit_backup.restore_prefinilized_state(this); return result; } - +template class UltraCircuitBuilder_; } // namespace proof_system \ No newline at end of file diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp b/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp index 47ff143b32..641cc3f4a1 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.hpp @@ -15,7 +15,7 @@ namespace proof_system { using namespace barretenberg; -class UltraCircuitBuilder : public CircuitBuilderBase> { +template class UltraCircuitBuilder_ : public CircuitBuilderBase> { public: static constexpr std::string_view NAME_STRING = "UltraArithmetization"; static constexpr CircuitType CIRCUIT_TYPE = CircuitType::ULTRA; @@ -41,8 +41,8 @@ class UltraCircuitBuilder : public CircuitBuilderBase b; std::array q; std::array r; - std::array neg_modulus; - barretenberg::fr modulus; + std::array neg_modulus; + FF modulus; }; enum AUX_SELECTORS { @@ -181,9 +181,9 @@ class UltraCircuitBuilder : public CircuitBuilderBase a; std::array b; - barretenberg::fr lo_0; - barretenberg::fr hi_0; - barretenberg::fr hi_1; + FF lo_0; + FF hi_0; + FF hi_1; bool operator==(const cached_partial_non_native_field_multiplication& other) const { @@ -234,10 +234,10 @@ class UltraCircuitBuilder : public CircuitBuilderBase>; - using SelectorVector = std::vector>; + using SelectorVector = std::vector>; std::vector public_inputs; - std::vector variables; + 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) @@ -245,7 +245,7 @@ class UltraCircuitBuilder : public CircuitBuilderBase real_variable_index; std::vector real_variable_tags; - std::map constant_variable_indices; + std::map constant_variable_indices; WireVector w_l; WireVector w_r; WireVector w_o; @@ -271,62 +271,61 @@ class UltraCircuitBuilder : public CircuitBuilderBase memory_write_records; std::map range_lists; - std::vector + std::vector cached_partial_non_native_field_multiplications; size_t num_gates; bool circuit_finalised = false; /** - * @brief Stores the state of everything logic-related in the constructor. + * @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 circuit_constructor + * @param builder * @return CircuitDataBackup */ - template - static CircuitDataBackup store_full_state(const CircuitBuilder& circuit_constructor) + template static CircuitDataBackup store_full_state(const CircuitBuilder& builder) { CircuitDataBackup stored_state; - stored_state.public_inputs = circuit_constructor.public_inputs; - stored_state.variables = circuit_constructor.variables; - - stored_state.next_var_index = circuit_constructor.next_var_index; - - stored_state.prev_var_index = circuit_constructor.prev_var_index; - - stored_state.real_variable_index = circuit_constructor.real_variable_index; - stored_state.real_variable_tags = circuit_constructor.real_variable_tags; - stored_state.constant_variable_indices = circuit_constructor.constant_variable_indices; - stored_state.w_l = circuit_constructor.w_l; - stored_state.w_r = circuit_constructor.w_r; - stored_state.w_o = circuit_constructor.w_o; - stored_state.w_4 = circuit_constructor.w_4; - stored_state.q_m = circuit_constructor.q_m; - stored_state.q_c = circuit_constructor.q_c; - stored_state.q_1 = circuit_constructor.q_1; - stored_state.q_2 = circuit_constructor.q_2; - stored_state.q_3 = circuit_constructor.q_3; - stored_state.q_4 = circuit_constructor.q_4; - stored_state.q_arith = circuit_constructor.q_arith; - stored_state.q_sort = circuit_constructor.q_sort; - stored_state.q_elliptic = circuit_constructor.q_elliptic; - stored_state.q_aux = circuit_constructor.q_aux; - stored_state.q_lookup_type = circuit_constructor.q_lookup_type; - stored_state.current_tag = circuit_constructor.current_tag; - stored_state.tau = circuit_constructor.tau; - - stored_state.ram_arrays = circuit_constructor.ram_arrays; - stored_state.rom_arrays = circuit_constructor.rom_arrays; - - stored_state.memory_read_records = circuit_constructor.memory_read_records; - stored_state.memory_write_records = circuit_constructor.memory_write_records; - stored_state.range_lists = circuit_constructor.range_lists; - stored_state.circuit_finalised = circuit_constructor.circuit_finalised; - stored_state.num_gates = circuit_constructor.num_gates; + 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_finalised = builder.circuit_finalised; + stored_state.num_gates = builder.num_gates; stored_state.cached_partial_non_native_field_multiplications = - circuit_constructor.cached_partial_non_native_field_multiplications; + builder.cached_partial_non_native_field_multiplications; return stored_state; } @@ -334,36 +333,36 @@ class UltraCircuitBuilder : public CircuitBuilderBase - static CircuitDataBackup store_prefinilized_state(const CircuitBuilder* circuit_constructor) + static CircuitDataBackup store_prefinilized_state(const CircuitBuilder* builder) { CircuitDataBackup stored_state; - stored_state.public_inputs = circuit_constructor->public_inputs; - stored_state.variables = circuit_constructor->variables; + stored_state.public_inputs = builder->public_inputs; + stored_state.variables = builder->variables; - stored_state.next_var_index = circuit_constructor->next_var_index; + stored_state.next_var_index = builder->next_var_index; - stored_state.prev_var_index = circuit_constructor->prev_var_index; + stored_state.prev_var_index = builder->prev_var_index; - stored_state.real_variable_index = circuit_constructor->real_variable_index; - stored_state.real_variable_tags = circuit_constructor->real_variable_tags; - stored_state.constant_variable_indices = circuit_constructor->constant_variable_indices; - stored_state.current_tag = circuit_constructor->current_tag; - stored_state.tau = circuit_constructor->tau; + 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 = circuit_constructor->ram_arrays; - stored_state.rom_arrays = circuit_constructor->rom_arrays; + stored_state.ram_arrays = builder->ram_arrays; + stored_state.rom_arrays = builder->rom_arrays; - stored_state.memory_read_records = circuit_constructor->memory_read_records; - stored_state.memory_write_records = circuit_constructor->memory_write_records; - stored_state.range_lists = circuit_constructor->range_lists; - stored_state.circuit_finalised = circuit_constructor->circuit_finalised; - stored_state.num_gates = circuit_constructor->num_gates; + 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_finalised = builder->circuit_finalised; + stored_state.num_gates = builder->num_gates; stored_state.cached_partial_non_native_field_multiplications = - circuit_constructor->cached_partial_non_native_field_multiplications; + builder->cached_partial_non_native_field_multiplications; return stored_state; } @@ -371,154 +370,153 @@ class UltraCircuitBuilder : public CircuitBuilderBase void restore_prefinilized_state(CircuitBuilder* circuit_constructor) + template void restore_prefinilized_state(CircuitBuilder* builder) { - circuit_constructor->public_inputs = public_inputs; - circuit_constructor->variables = variables; - - circuit_constructor->next_var_index = next_var_index; - - circuit_constructor->prev_var_index = prev_var_index; - - circuit_constructor->real_variable_index = real_variable_index; - circuit_constructor->real_variable_tags = real_variable_tags; - circuit_constructor->constant_variable_indices = constant_variable_indices; - circuit_constructor->current_tag = current_tag; - circuit_constructor->tau = tau; - - circuit_constructor->ram_arrays = ram_arrays; - circuit_constructor->rom_arrays = rom_arrays; - - circuit_constructor->memory_read_records = memory_read_records; - circuit_constructor->memory_write_records = memory_write_records; - circuit_constructor->range_lists = range_lists; - circuit_constructor->circuit_finalised = circuit_finalised; - circuit_constructor->num_gates = num_gates; - circuit_constructor->cached_partial_non_native_field_multiplications = - cached_partial_non_native_field_multiplications; - circuit_constructor->w_l.resize(num_gates); - circuit_constructor->w_r.resize(num_gates); - circuit_constructor->w_o.resize(num_gates); - circuit_constructor->w_4.resize(num_gates); - circuit_constructor->q_m.resize(num_gates); - circuit_constructor->q_c.resize(num_gates); - circuit_constructor->q_1.resize(num_gates); - circuit_constructor->q_2.resize(num_gates); - circuit_constructor->q_3.resize(num_gates); - circuit_constructor->q_4.resize(num_gates); - circuit_constructor->q_arith.resize(num_gates); - circuit_constructor->q_sort.resize(num_gates); - circuit_constructor->q_elliptic.resize(num_gates); - circuit_constructor->q_aux.resize(num_gates); - circuit_constructor->q_lookup_type.resize(num_gates); + 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_finalised = circuit_finalised; + 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); } /** * @brief Checks that the circuit state is the same as the stored circuit's one * - * @param circuit_constructor + * @param builder * @return true * @return false */ - template bool is_same_state(const CircuitBuilder& circuit_constructor) + template bool is_same_state(const CircuitBuilder& builder) { - if (!(public_inputs == circuit_constructor.public_inputs)) { + if (!(public_inputs == builder.public_inputs)) { return false; } - if (!(variables == circuit_constructor.variables)) { + if (!(variables == builder.variables)) { return false; } - if (!(next_var_index == circuit_constructor.next_var_index)) { + if (!(next_var_index == builder.next_var_index)) { return false; } - if (!(prev_var_index == circuit_constructor.prev_var_index)) { + if (!(prev_var_index == builder.prev_var_index)) { return false; } - if (!(real_variable_index == circuit_constructor.real_variable_index)) { + if (!(real_variable_index == builder.real_variable_index)) { return false; } - if (!(real_variable_tags == circuit_constructor.real_variable_tags)) { + if (!(real_variable_tags == builder.real_variable_tags)) { return false; } - if (!(constant_variable_indices == circuit_constructor.constant_variable_indices)) { + if (!(constant_variable_indices == builder.constant_variable_indices)) { return false; } - if (!(w_l == circuit_constructor.w_l)) { + if (!(w_l == builder.w_l)) { return false; } - if (!(w_r == circuit_constructor.w_r)) { + if (!(w_r == builder.w_r)) { return false; } - if (!(w_o == circuit_constructor.w_o)) { + if (!(w_o == builder.w_o)) { return false; } - if (!(w_4 == circuit_constructor.w_4)) { + if (!(w_4 == builder.w_4)) { return false; } - if (!(q_m == circuit_constructor.q_m)) { + if (!(q_m == builder.q_m)) { return false; } - if (!(q_c == circuit_constructor.q_c)) { + if (!(q_c == builder.q_c)) { return false; } - if (!(q_1 == circuit_constructor.q_1)) { + if (!(q_1 == builder.q_1)) { return false; } - if (!(q_2 == circuit_constructor.q_2)) { + if (!(q_2 == builder.q_2)) { return false; } - if (!(q_3 == circuit_constructor.q_3)) { + if (!(q_3 == builder.q_3)) { return false; } - if (!(q_4 == circuit_constructor.q_4)) { + if (!(q_4 == builder.q_4)) { return false; } - if (!(q_arith == circuit_constructor.q_arith)) { + if (!(q_arith == builder.q_arith)) { return false; } - if (!(q_sort == circuit_constructor.q_sort)) { + if (!(q_sort == builder.q_sort)) { return false; } - if (!(q_elliptic == circuit_constructor.q_elliptic)) { + if (!(q_elliptic == builder.q_elliptic)) { return false; } - if (!(q_aux == circuit_constructor.q_aux)) { + if (!(q_aux == builder.q_aux)) { return false; } - if (!(q_lookup_type == circuit_constructor.q_lookup_type)) { + if (!(q_lookup_type == builder.q_lookup_type)) { return false; } - if (!(current_tag == circuit_constructor.current_tag)) { + if (!(current_tag == builder.current_tag)) { return false; } - if (!(tau == circuit_constructor.tau)) { + if (!(tau == builder.tau)) { return false; } - if (!(ram_arrays == circuit_constructor.ram_arrays)) { + if (!(ram_arrays == builder.ram_arrays)) { return false; } - if (!(rom_arrays == circuit_constructor.rom_arrays)) { + if (!(rom_arrays == builder.rom_arrays)) { return false; } - if (!(memory_read_records == circuit_constructor.memory_read_records)) { + if (!(memory_read_records == builder.memory_read_records)) { return false; } - if (!(memory_write_records == circuit_constructor.memory_write_records)) { + if (!(memory_write_records == builder.memory_write_records)) { return false; } - if (!(range_lists == circuit_constructor.range_lists)) { + if (!(range_lists == builder.range_lists)) { return false; } if (!(cached_partial_non_native_field_multiplications == - circuit_constructor.cached_partial_non_native_field_multiplications)) { + builder.cached_partial_non_native_field_multiplications)) { return false; } - if (!(num_gates == circuit_constructor.num_gates)) { + if (!(num_gates == builder.num_gates)) { return false; } - if (!(circuit_finalised == circuit_constructor.circuit_finalised)) { + if (!(circuit_finalised == builder.circuit_finalised)) { return false; } return true; @@ -526,29 +524,29 @@ class UltraCircuitBuilder : public CircuitBuilderBase>; - using SelectorVector = std::vector>; - - 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; + 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; // These are variables that we have used a gate on, to enforce that they are // equal to a defined value. // TODO(#216)(Adrian): Why is this not in CircuitBuilderBase - std::map constant_variable_indices; + std::map constant_variable_indices; std::vector lookup_tables; std::vector lookup_multi_tables; @@ -581,19 +579,19 @@ class UltraCircuitBuilder : public CircuitBuilderBase>(ultra_selector_names(), size_hint) { w_l.reserve(size_hint); w_r.reserve(size_hint); w_o.reserve(size_hint); w_4.reserve(size_hint); - zero_idx = put_constant_variable(barretenberg::fr::zero()); - tau.insert({ DUMMY_TAG, DUMMY_TAG }); // TODO(luke): explain this + this->zero_idx = put_constant_variable(FF::zero()); + this->tau.insert({ DUMMY_TAG, DUMMY_TAG }); // TODO(luke): explain this }; - UltraCircuitBuilder(const UltraCircuitBuilder& other) = delete; - UltraCircuitBuilder(UltraCircuitBuilder&& other) - : CircuitBuilderBase>(std::move(other)) + UltraCircuitBuilder_(const UltraCircuitBuilder_& other) = delete; + UltraCircuitBuilder_(UltraCircuitBuilder_&& other) + : CircuitBuilderBase>(std::move(other)) { constant_variable_indices = other.constant_variable_indices; @@ -607,10 +605,10 @@ class UltraCircuitBuilder : public CircuitBuilderBase>::operator=(std::move(other)); + CircuitBuilderBase>::operator=(std::move(other)); constant_variable_indices = other.constant_variable_indices; lookup_tables = other.lookup_tables; @@ -624,7 +622,7 @@ class UltraCircuitBuilder : public CircuitBuilderBasenum_gates; // each ROM gate adds +1 extra gate due to the rom reads being copied to a sorted list set for (size_t i = 0; i < rom_arrays.size(); ++i) { for (size_t j = 0; j < rom_arrays[i].state.size(); ++j) { @@ -721,7 +719,7 @@ 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; @@ -798,7 +796,7 @@ class UltraCircuitBuilder : public CircuitBuilderBasenum_gates; } size_t count = 0; size_t rangecount = 0; @@ -828,11 +826,11 @@ class UltraCircuitBuilder : public CircuitBuilderBasepublic_inputs.size(); return std::max(minimum_circuit_size, num_filled_gates); } - /** + /**x * @brief Print the number and composition of gates in the circuit * */ @@ -848,7 +846,7 @@ class UltraCircuitBuilder : public CircuitBuilderBasevariables[a_idx] != b && !this->failed()) { + this->failure(msg); } auto b_idx = put_constant_variable(b); - assert_equal(a_idx, b_idx, msg); + this->assert_equal(a_idx, b_idx, msg); } /** * Plookup Methods **/ void add_table_column_selector_poly_to_proving_key(barretenberg::polynomial& small, const std::string& tag); - void initialize_precomputed_table( - const plookup::BasicTableId id, - bool (*generator)(std::vector&, - std::vector&, - std::vector&), - std::array (*get_values_from_key)(const std::array)); + void initialize_precomputed_table(const plookup::BasicTableId id, + bool (*generator)(std::vector&, std::vector&, std::vector&), + std::array (*get_values_from_key)(const std::array)); plookup::BasicTable& get_table(const plookup::BasicTableId id); plookup::MultiTable& create_table(const plookup::MultiTableId id); plookup::ReadData create_gates_from_plookup_accumulators( const plookup::MultiTableId& id, - const plookup::ReadData& read_values, + const plookup::ReadData& read_values, const uint32_t key_a_index, std::optional key_b_index = std::nullopt); @@ -1030,31 +1023,29 @@ class UltraCircuitBuilder : public CircuitBuilderBase& variable_index); void create_sort_constraint(const std::vector& variable_index); - void create_sort_constraint_with_edges(const std::vector& variable_index, - const barretenberg::fr&, - const barretenberg::fr&); + void create_sort_constraint_with_edges(const std::vector& variable_index, const FF&, const FF&); void assign_tag(const uint32_t variable_index, const uint32_t tag) { - ASSERT(tag <= current_tag); + ASSERT(tag <= this->current_tag); // If we've already assigned this tag to this variable, return (can happen due to copy constraints) - if (real_variable_tags[real_variable_index[variable_index]] == tag) { + if (this->real_variable_tags[this->real_variable_index[variable_index]] == tag) { return; } - ASSERT(real_variable_tags[real_variable_index[variable_index]] == DUMMY_TAG); - real_variable_tags[real_variable_index[variable_index]] = tag; + ASSERT(this->real_variable_tags[this->real_variable_index[variable_index]] == DUMMY_TAG); + this->real_variable_tags[this->real_variable_index[variable_index]] = tag; } uint32_t create_tag(const uint32_t tag_index, const uint32_t tau_index) { - tau.insert({ tag_index, tau_index }); - current_tag++; // Why exactly? - return current_tag; + this->tau.insert({ tag_index, tau_index }); + this->current_tag++; // Why exactly? + return this->current_tag; } uint32_t get_new_tag() { - current_tag++; - return current_tag; + this->current_tag++; + return this->current_tag; } RangeList create_range_list(const uint64_t target_range); @@ -1078,19 +1069,18 @@ class UltraCircuitBuilder : public CircuitBuilderBase evaluate_non_native_field_multiplication( const non_native_field_witnesses& input, const bool range_constrain_quotient_and_remainder = true); std::array queue_partial_non_native_field_multiplication(const non_native_field_witnesses& input); - typedef std::pair scaled_witness; - typedef std::tuple add_simple; - std::array evaluate_non_native_field_subtraction( - add_simple limb0, - add_simple limb1, - add_simple limb2, - add_simple limb3, - std::tuple limbp); + typedef std::pair scaled_witness; + typedef std::tuple add_simple; + std::array evaluate_non_native_field_subtraction(add_simple limb0, + add_simple limb1, + add_simple limb2, + add_simple limb3, + std::tuple limbp); std::array evaluate_non_native_field_addition(add_simple limb0, add_simple limb1, add_simple limb2, add_simple limb3, - std::tuple limbp); + std::tuple limbp); /** * Memory @@ -1123,61 +1113,63 @@ class UltraCircuitBuilder : public CircuitBuilderBase; +using UltraCircuitBuilder = UltraCircuitBuilder_; } // namespace proof_system diff --git a/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp b/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp index ecbf2231b0..d994c0b923 100644 --- a/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp +++ b/cpp/src/barretenberg/proof_system/circuit_builder/ultra_circuit_builder.test.cpp @@ -15,7 +15,7 @@ TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) { UltraCircuitBuilder circuit_constructor = UltraCircuitBuilder(); - barretenberg::fr input_value = fr::random_element(); + fr input_value = fr::random_element(); const fr input_hi = uint256_t(input_value).slice(126, 256); const fr input_lo = uint256_t(input_value).slice(0, 126); const auto input_hi_index = circuit_constructor.add_variable(input_hi); @@ -29,8 +29,8 @@ TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) const auto lookup_witnesses_lo = circuit_constructor.create_gates_from_plookup_accumulators( MultiTableId::PEDERSEN_LEFT_LO, sequence_data_lo, input_lo_index); - std::vector expected_x; - std::vector expected_y; + std::vector expected_x; + std::vector expected_y; const size_t num_lookups_hi = (128 + crypto::pedersen_hash::lookup::BITS_PER_TABLE) / crypto::pedersen_hash::lookup::BITS_PER_TABLE; @@ -40,7 +40,7 @@ TEST(ultra_circuit_constructor, create_gates_from_plookup_accumulators) EXPECT_EQ(num_lookups_hi, lookup_witnesses_hi[ColumnIdx::C1].size()); EXPECT_EQ(num_lookups_lo, lookup_witnesses_lo[ColumnIdx::C1].size()); - std::vector expected_scalars; + std::vector expected_scalars; expected_x.resize(num_lookups); expected_y.resize(num_lookups); expected_scalars.resize(num_lookups); diff --git a/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp b/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp index 0c6579ae70..7db8a2ab0b 100644 --- a/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp +++ b/cpp/src/barretenberg/stdlib/primitives/circuit_builders/circuit_builders_fwd.hpp @@ -1,5 +1,5 @@ /** - * @brief Defines particular composer and circuit constructor types expected to be used for proof or circuit + * @brief Defines particular composer and circuit builder types expected to be used for proof or circuit construction in stdlib and contains macros for explicit instantiation. * * @details This file is designed to be included in header files to instruct the compiler that these classes exist and @@ -16,10 +16,17 @@ class Ultra; } // namespace flavor } // namespace proof_system::honk +namespace barretenberg { +class Bn254FrParams; +template struct alignas(32) field; +} // namespace barretenberg namespace proof_system { -class StandardCircuitBuilder; -class TurboCircuitBuilder; -class UltraCircuitBuilder; +template class StandardCircuitBuilder_; +using StandardCircuitBuilder = StandardCircuitBuilder_>; +template class TurboCircuitBuilder_; +using TurboCircuitBuilder = TurboCircuitBuilder_>; +template class UltraCircuitBuilder_; +using UltraCircuitBuilder = UltraCircuitBuilder_>; } // namespace proof_system #define EXTERN_STDLIB_TYPE(stdlib_type) \