diff --git a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp index c3dbe4cb464..96154837399 100644 --- a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.cpp @@ -10,9 +10,7 @@ namespace proof_system::honk { * @tparam Flavor * @param circuit */ -template -void ProverInstance_::compute_circuit_size_parameters(Circuit& circuit) - requires IsUltraFlavor +template void ProverInstance_::compute_circuit_size_parameters(Circuit& circuit) { // Compute total length of the tables and the number of lookup gates; their sum is the minimum circuit size for (const auto& table : circuit.lookup_tables) { @@ -58,101 +56,98 @@ template void ProverInstance_::compute_witness(Circuit& c proving_key->w_l = wire_polynomials[0]; proving_key->w_r = wire_polynomials[1]; proving_key->w_o = wire_polynomials[2]; + proving_key->w_4 = wire_polynomials[3]; - if constexpr (IsUltraFlavor) { - proving_key->w_4 = wire_polynomials[3]; - - // If Goblin, construct the ECC op queue wire polynomials - if constexpr (IsGoblinFlavor) { - construct_ecc_op_wire_polynomials(wire_polynomials); - } + // If Goblin, construct the ECC op queue wire polynomials + if constexpr (IsGoblinFlavor) { + construct_ecc_op_wire_polynomials(wire_polynomials); + } - // Construct the sorted concatenated list polynomials for the lookup argument - polynomial s_1(dyadic_circuit_size); - polynomial s_2(dyadic_circuit_size); - polynomial s_3(dyadic_circuit_size); - polynomial s_4(dyadic_circuit_size); - - // The sorted list polynomials have (tables_size + lookups_size) populated entries. We define the index below so - // that these entries are written into the last indices of the polynomials. The values on the first - // dyadic_circuit_size - (tables_size + lookups_size) indices are automatically initialized to zero via the - // polynomial constructor. - size_t s_index = dyadic_circuit_size - tables_size - lookups_size; - ASSERT(s_index > 0); // We need at least 1 row of zeroes for the permutation argument - - for (auto& table : circuit.lookup_tables) { - const fr table_index(table.table_index); - auto& lookup_gates = table.lookup_gates; - for (size_t i = 0; i < table.size; ++i) { - if (table.use_twin_keys) { - lookup_gates.push_back({ - { - table.column_1[i].from_montgomery_form().data[0], - table.column_2[i].from_montgomery_form().data[0], - }, - { - table.column_3[i], - 0, - }, - }); - } else { - lookup_gates.push_back({ - { - table.column_1[i].from_montgomery_form().data[0], - 0, - }, - { - table.column_2[i], - table.column_3[i], - }, - }); - } + // Construct the sorted concatenated list polynomials for the lookup argument + polynomial s_1(dyadic_circuit_size); + polynomial s_2(dyadic_circuit_size); + polynomial s_3(dyadic_circuit_size); + polynomial s_4(dyadic_circuit_size); + + // The sorted list polynomials have (tables_size + lookups_size) populated entries. We define the index below so + // that these entries are written into the last indices of the polynomials. The values on the first + // dyadic_circuit_size - (tables_size + lookups_size) indices are automatically initialized to zero via the + // polynomial constructor. + size_t s_index = dyadic_circuit_size - tables_size - lookups_size; + ASSERT(s_index > 0); // We need at least 1 row of zeroes for the permutation argument + + for (auto& table : circuit.lookup_tables) { + const fr table_index(table.table_index); + auto& lookup_gates = table.lookup_gates; + for (size_t i = 0; i < table.size; ++i) { + if (table.use_twin_keys) { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + table.column_2[i].from_montgomery_form().data[0], + }, + { + table.column_3[i], + 0, + }, + }); + } else { + lookup_gates.push_back({ + { + table.column_1[i].from_montgomery_form().data[0], + 0, + }, + { + table.column_2[i], + table.column_3[i], + }, + }); } + } #ifdef NO_TBB - std::sort(lookup_gates.begin(), lookup_gates.end()); + std::sort(lookup_gates.begin(), lookup_gates.end()); #else - std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); + std::sort(std::execution::par_unseq, lookup_gates.begin(), lookup_gates.end()); #endif - for (const auto& entry : lookup_gates) { - const auto components = entry.to_sorted_list_components(table.use_twin_keys); - s_1[s_index] = components[0]; - s_2[s_index] = components[1]; - s_3[s_index] = components[2]; - s_4[s_index] = table_index; - ++s_index; - } + for (const auto& entry : lookup_gates) { + const auto components = entry.to_sorted_list_components(table.use_twin_keys); + s_1[s_index] = components[0]; + s_2[s_index] = components[1]; + s_3[s_index] = components[2]; + s_4[s_index] = table_index; + ++s_index; } - - // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing - // space - proving_key->sorted_1 = s_1; - proving_key->sorted_2 = s_2; - proving_key->sorted_3 = s_3; - proving_key->sorted_4 = s_4; - - // Copy memory read/write record data into proving key. Prover needs to know which gates contain a read/write - // 'record' witness on the 4th wire. This wire value can only be fully computed once the first 3 wire - // polynomials have been committed to. The 4th wire on these gates will be a random linear combination of the - // first 3 wires, using the plookup challenge `eta`. We need to update the records with an offset Because we - // shift the gates to account for everything that comes before them in the execution trace, e.g. public inputs, - // a zero row, etc. - size_t offset = num_ecc_op_gates + num_public_inputs + num_zero_rows; - auto add_public_inputs_offset = [offset](uint32_t gate_index) { return gate_index + offset; }; - proving_key->memory_read_records = std::vector(); - proving_key->memory_write_records = std::vector(); - - std::transform(circuit.memory_read_records.begin(), - circuit.memory_read_records.end(), - std::back_inserter(proving_key->memory_read_records), - add_public_inputs_offset); - std::transform(circuit.memory_write_records.begin(), - circuit.memory_write_records.end(), - std::back_inserter(proving_key->memory_write_records), - add_public_inputs_offset); } + // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing + // space + proving_key->sorted_1 = s_1; + proving_key->sorted_2 = s_2; + proving_key->sorted_3 = s_3; + proving_key->sorted_4 = s_4; + + // Copy memory read/write record data into proving key. Prover needs to know which gates contain a read/write + // 'record' witness on the 4th wire. This wire value can only be fully computed once the first 3 wire + // polynomials have been committed to. The 4th wire on these gates will be a random linear combination of the + // first 3 wires, using the plookup challenge `eta`. We need to update the records with an offset Because we + // shift the gates to account for everything that comes before them in the execution trace, e.g. public inputs, + // a zero row, etc. + size_t offset = num_ecc_op_gates + num_public_inputs + num_zero_rows; + auto add_public_inputs_offset = [offset](uint32_t gate_index) { return gate_index + offset; }; + proving_key->memory_read_records = std::vector(); + proving_key->memory_write_records = std::vector(); + + std::transform(circuit.memory_read_records.begin(), + circuit.memory_read_records.end(), + std::back_inserter(proving_key->memory_read_records), + add_public_inputs_offset); + std::transform(circuit.memory_write_records.begin(), + circuit.memory_write_records.end(), + std::back_inserter(proving_key->memory_write_records), + add_public_inputs_offset); + computed_witness = true; } @@ -164,9 +159,7 @@ template void ProverInstance_::compute_witness(Circuit& c * @tparam Flavor * @param wire_polynomials */ -template -void ProverInstance_::construct_ecc_op_wire_polynomials(auto& wire_polynomials) - requires IsUltraFlavor +template void ProverInstance_::construct_ecc_op_wire_polynomials(auto& wire_polynomials) { std::array op_wire_polynomials; for (auto& poly : op_wire_polynomials) { @@ -200,64 +193,63 @@ std::shared_ptr ProverInstance_::compute_pr // Compute lagrange selectors proving_key = std::make_shared(dyadic_circuit_size, num_public_inputs); - construct_selector_polynomials(circuit, proving_key.get()); - if constexpr (IsUltraFlavor) { + construct_selector_polynomials(circuit, proving_key.get()); - compute_honk_generalized_sigma_permutations(circuit, proving_key.get()); - compute_first_and_last_lagrange_polynomials(proving_key.get()); + compute_honk_generalized_sigma_permutations(circuit, proving_key.get()); - polynomial poly_q_table_column_1(dyadic_circuit_size); - polynomial poly_q_table_column_2(dyadic_circuit_size); - polynomial poly_q_table_column_3(dyadic_circuit_size); - polynomial poly_q_table_column_4(dyadic_circuit_size); + compute_first_and_last_lagrange_polynomials(proving_key.get()); - size_t offset = dyadic_circuit_size - tables_size; + polynomial poly_q_table_column_1(dyadic_circuit_size); + polynomial poly_q_table_column_2(dyadic_circuit_size); + polynomial poly_q_table_column_3(dyadic_circuit_size); + polynomial poly_q_table_column_4(dyadic_circuit_size); - // Create lookup selector polynomials which interpolate each table column. - // Our selector polys always need to interpolate the full subgroup size, so here we offset so as to - // put the table column's values at the end. (The first gates are for non-lookup constraints). - // [0, ..., 0, ...table, 0, 0, 0, x] - // ^^^^^^^^^ ^^^^^^^^ ^^^^^^^ ^nonzero to ensure uniqueness and to avoid infinity commitments - // | table randomness - // ignored, as used for regular constraints and padding to the next power of 2. + size_t offset = dyadic_circuit_size - tables_size; - for (size_t i = 0; i < offset; ++i) { - poly_q_table_column_1[i] = 0; - poly_q_table_column_2[i] = 0; - poly_q_table_column_3[i] = 0; - poly_q_table_column_4[i] = 0; - } + // Create lookup selector polynomials which interpolate each table column. + // Our selector polys always need to interpolate the full subgroup size, so here we offset so as to + // put the table column's values at the end. (The first gates are for non-lookup constraints). + // [0, ..., 0, ...table, 0, 0, 0, x] + // ^^^^^^^^^ ^^^^^^^^ ^^^^^^^ ^nonzero to ensure uniqueness and to avoid infinity commitments + // | table randomness + // ignored, as used for regular constraints and padding to the next power of 2. - for (const auto& table : circuit.lookup_tables) { - const fr table_index(table.table_index); + for (size_t i = 0; i < offset; ++i) { + poly_q_table_column_1[i] = 0; + poly_q_table_column_2[i] = 0; + poly_q_table_column_3[i] = 0; + poly_q_table_column_4[i] = 0; + } - for (size_t i = 0; i < table.size; ++i) { - poly_q_table_column_1[offset] = table.column_1[i]; - poly_q_table_column_2[offset] = table.column_2[i]; - poly_q_table_column_3[offset] = table.column_3[i]; - poly_q_table_column_4[offset] = table_index; - ++offset; - } + for (const auto& table : circuit.lookup_tables) { + const fr table_index(table.table_index); + + for (size_t i = 0; i < table.size; ++i) { + poly_q_table_column_1[offset] = table.column_1[i]; + poly_q_table_column_2[offset] = table.column_2[i]; + poly_q_table_column_3[offset] = table.column_3[i]; + poly_q_table_column_4[offset] = table_index; + ++offset; } + } - // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing - // space + // Polynomial memory is zeroed out when constructed with size hint, so we don't have to initialize trailing + // space - proving_key->table_1 = poly_q_table_column_1; - proving_key->table_2 = poly_q_table_column_2; - proving_key->table_3 = poly_q_table_column_3; - proving_key->table_4 = poly_q_table_column_4; + proving_key->table_1 = poly_q_table_column_1; + proving_key->table_2 = poly_q_table_column_2; + proving_key->table_3 = poly_q_table_column_3; + proving_key->table_4 = poly_q_table_column_4; - proving_key->recursive_proof_public_input_indices = std::vector( - recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); + proving_key->recursive_proof_public_input_indices = + std::vector(recursive_proof_public_input_indices.begin(), recursive_proof_public_input_indices.end()); - proving_key->contains_recursive_proof = contains_recursive_proof; + proving_key->contains_recursive_proof = contains_recursive_proof; - if constexpr (IsGoblinFlavor) { - proving_key->num_ecc_op_gates = num_ecc_op_gates; - proving_key->op_queue = circuit.op_queue; - } + if constexpr (IsGoblinFlavor) { + proving_key->num_ecc_op_gates = num_ecc_op_gates; + proving_key->op_queue = circuit.op_queue; } return proving_key; @@ -282,27 +274,25 @@ template void ProverInstance_::initialise_prover_polynomi prover_polynomials.w_r = proving_key->w_r; prover_polynomials.w_o = proving_key->w_o; - if constexpr (IsUltraFlavor) { - prover_polynomials.q_4 = proving_key->q_4; - prover_polynomials.q_arith = proving_key->q_arith; - prover_polynomials.q_sort = proving_key->q_sort; - prover_polynomials.q_elliptic = proving_key->q_elliptic; - prover_polynomials.q_aux = proving_key->q_aux; - prover_polynomials.q_lookup = proving_key->q_lookup; - prover_polynomials.sigma_4 = proving_key->sigma_4; - prover_polynomials.id_4 = proving_key->id_4; - prover_polynomials.table_1 = proving_key->table_1; - prover_polynomials.table_2 = proving_key->table_2; - prover_polynomials.table_3 = proving_key->table_3; - prover_polynomials.table_4 = proving_key->table_4; - prover_polynomials.table_1_shift = proving_key->table_1.shifted(); - prover_polynomials.table_2_shift = proving_key->table_2.shifted(); - prover_polynomials.table_3_shift = proving_key->table_3.shifted(); - prover_polynomials.table_4_shift = proving_key->table_4.shifted(); - prover_polynomials.w_l_shift = proving_key->w_l.shifted(); - prover_polynomials.w_r_shift = proving_key->w_r.shifted(); - prover_polynomials.w_o_shift = proving_key->w_o.shifted(); - } + prover_polynomials.q_4 = proving_key->q_4; + prover_polynomials.q_arith = proving_key->q_arith; + prover_polynomials.q_sort = proving_key->q_sort; + prover_polynomials.q_elliptic = proving_key->q_elliptic; + prover_polynomials.q_aux = proving_key->q_aux; + prover_polynomials.q_lookup = proving_key->q_lookup; + prover_polynomials.sigma_4 = proving_key->sigma_4; + prover_polynomials.id_4 = proving_key->id_4; + prover_polynomials.table_1 = proving_key->table_1; + prover_polynomials.table_2 = proving_key->table_2; + prover_polynomials.table_3 = proving_key->table_3; + prover_polynomials.table_4 = proving_key->table_4; + prover_polynomials.table_1_shift = proving_key->table_1.shifted(); + prover_polynomials.table_2_shift = proving_key->table_2.shifted(); + prover_polynomials.table_3_shift = proving_key->table_3.shifted(); + prover_polynomials.table_4_shift = proving_key->table_4.shifted(); + prover_polynomials.w_l_shift = proving_key->w_l.shifted(); + prover_polynomials.w_r_shift = proving_key->w_r.shifted(); + prover_polynomials.w_o_shift = proving_key->w_o.shifted(); if constexpr (IsGoblinFlavor) { prover_polynomials.ecc_op_wire_1 = proving_key->ecc_op_wire_1; @@ -315,26 +305,18 @@ template void ProverInstance_::initialise_prover_polynomi std::span public_wires_source = prover_polynomials.w_r; // Determine public input offsets in the circuit relative to the 0th index for Ultra flavors - if constexpr (IsUltraFlavor) { - pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; - if constexpr (IsGoblinFlavor) { - pub_inputs_offset += proving_key->num_ecc_op_gates; - } - // Construct the public inputs array - for (size_t i = 0; i < proving_key->num_public_inputs; ++i) { - size_t idx = i + pub_inputs_offset; - public_inputs.emplace_back(public_wires_source[idx]); - } - } else { - for (size_t i = 0; i < proving_key->num_public_inputs; ++i) { - public_inputs.emplace_back(public_wires_source[i]); - } + pub_inputs_offset = Flavor::has_zero_row ? 1 : 0; + if constexpr (IsGoblinFlavor) { + pub_inputs_offset += proving_key->num_ecc_op_gates; + } + // Construct the public inputs array + for (size_t i = 0; i < proving_key->num_public_inputs; ++i) { + size_t idx = i + pub_inputs_offset; + public_inputs.emplace_back(public_wires_source[idx]); } } -template -void ProverInstance_::compute_sorted_accumulator_polynomials(FF eta) - requires IsUltraFlavor +template void ProverInstance_::compute_sorted_accumulator_polynomials(FF eta) { relation_parameters.eta = eta; // Compute sorted witness-table accumulator @@ -359,9 +341,7 @@ void ProverInstance_::compute_sorted_accumulator_polynomials(FF eta) * @param eta random challenge * @return Polynomial */ -template -void ProverInstance_::compute_sorted_list_accumulator(FF eta) - requires IsUltraFlavor +template void ProverInstance_::compute_sorted_list_accumulator(FF eta) { const size_t circuit_size = proving_key->circuit_size; @@ -392,9 +372,7 @@ void ProverInstance_::compute_sorted_list_accumulator(FF eta) * @tparam Flavor * @param eta challenge produced after commitment to first three wire polynomials */ -template -void ProverInstance_::add_plookup_memory_records_to_wire_4(FF eta) - requires IsUltraFlavor +template void ProverInstance_::add_plookup_memory_records_to_wire_4(FF eta) { // The plookup memory record values are computed at the indicated indices as // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; @@ -432,10 +410,8 @@ template void ProverInstance_::compute_grand_product_poly relation_parameters.gamma = gamma; relation_parameters.public_input_delta = public_input_delta; - if constexpr (IsUltraFlavor) { - auto lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, proving_key->circuit_size); - relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; - } + auto lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, proving_key->circuit_size); + relation_parameters.lookup_grand_product_delta = lookup_grand_product_delta; // Compute permutation and lookup grand product polynomials grand_product_library::compute_grand_products(proving_key, prover_polynomials, relation_parameters); @@ -471,33 +447,32 @@ std::shared_ptr ProverInstance_::compu verification_key->lagrange_first = commitment_key->commit(proving_key->lagrange_first); verification_key->lagrange_last = commitment_key->commit(proving_key->lagrange_last); - if constexpr (IsUltraFlavor) { - verification_key->q_4 = commitment_key->commit(proving_key->q_4); - verification_key->q_arith = commitment_key->commit(proving_key->q_arith); - verification_key->q_sort = commitment_key->commit(proving_key->q_sort); - verification_key->q_elliptic = commitment_key->commit(proving_key->q_elliptic); - verification_key->q_aux = commitment_key->commit(proving_key->q_aux); - verification_key->q_lookup = commitment_key->commit(proving_key->q_lookup); - verification_key->sigma_4 = commitment_key->commit(proving_key->sigma_4); - verification_key->id_4 = commitment_key->commit(proving_key->id_4); - verification_key->table_1 = commitment_key->commit(proving_key->table_1); - verification_key->table_2 = commitment_key->commit(proving_key->table_2); - verification_key->table_3 = commitment_key->commit(proving_key->table_3); - verification_key->table_4 = commitment_key->commit(proving_key->table_4); - - // TODO(luke): Similar to the lagrange_first/last polynomials, we dont really need to commit to this polynomial - // due to its simple structure. Handling it in the same way as the lagrange polys for now for simplicity. - if constexpr (IsGoblinFlavor) { - verification_key->lagrange_ecc_op = commitment_key->commit(proving_key->lagrange_ecc_op); - } + verification_key->q_4 = commitment_key->commit(proving_key->q_4); + verification_key->q_arith = commitment_key->commit(proving_key->q_arith); + verification_key->q_sort = commitment_key->commit(proving_key->q_sort); + verification_key->q_elliptic = commitment_key->commit(proving_key->q_elliptic); + verification_key->q_aux = commitment_key->commit(proving_key->q_aux); + verification_key->q_lookup = commitment_key->commit(proving_key->q_lookup); + verification_key->sigma_4 = commitment_key->commit(proving_key->sigma_4); + verification_key->id_4 = commitment_key->commit(proving_key->id_4); + verification_key->table_1 = commitment_key->commit(proving_key->table_1); + verification_key->table_2 = commitment_key->commit(proving_key->table_2); + verification_key->table_3 = commitment_key->commit(proving_key->table_3); + verification_key->table_4 = commitment_key->commit(proving_key->table_4); + + // TODO(luke): Similar to the lagrange_first/last polynomials, we dont really need to commit to this polynomial + // due to its simple structure. Handling it in the same way as the lagrange polys for now for simplicity. + if constexpr (IsGoblinFlavor) { + verification_key->lagrange_ecc_op = commitment_key->commit(proving_key->lagrange_ecc_op); + } - // // See `add_recusrive_proof()` for how this recursive data is assigned. - // verification_key->recursive_proof_public_input_indices = - // std::vector(recursive_proof_public_input_indices.begin(), - // recursive_proof_public_input_indices.end()); + // // See `add_recusrive_proof()` for how this recursive data is assigned. + // verification_key->recursive_proof_public_input_indices = + // std::vector(recursive_proof_public_input_indices.begin(), + // recursive_proof_public_input_indices.end()); + + // verification_key->contains_recursive_proof = contains_recursive_proof; - // verification_key->contains_recursive_proof = contains_recursive_proof; - } return verification_key; } diff --git a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp index 830f0578837..82a15ae736f 100644 --- a/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/instance/prover_instance.hpp @@ -49,13 +49,7 @@ template class ProverInstance_ { ProverInstance_(Circuit& circuit) { - if constexpr (IsUltraFlavor) { - compute_circuit_size_parameters(circuit); - } else { - num_public_inputs = circuit.public_inputs.size(); - total_num_gates = circuit.num_gates + num_public_inputs; - dyadic_circuit_size = circuit.get_circuit_subgroup_size(total_num_gates); - } + compute_circuit_size_parameters(circuit); compute_proving_key(circuit); compute_witness(circuit); } @@ -72,11 +66,9 @@ template class ProverInstance_ { void initialise_prover_polynomials(); - void compute_sorted_accumulator_polynomials(FF) - requires IsUltraFlavor; + void compute_sorted_accumulator_polynomials(FF); - void compute_sorted_list_accumulator(FF) - requires IsUltraFlavor; + void compute_sorted_list_accumulator(FF); void compute_grand_product_polynomials(FF, FF); @@ -94,18 +86,15 @@ template class ProverInstance_ { std::shared_ptr compute_proving_key(Circuit&); - void compute_circuit_size_parameters(Circuit&) - requires IsUltraFlavor; + void compute_circuit_size_parameters(Circuit&); void compute_witness(Circuit&); - void construct_ecc_op_wire_polynomials(auto&) - requires IsUltraFlavor; + void construct_ecc_op_wire_polynomials(auto&); void add_table_column_selector_poly_to_proving_key(barretenberg::polynomial& small, const std::string& tag); - void add_plookup_memory_records_to_wire_4(FF) - requires IsUltraFlavor; + void add_plookup_memory_records_to_wire_4(FF); }; extern template class ProverInstance_; diff --git a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relation_correctness.test.cpp index 2c34ebab7c2..d73918737cc 100644 --- a/barretenberg/cpp/src/barretenberg/honk/sumcheck/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/honk/sumcheck/relation_correctness.test.cpp @@ -75,15 +75,13 @@ template void create_some_add_gates(auto& circuit_builder) circuit_builder.create_add_gate({ d_idx, c_idx, a_idx, 1, -1, -1, 0 }); } - // If Ultra arithmetization, add a big add gate with use of next row to test q_arith = 2 - if constexpr (proof_system::IsUltraFlavor) { - FF e = a + b + c + d; - uint32_t e_idx = circuit_builder.add_variable(e); - - uint32_t zero_idx = circuit_builder.zero_idx; - circuit_builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); // use next row - circuit_builder.create_big_add_gate({ zero_idx, zero_idx, zero_idx, e_idx, 0, 0, 0, 0, 0 }, false); - } + // Add an Ultra-style big add gate with use of next row to test q_arith = 2 + FF e = a + b + c + d; + uint32_t e_idx = circuit_builder.add_variable(e); + + uint32_t zero_idx = circuit_builder.zero_idx; + circuit_builder.create_big_add_gate({ a_idx, b_idx, c_idx, d_idx, -1, -1, -1, -1, 0 }, true); // use next row + circuit_builder.create_big_add_gate({ zero_idx, zero_idx, zero_idx, e_idx, 0, 0, 0, 0, 0 }, false); } template void create_some_lookup_gates(auto& circuit_builder)