diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.cpp b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.cpp index afe06392009..ea9ab77c13d 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.cpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.cpp @@ -68,6 +68,8 @@ bool UltraCircuitChecker::check_block(Builder& builder, auto values = init_empty_values(); Params params; params.eta = memory_data.eta; // used in Auxiliary relation for RAM/ROM consistency + params.eta_two = memory_data.eta_two; + params.eta_three = memory_data.eta_three; // Perform checks on each gate defined in the builder bool result = true; @@ -179,10 +181,11 @@ void UltraCircuitChecker::populate_values( } }; - // A lambda function for computing a memory record term of the form w3 * eta^3 + w2 * eta^2 + w1 * eta - auto compute_memory_record_term = [](const FF& w_1, const FF& w_2, const FF& w_3, const FF& eta) { - return ((w_3 * eta + w_2) * eta + w_1) * eta; - }; + // A lambda function for computing a memory record term of the form w3 * eta_three + w2 * eta_two + w1 * eta + auto compute_memory_record_term = + [](const FF& w_1, const FF& w_2, const FF& w_3, const FF& eta, const FF& eta_two, FF& eta_three) { + return (w_3 * eta_three + w_2 * eta_two + w_1 * eta); + }; // Set wire values. Wire 4 is treated specially since it may contain memory records values.w_l = builder.get_variable(block.w_l()[idx]); @@ -191,9 +194,13 @@ void UltraCircuitChecker::populate_values( // Note: memory_data contains indices into the block to which RAM/ROM gates were added so we need to check that we // are indexing into the correct block before updating the w_4 value. if (block.has_ram_rom && memory_data.read_record_gates.contains(idx)) { - values.w_4 = compute_memory_record_term(values.w_l, values.w_r, values.w_o, memory_data.eta); + values.w_4 = compute_memory_record_term( + values.w_l, values.w_r, values.w_o, memory_data.eta, memory_data.eta_two, memory_data.eta_three); } else if (block.has_ram_rom && memory_data.write_record_gates.contains(idx)) { - values.w_4 = compute_memory_record_term(values.w_l, values.w_r, values.w_o, memory_data.eta) + FF::one(); + values.w_4 = + compute_memory_record_term( + values.w_l, values.w_r, values.w_o, memory_data.eta, memory_data.eta_two, memory_data.eta_three) + + FF::one(); } else { values.w_4 = builder.get_variable(block.w_4()[idx]); } @@ -204,12 +211,20 @@ void UltraCircuitChecker::populate_values( values.w_r_shift = builder.get_variable(block.w_r()[idx + 1]); values.w_o_shift = builder.get_variable(block.w_o()[idx + 1]); if (block.has_ram_rom && memory_data.read_record_gates.contains(idx + 1)) { - values.w_4_shift = - compute_memory_record_term(values.w_l_shift, values.w_r_shift, values.w_o_shift, memory_data.eta); + values.w_4_shift = compute_memory_record_term(values.w_l_shift, + values.w_r_shift, + values.w_o_shift, + memory_data.eta, + memory_data.eta_two, + memory_data.eta_three); } else if (block.has_ram_rom && memory_data.write_record_gates.contains(idx + 1)) { - values.w_4_shift = - compute_memory_record_term(values.w_l_shift, values.w_r_shift, values.w_o_shift, memory_data.eta) + - FF::one(); + values.w_4_shift = compute_memory_record_term(values.w_l_shift, + values.w_r_shift, + values.w_o_shift, + memory_data.eta, + memory_data.eta_two, + memory_data.eta_three) + + FF::one(); } else { values.w_4_shift = builder.get_variable(block.w_4()[idx + 1]); } diff --git a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.hpp b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.hpp index 4e4ae0d32ac..39a92d46819 100644 --- a/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.hpp +++ b/barretenberg/cpp/src/barretenberg/circuit_checker/ultra_circuit_checker.hpp @@ -132,7 +132,10 @@ class UltraCircuitChecker { * @brief Struct for managing memory record data for ensuring RAM/ROM correctness */ struct MemoryCheckData { - FF eta = FF::random_element(); // randomness for constructing wire 4 mem records + // randomness for constructing wire 4 mem records + FF eta = FF::random_element(); + FF eta_two = FF::random_element(); + FF eta_three = FF::random_element(); std::unordered_set read_record_gates; // row indices for gates containing RAM/ROM read mem record std::unordered_set write_record_gates; // row indices for gates containing RAM/ROM write mem record diff --git a/barretenberg/cpp/src/barretenberg/honk/proof_system/types/proof.hpp b/barretenberg/cpp/src/barretenberg/honk/proof_system/types/proof.hpp index 2c9ea4e3a3b..a20111a69be 100644 --- a/barretenberg/cpp/src/barretenberg/honk/proof_system/types/proof.hpp +++ b/barretenberg/cpp/src/barretenberg/honk/proof_system/types/proof.hpp @@ -5,7 +5,7 @@ namespace bb { -using HonkProof = std::vector; +using HonkProof = std::vector; // this can be fr? template using StdlibProof = std::vector>; diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp index 4c5d2bc763f..bafae22398f 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/combiner.test.cpp @@ -51,22 +51,23 @@ TEST(Protogalaxy, CombinerOn2Instances) } ProverInstances instances{ instance_data }; - instances.alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only + instances.alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only auto pow_polynomial = PowPolynomial(std::vector{ 2 }); auto result = prover.compute_combiner(instances, pow_polynomial); - auto expected_result = Univariate(std::array{ 87706, - 13644570, - 76451738, - 226257946, - static_cast(500811930), - static_cast(937862426), - static_cast(1575158170), - static_cast(2450447898), - static_cast(3601480346), - static_cast(5066004250), - static_cast(6881768346), - static_cast(9086521370), - static_cast(11718012058) }); + auto expected_result = Univariate(std::array{ + 87706, + 13644570, + 76451738, + 226257946, + static_cast(500811930), + static_cast(937862426), + static_cast(1575158170), + static_cast(2450447898), + static_cast(3601480346), + static_cast(5066004250), + static_cast(6881768346), + static_cast(9086521370), + }); EXPECT_EQ(result, expected_result); } else { std::vector> instance_data(NUM_INSTANCES); @@ -84,7 +85,7 @@ TEST(Protogalaxy, CombinerOn2Instances) } ProverInstances instances{ instance_data }; - instances.alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only + instances.alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only const auto create_add_gate = [](auto& polys, const size_t idx, FF w_l, FF w_r) { polys.w_l[idx] = w_l; @@ -133,7 +134,7 @@ TEST(Protogalaxy, CombinerOn2Instances) auto pow_polynomial = PowPolynomial(std::vector{ 2 }); auto result = prover.compute_combiner(instances, pow_polynomial); auto expected_result = - Univariate(std::array{ 0, 0, 12, 36, 72, 120, 180, 252, 336, 432, 540, 660, 792 }); + Univariate(std::array{ 0, 0, 12, 36, 72, 120, 180, 252, 336, 432, 540, 660 }); EXPECT_EQ(result, expected_result); } @@ -175,7 +176,7 @@ TEST(Protogalaxy, CombinerOn4Instances) } ProverInstances instances{ instance_data }; - instances.alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only + instances.alphas.fill(bb::Univariate(FF(0))); // focus on the arithmetic relation only zero_all_selectors(instances[0]->prover_polynomials); zero_all_selectors(instances[1]->prover_polynomials); @@ -184,9 +185,9 @@ TEST(Protogalaxy, CombinerOn4Instances) auto pow_polynomial = PowPolynomial(std::vector{ 2 }); auto result = prover.compute_combiner(instances, pow_polynomial); - std::array zeroes; + std::array zeroes; std::fill(zeroes.begin(), zeroes.end(), 0); - auto expected_result = Univariate(zeroes); + auto expected_result = Univariate(zeroes); EXPECT_EQ(result, expected_result); }; run_test(); diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp index 1124bfdec23..453e0d844d7 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy.test.cpp @@ -119,10 +119,14 @@ template class ProtoGalaxyTests : public testing::Test { auto instance = std::make_shared(builder); instance->relation_parameters.eta = FF::random_element(); + instance->relation_parameters.eta_two = FF::random_element(); + instance->relation_parameters.eta_three = FF::random_element(); instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key->compute_sorted_accumulator_polynomials(instance->relation_parameters.eta); + instance->proving_key->compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); if constexpr (IsGoblinFlavor) { instance->proving_key->compute_logderivative_inverse(instance->relation_parameters); } @@ -219,13 +223,12 @@ template class ProtoGalaxyTests : public testing::Test { static void test_combiner_quotient() { auto compressed_perturbator = FF(2); // F(\alpha) in the paper - auto combiner = - bb::Univariate(std::array{ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }); + auto combiner = bb::Univariate(std::array{ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31 }); auto combiner_quotient = ProtoGalaxyProver::compute_combiner_quotient(compressed_perturbator, combiner); // K(i) = (G(i) - ( L_0(i) * F(\alpha)) / Z(i), i = {2,.., 13} for ProverInstances::NUM = 2 // K(i) = (G(i) - (1 - i) * F(\alpha)) / i * (i - 1) - auto expected_evals = bb::Univariate(std::array{ + auto expected_evals = bb::Univariate(std::array{ (FF(22) - (FF(1) - FF(2)) * compressed_perturbator) / (FF(2) * FF(2 - 1)), (FF(23) - (FF(1) - FF(3)) * compressed_perturbator) / (FF(3) * FF(3 - 1)), (FF(24) - (FF(1) - FF(4)) * compressed_perturbator) / (FF(4) * FF(4 - 1)), @@ -236,7 +239,6 @@ template class ProtoGalaxyTests : public testing::Test { (FF(29) - (FF(1) - FF(9)) * compressed_perturbator) / (FF(9) * FF(9 - 1)), (FF(30) - (FF(1) - FF(10)) * compressed_perturbator) / (FF(10) * FF(10 - 1)), (FF(31) - (FF(1) - FF(11)) * compressed_perturbator) / (FF(11) * FF(11 - 1)), - (FF(32) - (FF(1) - FF(12)) * compressed_perturbator) / (FF(12) * FF(12 - 1)), }); for (size_t idx = 2; idx < 7; idx++) { @@ -263,7 +265,7 @@ template class ProtoGalaxyTests : public testing::Test { ProverInstances instances{ { instance1, instance2 } }; ProtoGalaxyProver::combine_relation_parameters(instances); - bb::Univariate expected_eta{ { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23 } }; + bb::Univariate expected_eta{ { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21 } }; EXPECT_EQ(instances.relation_parameters.eta, expected_eta); } @@ -285,7 +287,7 @@ template class ProtoGalaxyTests : public testing::Test { ProverInstances instances{ { instance1, instance2 } }; ProtoGalaxyProver::combine_alpha(instances); - bb::Univariate expected_alpha{ { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26 } }; + bb::Univariate expected_alpha{ { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24 } }; for (const auto& alpha : instances.alphas) { EXPECT_EQ(alpha, expected_alpha); } diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp index d7774878347..a1cb41cef73 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_prover.cpp @@ -121,6 +121,8 @@ std::shared_ptr ProtoGalaxyProver_{ combined_relation_parameters.eta.evaluate(challenge), + combined_relation_parameters.eta_two.evaluate(challenge), + combined_relation_parameters.eta_three.evaluate(challenge), combined_relation_parameters.beta.evaluate(challenge), combined_relation_parameters.gamma.evaluate(challenge), combined_relation_parameters.public_input_delta.evaluate(challenge), diff --git a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp index 9d6eb95e88f..b47ba04a292 100644 --- a/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/protogalaxy/protogalaxy_verifier.cpp @@ -146,6 +146,8 @@ std::shared_ptr ProtoGalaxyVerifier_relation_parameters.eta * lagranges[inst_idx]; + expected_parameters.eta_two += instance->relation_parameters.eta_two * lagranges[inst_idx]; + expected_parameters.eta_three += instance->relation_parameters.eta_three * lagranges[inst_idx]; expected_parameters.beta += instance->relation_parameters.beta * lagranges[inst_idx]; expected_parameters.gamma += instance->relation_parameters.gamma * lagranges[inst_idx]; expected_parameters.public_input_delta += diff --git a/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp index 0e97cb1ded2..745508d1415 100644 --- a/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/auxiliary_relation.hpp @@ -41,12 +41,12 @@ template class AuxiliaryRelationImpl { }; static constexpr std::array TOTAL_LENGTH_ADJUSTMENTS{ - 6, // auxiliary sub-relation - 6, // ROM consistency sub-relation 1 - 6, // ROM consistency sub-relation 2 - 6, // RAM consistency sub-relation 1 - 6, // RAM consistency sub-relation 2 - 6 // RAM consistency sub-relation 3 + 1, // auxiliary sub-relation + 1, // ROM consistency sub-relation 1 + 1, // ROM consistency sub-relation 2 + 1, // RAM consistency sub-relation 1 + 1, // RAM consistency sub-relation 2 + 1 // RAM consistency sub-relation 3 }; /** @@ -96,6 +96,8 @@ template class AuxiliaryRelationImpl { using ParameterView = GetParameterView; const auto& eta = ParameterView(params.eta); + const auto& eta_two = ParameterView(params.eta_two); + const auto& eta_three = ParameterView(params.eta_three); auto w_1 = View(in.w_l); auto w_2 = View(in.w_r); @@ -186,13 +188,13 @@ template class AuxiliaryRelationImpl { * * t: `timestamp` of memory cell being accessed (used for RAM, set to 0 for ROM) * * v: `value` of memory cell being accessed * * a: `access` type of record. read: 0 = read, 1 = write - * * r: `record` of memory cell. record = access + index * eta + timestamp * eta^2 + value * eta^3 + * * r: `record` of memory cell. record = access + index * eta + timestamp * η₂ + value * η₃ * * A ROM memory record contains a tuple of the following fields: * * i: `index` of memory cell being accessed * * v: `value1` of memory cell being accessed (ROM tables can store up to 2 values per index) * * v2:`value2` of memory cell being accessed (ROM tables can store up to 2 values per index) - * * r: `record` of memory cell. record = index * eta + value2 * eta^2 + value1 * eta^3 + * * r: `record` of memory cell. record = index * eta + value2 * η₂ + value1 * η₃ * * When performing a read/write access, the values of i, t, v, v2, a, r are stored in the following wires + * selectors, depending on whether the gate is a RAM read/write or a ROM read @@ -210,21 +212,19 @@ template class AuxiliaryRelationImpl { /** * Memory Record Check * Partial degree: 1 - * Total degree: 4 + * Total degree: 2 * * A ROM/ROM access gate can be evaluated with the identity: * - * qc + w1 \eta + w2 \eta^2 + w3 \eta^3 - w4 = 0 + * qc + w1 \eta + w2 η₂ + w3 η₃ - w4 = 0 * * For ROM gates, qc = 0 */ - auto memory_record_check = w_3 * eta; - memory_record_check += w_2; - memory_record_check *= eta; - memory_record_check += w_1; - memory_record_check *= eta; + auto memory_record_check = w_3 * eta_three; + memory_record_check += w_2 * eta_two; + memory_record_check += w_1 * eta; memory_record_check += q_c; - auto partial_record_check = memory_record_check; // used in RAM consistency check; deg 1 or 4 + auto partial_record_check = memory_record_check; // used in RAM consistency check; deg 1 or 2 memory_record_check = memory_record_check - w_4; /** @@ -253,13 +253,13 @@ template class AuxiliaryRelationImpl { adjacent_values_match_if_adjacent_indices_match * (q_1 * q_2) * (q_aux * scaling_factor); // deg 5 std::get<2>(accumulators) += index_is_monotonically_increasing * (q_1 * q_2) * (q_aux * scaling_factor); // deg 5 - auto ROM_consistency_check_identity = memory_record_check * (q_1 * q_2); // deg 3 or 7 + auto ROM_consistency_check_identity = memory_record_check * (q_1 * q_2); // deg 3 or 4 /** * RAM Consistency Check * * The 'access' type of the record is extracted with the expression `w_4 - partial_record_check` - * (i.e. for an honest Prover `w1 * eta + w2 * eta^2 + w3 * eta^3 - w4 = access`. + * (i.e. for an honest Prover `w1 * η + w2 * η₂ + w3 * η₃ - w4 = access`. * This is validated by requiring `access` to be boolean * * For two adjacent entries in the sorted list if _both_ @@ -273,22 +273,20 @@ template class AuxiliaryRelationImpl { * N.B. it is the responsibility of the circuit writer to ensure that every RAM cell is initialized * with a WRITE operation. */ - auto access_type = (w_4 - partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 4 - auto access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 8 + auto access_type = (w_4 - partial_record_check); // will be 0 or 1 for honest Prover; deg 1 or 2 + auto access_check = access_type * access_type - access_type; // check value is 0 or 1; deg 2 or 4 // TODO(https://github.com/AztecProtocol/barretenberg/issues/757): If we sorted in - // reverse order we could re-use `partial_record_check` 1 - ((w3' * eta + w2') * eta + w1') * eta - // deg 1 or 4 - auto next_gate_access_type = w_3_shift * eta; - next_gate_access_type += w_2_shift; - next_gate_access_type *= eta; - next_gate_access_type += w_1_shift; - next_gate_access_type *= eta; + // reverse order we could re-use `partial_record_check` 1 - (w3' * eta_three + w2' * eta_two + w1' * + // eta) deg 1 or 2 + auto next_gate_access_type = w_3_shift * eta_three; + next_gate_access_type += w_2_shift * eta_two; + next_gate_access_type += w_1_shift * eta; next_gate_access_type = w_4_shift - next_gate_access_type; auto value_delta = w_3_shift - w_3; auto adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation = - (index_delta * FF(-1) + FF(1)) * value_delta * (next_gate_access_type * FF(-1) + FF(1)); // deg 3 or 6 + (index_delta * FF(-1) + FF(1)) * value_delta * (next_gate_access_type * FF(-1) + FF(1)); // deg 3 or 4 // 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 @@ -300,11 +298,11 @@ template class AuxiliaryRelationImpl { // Putting it all together... std::get<3>(accumulators) += adjacent_values_match_if_adjacent_indices_match_and_next_access_is_a_read_operation * (q_arith) * - (q_aux * scaling_factor); // deg 5 or 8 + (q_aux * scaling_factor); // deg 5 or 6 std::get<4>(accumulators) += index_is_monotonically_increasing * (q_arith) * (q_aux * scaling_factor); // deg 4 std::get<5>(accumulators) += next_gate_access_type_is_boolean * (q_arith) * (q_aux * scaling_factor); // deg 4 or 6 - auto RAM_consistency_check_identity = access_check * (q_arith); // deg 3 or 9 + auto RAM_consistency_check_identity = access_check * (q_arith); // deg 3 or 5 /** * RAM Timestamp Consistency Check @@ -324,14 +322,14 @@ template class AuxiliaryRelationImpl { * The complete RAM/ROM memory identity * Partial degree: */ - auto memory_identity = ROM_consistency_check_identity; // deg 3 or 6 + auto memory_identity = ROM_consistency_check_identity; // deg 3 or 4 memory_identity += RAM_timestamp_check_identity * (q_4 * q_1); // deg 4 - memory_identity += memory_record_check * (q_m * q_1); // deg 3 or 6 - memory_identity += RAM_consistency_check_identity; // deg 3 or 9 + memory_identity += memory_record_check * (q_m * q_1); // deg 3 or 4 + memory_identity += RAM_consistency_check_identity; // deg 3 or 5 - // (deg 3 or 9) + (deg 4) + (deg 3) + // (deg 3 or 5) + (deg 4) + (deg 3) auto auxiliary_identity = memory_identity + non_native_field_identity + limb_accumulator_identity; - auxiliary_identity *= (q_aux * scaling_factor); // deg 4 or 10 + auxiliary_identity *= (q_aux * scaling_factor); // deg 5 or 6 std::get<0>(accumulators) += auxiliary_identity; }; }; diff --git a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp b/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp index c4d1e9342ad..a9a4bd3fb47 100644 --- a/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/lookup_relation.hpp @@ -28,7 +28,7 @@ template class LookupRelationImpl { }; static constexpr std::array TOTAL_LENGTH_ADJUSTMENTS{ - 6, // grand product construction sub-relation + 4, // grand product construction sub-relation 0 // left-shiftable polynomial sub-relation }; /** @@ -67,8 +67,8 @@ template class LookupRelationImpl { const auto& beta = ParameterView(params.beta); const auto& gamma = ParameterView(params.gamma); const auto& eta = ParameterView(params.eta); - const auto eta_sqr = eta * eta; - const auto eta_cube = eta_sqr * eta; + const auto& eta_two = ParameterView(params.eta_two); + const auto& eta_three = ParameterView(params.eta_three); const auto one_plus_beta = beta + FF(1); const auto gamma_by_one_plus_beta = gamma * one_plus_beta; @@ -97,24 +97,24 @@ template class LookupRelationImpl { auto column_3_step_size = View(in.q_c); auto q_lookup = View(in.q_lookup); - // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η²(w_3 + q_c*w_3_shift) + η³q_index. - // deg 2 or 4 + // (w_1 + q_2*w_1_shift) + η(w_2 + q_m*w_2_shift) + η₂(w_3 + q_c*w_3_shift) + η₃q_index. + // deg 2 or 3 auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + - (w_3 + column_3_step_size * w_3_shift) * eta_sqr + table_index * eta_cube; + (w_3 + column_3_step_size * w_3_shift) * eta_two + table_index * eta_three; - // t_1 + ηt_2 + η²t_3 + η³t_4 - // deg 1 or 4 - auto table_accum = table_1 + table_2 * eta + table_3 * eta_sqr + table_4 * eta_cube; + // t_1 + ηt_2 + η₂t_3 + η₃t_4 + // deg 1 or 2 + auto table_accum = table_1 + table_2 * eta + table_3 * eta_two + table_4 * eta_three; - // t_1_shift + ηt_2_shift + η²t_3_shift + η³t_4_shift - // deg 4 + // t_1_shift + ηt_2_shift + η₂t_3_shift + η₃t_4_shift + // deg 1 or 2 auto table_accum_shift = - table_1_shift + table_2_shift * eta + table_3_shift * eta_sqr + table_4_shift * eta_cube; + table_1_shift + table_2_shift * eta + table_3_shift * eta_two + table_4_shift * eta_three; - auto tmp = (q_lookup * wire_accum + gamma); // deg 2 or 4 - tmp *= (table_accum + table_accum_shift * beta + gamma_by_one_plus_beta); // 1 or 5 - tmp *= one_plus_beta; // deg 1 - return tmp; // deg 4 or 10 + auto tmp = (q_lookup * wire_accum + gamma); // deg 3 or 4 + tmp *= (table_accum + table_accum_shift * beta + gamma_by_one_plus_beta); // 1 or 3 + tmp *= one_plus_beta; // deg 0 or 1 + return tmp; // deg 4 or 8 } /** @@ -186,10 +186,10 @@ template class LookupRelationImpl { auto lagrange_first = View(in.lagrange_first); auto lagrange_last = View(in.lagrange_last); - const auto lhs = compute_grand_product_numerator(in, params); // deg 4 or 10 + const auto lhs = compute_grand_product_numerator(in, params); // deg 4 or 8 const auto rhs = compute_grand_product_denominator(in, params); // deg 1 or 2 - // (deg 5 or 11) - (deg 3 or 5) + // (deg 5 or 9) - (deg 3 or 5) const auto tmp = lhs * (z_lookup + lagrange_first) - rhs * (z_lookup_shift + lagrange_last * grand_product_delta); std::get<0>(accumulators) += tmp * scaling_factor; diff --git a/barretenberg/cpp/src/barretenberg/relations/relation_parameters.hpp b/barretenberg/cpp/src/barretenberg/relations/relation_parameters.hpp index b6b71fed365..70573ad8626 100644 --- a/barretenberg/cpp/src/barretenberg/relations/relation_parameters.hpp +++ b/barretenberg/cpp/src/barretenberg/relations/relation_parameters.hpp @@ -15,7 +15,9 @@ template struct RelationParameters { static constexpr int NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR = 4; static constexpr int NUM_NATIVE_LIMBS_IN_GOBLIN_TRANSLATOR = 1; static constexpr int NUM_CHALLENGE_POWERS_IN_GOBLIN_TRANSLATOR = 4; - T eta = T(0); // Lookup + T eta = T(0); // Lookup + Aux Memory + T eta_two = T(0); // Lookup + Aux Memory + T eta_three = T(0); // Lookup + Aux Memory T beta = T(0); // Permutation + Lookup T gamma = T(0); // Permutation + Lookup T public_input_delta = T(0); // Permutation @@ -38,13 +40,17 @@ template struct RelationParameters { { T(0), T(0), T(0), T(0), T(0) }, { T(0), T(0), T(0), T(0), T(0) } } }; - static constexpr int NUM_TO_FOLD = 5; - auto get_to_fold() { return RefArray{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta }; } + auto get_to_fold() + { + return RefArray{ eta, eta_two, eta_three, beta, gamma, public_input_delta, lookup_grand_product_delta }; + } static RelationParameters get_random() { RelationParameters result; result.eta = T::random_element(); + result.eta_two = T::random_element(); + result.eta_three = T::random_element(); result.beta = T::random_element(); result.beta_sqr = result.beta * result.beta; result.beta_cube = result.beta_sqr * result.beta; diff --git a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp index 79e7349d6b8..0406f82bcef 100644 --- a/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/relations/ultra_relation_consistency.test.cpp @@ -248,6 +248,8 @@ TEST_F(UltraRelationConsistency, LookupRelation) const auto parameters = RelationParameters::get_random(); const auto eta = parameters.eta; + const auto eta_two = parameters.eta_two; + const auto eta_three = parameters.eta_three; const auto beta = parameters.beta; const auto gamma = parameters.gamma; auto grand_product_delta = parameters.lookup_grand_product_delta; @@ -255,15 +257,13 @@ TEST_F(UltraRelationConsistency, LookupRelation) // Extract the extended edges for manual computation of relation contribution auto one_plus_beta = FF::one() + beta; auto gamma_by_one_plus_beta = gamma * one_plus_beta; - auto eta_sqr = eta * eta; - auto eta_cube = eta_sqr * eta; auto wire_accum = (w_1 + column_1_step_size * w_1_shift) + (w_2 + column_2_step_size * w_2_shift) * eta + - (w_3 + column_3_step_size * w_3_shift) * eta_sqr + table_index * eta_cube; + (w_3 + column_3_step_size * w_3_shift) * eta_two + table_index * eta_three; - auto table_accum = table_1 + table_2 * eta + table_3 * eta_sqr + table_4 * eta_cube; + auto table_accum = table_1 + table_2 * eta + table_3 * eta_two + table_4 * eta_three; auto table_accum_shift = - table_1_shift + table_2_shift * eta + table_3_shift * eta_sqr + table_4_shift * eta_cube; + table_1_shift + table_2_shift * eta + table_3_shift * eta_two + table_4_shift * eta_three; // Contribution 1 auto contribution_1 = (z_lookup + lagrange_first) * (q_lookup * wire_accum + gamma) * @@ -417,6 +417,8 @@ TEST_F(UltraRelationConsistency, AuxiliaryRelation) const auto parameters = RelationParameters::get_random(); const auto& eta = parameters.eta; + const auto& eta_two = parameters.eta_two; + const auto& eta_three = parameters.eta_three; SumcheckArrayOfValuesOverSubrelations expected_values; /** @@ -463,12 +465,9 @@ TEST_F(UltraRelationConsistency, AuxiliaryRelation) /** * Memory Record Check */ - auto memory_record_check = w_3; - memory_record_check *= eta; - memory_record_check += w_2; - memory_record_check *= eta; - memory_record_check += w_1; - memory_record_check *= eta; + auto memory_record_check = w_3 * eta_three; + memory_record_check += w_2 * eta_two; + memory_record_check += w_1 * eta; memory_record_check += q_c; auto partial_record_check = memory_record_check; // used in RAM consistency check memory_record_check = memory_record_check - w_4; @@ -494,12 +493,9 @@ TEST_F(UltraRelationConsistency, AuxiliaryRelation) auto access_type = (w_4 - partial_record_check); // will be 0 or 1 for honest Prover auto access_check = access_type * access_type - access_type; // check value is 0 or 1 - auto next_gate_access_type = w_3_shift; - next_gate_access_type *= eta; - next_gate_access_type += w_2_shift; - next_gate_access_type *= eta; - next_gate_access_type += w_1_shift; - next_gate_access_type *= eta; + auto next_gate_access_type = w_3_shift * eta_three; + next_gate_access_type += w_2_shift * eta_two; + next_gate_access_type += w_1_shift * eta; next_gate_access_type = w_4_shift - next_gate_access_type; auto value_delta = w_3_shift - w_3; diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp index 6fd55434863..f1b50360f94 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/protogalaxy_recursive_verifier.cpp @@ -50,7 +50,8 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst } // Get challenge for sorted list batching and wire four memory records commitment - auto eta = transcript->template get_challenge(domain_separator + "_eta"); + auto [eta, eta_two, eta_three] = transcript->template get_challenges( + domain_separator + "_eta", domain_separator + "_eta_two", domain_separator + "_eta_three"); witness_commitments.sorted_accum = transcript->template receive_from_prover(domain_separator + "_" + labels.sorted_accum); witness_commitments.w_4 = transcript->template receive_from_prover(domain_separator + "_" + labels.w_4); @@ -79,7 +80,7 @@ void ProtoGalaxyRecursiveVerifier_::receive_and_finalise_inst const FF lookup_grand_product_delta = compute_lookup_grand_product_delta(beta, gamma, inst->verification_key->circuit_size); inst->relation_parameters = - RelationParameters{ eta, beta, gamma, public_input_delta, lookup_grand_product_delta }; + RelationParameters{ eta, eta_two, eta_three, beta, gamma, public_input_delta, lookup_grand_product_delta }; // Get the relation separation challenges for (size_t idx = 0; idx < NUM_SUBRELATIONS - 1; idx++) { @@ -222,6 +223,8 @@ std::shared_ptr ProtoGalaxyRecursiveVerifi for (size_t inst_idx = 0; inst_idx < VerifierInstances::NUM; inst_idx++) { auto instance = instances[inst_idx]; expected_parameters.eta += instance->relation_parameters.eta * lagranges[inst_idx]; + expected_parameters.eta_two += instance->relation_parameters.eta_two * lagranges[inst_idx]; + expected_parameters.eta_three += instance->relation_parameters.eta_three * lagranges[inst_idx]; expected_parameters.beta += instance->relation_parameters.beta * lagranges[inst_idx]; expected_parameters.gamma += instance->relation_parameters.gamma * lagranges[inst_idx]; expected_parameters.public_input_delta += diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/recursive_verifier_instance.hpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/recursive_verifier_instance.hpp index 12a54f89169..16ccfe6c4e5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/recursive_verifier_instance.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/recursive_verifier_instance.hpp @@ -84,6 +84,8 @@ template class RecursiveVerifierInstance_ { challenge_idx++; } relation_parameters.eta = FF::from_witness(builder, instance->relation_parameters.eta); + relation_parameters.eta_two = FF::from_witness(builder, instance->relation_parameters.eta_two); + relation_parameters.eta_three = FF::from_witness(builder, instance->relation_parameters.eta_three); relation_parameters.beta = FF::from_witness(builder, instance->relation_parameters.beta); relation_parameters.gamma = FF::from_witness(builder, instance->relation_parameters.gamma); relation_parameters.public_input_delta = @@ -131,6 +133,8 @@ template class RecursiveVerifierInstance_ { } inst.relation_parameters.eta = relation_parameters.eta.get_value(); + inst.relation_parameters.eta_two = relation_parameters.eta_two.get_value(); + inst.relation_parameters.eta_three = relation_parameters.eta_three.get_value(); inst.relation_parameters.beta = relation_parameters.beta.get_value(); inst.relation_parameters.gamma = relation_parameters.gamma.get_value(); inst.relation_parameters.public_input_delta = relation_parameters.public_input_delta.get_value(); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp index 334ad876caf..cf97878c6d7 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/honk_recursion/verifier/ultra_recursive_verifier.cpp @@ -71,8 +71,10 @@ std::array UltraRecursiveVerifier_::ve } // Get challenge for sorted list batching and wire four memory records - auto eta = transcript->template get_challenge("eta"); + auto [eta, eta_two, eta_three] = transcript->template get_challenges("eta", "eta_two", "eta_three"); relation_parameters.eta = eta; + relation_parameters.eta_two = eta_two; + relation_parameters.eta_three = eta_three; // Get commitments to sorted list accumulator and fourth wire commitments.sorted_accum = transcript->template receive_from_prover(commitment_labels.sorted_accum); diff --git a/barretenberg/cpp/src/barretenberg/stdlib/plonk_recursion/verifier/verifier.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib/plonk_recursion/verifier/verifier.test.cpp index 4223324ed25..ade9940d9dc 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib/plonk_recursion/verifier/verifier.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib/plonk_recursion/verifier/verifier.test.cpp @@ -348,8 +348,14 @@ template class stdlib_verifier : public testing::Test { static void check_recursive_verification_circuit(OuterBuilder& outer_circuit, bool expected_result) { info("number of gates in recursive verification circuit = ", outer_circuit.get_num_gates()); - bool result = CircuitChecker::check(outer_circuit); + OuterComposer outer_composer; + auto prover = outer_composer.create_prover(outer_circuit); + auto verifier = outer_composer.create_verifier(outer_circuit); + auto proof = prover.construct_proof(); + auto result = verifier.verify_proof(proof); + // bool result = CircuitChecker::check(outer_circuit); EXPECT_EQ(result, expected_result); + static_cast(expected_result); auto g2_lines = srs::get_bn254_crs_factory()->get_verifier_crs()->get_precomputed_g2_lines(); EXPECT_EQ(check_recursive_proof_public_inputs(outer_circuit, g2_lines), true); } @@ -366,7 +372,13 @@ template class stdlib_verifier : public testing::Test { create_inner_circuit(builder, inputs); - bool result = CircuitChecker::check(builder); + InnerComposer inner_composer; + + auto prover = inner_composer.create_prover(builder); + auto verifier = inner_composer.create_verifier(builder); + auto proof = prover.construct_proof(); + auto result = verifier.verify_proof(proof); + EXPECT_EQ(result, true); } @@ -567,9 +579,9 @@ template class stdlib_verifier : public testing::Test { } }; -typedef testing::Types OuterCircuitTypes; +typedef testing::Types OuterComposerTypes; -TYPED_TEST_SUITE(stdlib_verifier, OuterCircuitTypes); +TYPED_TEST_SUITE(stdlib_verifier, OuterComposerTypes); HEAVY_TYPED_TEST(stdlib_verifier, test_inner_circuit) { diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_flavor.hpp index 192cdd12e39..4eb513ae5a5 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/goblin_ultra_flavor.hpp @@ -280,6 +280,15 @@ class GoblinUltraFlavor { // The plookup wires that store plookup read data. auto get_table_column_wires() { return RefArray{ w_l, w_r, w_o }; }; + void compute_sorted_accumulator_polynomials(const FF& eta, const FF& eta_two, const FF& eta_three) + { + // Compute sorted witness-table accumulator + compute_sorted_list_accumulator(eta, eta_two, eta_three); + + // Finalize fourth wire polynomial by adding lookup memory records + add_plookup_memory_records_to_wire_4(eta, eta_two, eta_three); + } + /** * @brief Construct sorted list accumulator polynomial 's'. * @@ -291,33 +300,20 @@ class GoblinUltraFlavor { * @param eta random challenge * @return Polynomial */ - void compute_sorted_list_accumulator(const FF& eta) + void compute_sorted_list_accumulator(const FF& eta, const FF& eta_two, const FF& eta_three) { - const size_t circuit_size = this->circuit_size; - auto sorted_list_accumulator = Polynomial{ circuit_size }; + auto sorted_list_accumulator = Polynomial{ this->circuit_size }; // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) - for (size_t i = 0; i < circuit_size; ++i) { - FF T0 = this->sorted_polynomials[3][i]; - T0 *= eta; - T0 += this->sorted_polynomials[2][i]; - T0 *= eta; - T0 += this->sorted_polynomials[1][i]; - T0 *= eta; - T0 += this->sorted_polynomials[0][i]; + for (size_t i = 0; i < this->circuit_size; ++i) { + FF T0 = sorted_polynomials[3][i] * eta_three; + T0 += sorted_polynomials[2][i] * eta_two; + T0 += sorted_polynomials[1][i] * eta; + T0 += sorted_polynomials[0][i]; sorted_list_accumulator[i] = T0; } - this->sorted_accum = sorted_list_accumulator.share(); - } - - void compute_sorted_accumulator_polynomials(const FF& eta) - { - // Compute sorted witness-table accumulator - this->compute_sorted_list_accumulator(eta); - - // Finalize fourth wire polynomial by adding lookup memory records - add_plookup_memory_records_to_wire_4(eta); + sorted_accum = sorted_list_accumulator.share(); } /** @@ -329,31 +325,25 @@ class GoblinUltraFlavor { * @tparam Flavor * @param eta challenge produced after commitment to first three wire polynomials */ - void add_plookup_memory_records_to_wire_4(const FF& eta) + void add_plookup_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) { // The plookup memory record values are computed at the indicated indices as // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; // (See plookup_auxiliary_widget.hpp for details) - auto wires = this->get_wires(); + auto wires = get_wires(); // Compute read record values - for (const auto& gate_idx : this->memory_read_records) { - wires[3][gate_idx] += wires[2][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[1][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[0][gate_idx]; - wires[3][gate_idx] *= eta; + for (const auto& gate_idx : memory_read_records) { + wires[3][gate_idx] += wires[2][gate_idx] * eta_three; + wires[3][gate_idx] += wires[1][gate_idx] * eta_two; + wires[3][gate_idx] += wires[0][gate_idx] * eta; } // Compute write record values - for (const auto& gate_idx : this->memory_write_records) { - wires[3][gate_idx] += wires[2][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[1][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[0][gate_idx]; - wires[3][gate_idx] *= eta; + for (const auto& gate_idx : memory_write_records) { + wires[3][gate_idx] += wires[2][gate_idx] * eta_three; + wires[3][gate_idx] += wires[1][gate_idx] * eta_two; + wires[3][gate_idx] += wires[0][gate_idx] * eta; wires[3][gate_idx] += 1; } } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp index 55edddad961..7a2ef577349 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/grand_product_library.test.cpp @@ -228,9 +228,13 @@ template class GrandProductTests : public testing::Test { auto beta = FF::random_element(); auto gamma = FF::random_element(); auto eta = FF::random_element(); + auto eta_two = FF::random_element(); + auto eta_three = FF::random_element(); RelationParameters params{ .eta = eta, + .eta_two = eta_two, + .eta_three = eta_three, .beta = beta, .gamma = gamma, .public_input_delta = 1, @@ -267,8 +271,6 @@ template class GrandProductTests : public testing::Test { // ∏(s_k + βs_{k+1} + γ(1 + β)) // // in a way that is simple to read (but inefficient). See prover library method for more details. - const FF eta_sqr = eta.sqr(); - const FF eta_cube = eta_sqr * eta; std::array accumulators; for (size_t i = 0; i < 4; ++i) { @@ -280,22 +282,22 @@ template class GrandProductTests : public testing::Test { // Note: block_mask is used for efficient modulus, i.e. i % N := i & (N-1), for N = 2^k const size_t block_mask = circuit_size - 1; // Initialize 't(X)' to be used in an expression of the form t(X) + β*t(Xω) - FF table_i = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_sqr + tables[3][0] * eta_cube; + FF table_i = tables[0][0] + tables[1][0] * eta + tables[2][0] * eta_two + tables[3][0] * eta_three; for (size_t i = 0; i < circuit_size; ++i) { size_t shift_idx = (i + 1) & block_mask; // f = (w_1 + q_2*w_1(Xω)) + η(w_2 + q_m*w_2(Xω)) + η²(w_3 + q_c*w_3(Xω)) + η³q_index. FF f_i = (wires[0][i] + wires[0][shift_idx] * column_1_step_size[i]) + (wires[1][i] + wires[1][shift_idx] * column_2_step_size[i]) * eta + - (wires[2][i] + wires[2][shift_idx] * column_3_step_size[i]) * eta_sqr + - eta_cube * lookup_index_selector[i]; + (wires[2][i] + wires[2][shift_idx] * column_3_step_size[i]) * eta_two + + eta_three * lookup_index_selector[i]; // q_lookup * f + γ accumulators[0][i] = lookup_selector[i] * f_i + gamma; // t = t_1 + ηt_2 + η²t_3 + η³t_4 - FF table_i_plus_1 = tables[0][shift_idx] + eta * tables[1][shift_idx] + eta_sqr * tables[2][shift_idx] + - eta_cube * tables[3][shift_idx]; + FF table_i_plus_1 = tables[0][shift_idx] + eta * tables[1][shift_idx] + eta_two * tables[2][shift_idx] + + eta_three * tables[3][shift_idx]; // t + βt(Xω) + γ(1 + β) accumulators[1][i] = table_i + table_i_plus_1 * beta + gamma * (FF::one() + beta); diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp index 99bc3ad94b9..1e29d4a5ccb 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_flavor.hpp @@ -58,7 +58,7 @@ class UltraFlavor { static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); static_assert(MAX_PARTIAL_RELATION_LENGTH == 6); static constexpr size_t MAX_TOTAL_RELATION_LENGTH = compute_max_total_relation_length(); - static_assert(MAX_TOTAL_RELATION_LENGTH == 12); + static_assert(MAX_TOTAL_RELATION_LENGTH == 11); static constexpr size_t NUM_SUBRELATIONS = compute_number_of_subrelations(); // For instances of this flavour, used in folding, we need a unique sumcheck batching challenge for each // subrelation. This is because using powers of alpha would increase the degree of Protogalaxy polynomial $G$ (the @@ -287,6 +287,15 @@ class UltraFlavor { // The plookup wires that store plookup read data. auto get_table_column_wires() { return RefArray{ w_l, w_r, w_o }; }; + void compute_sorted_accumulator_polynomials(const FF& eta, const FF& eta_two, const FF& eta_three) + { + // Compute sorted witness-table accumulator + compute_sorted_list_accumulator(eta, eta_two, eta_three); + + // Finalize fourth wire polynomial by adding lookup memory records + add_plookup_memory_records_to_wire_4(eta, eta_two, eta_three); + } + /** * @brief Construct sorted list accumulator polynomial 's'. * @@ -298,33 +307,19 @@ class UltraFlavor { * @param eta random challenge * @return Polynomial */ - void compute_sorted_list_accumulator(const FF& eta) + void compute_sorted_list_accumulator(const FF& eta, const FF& eta_two, const FF& eta_three) { - const size_t circuit_size = this->circuit_size; - - auto sorted_list_accumulator = Polynomial{ circuit_size }; + auto sorted_list_accumulator = Polynomial{ this->circuit_size }; // Construct s via Horner, i.e. s = s_1 + η(s_2 + η(s_3 + η*s_4)) - for (size_t i = 0; i < circuit_size; ++i) { - FF T0 = this->sorted_polynomials[3][i]; - T0 *= eta; - T0 += this->sorted_polynomials[2][i]; - T0 *= eta; - T0 += this->sorted_polynomials[1][i]; - T0 *= eta; - T0 += this->sorted_polynomials[0][i]; + for (size_t i = 0; i < this->circuit_size; ++i) { + FF T0 = sorted_polynomials[3][i] * eta_three; + T0 += sorted_polynomials[2][i] * eta_two; + T0 += sorted_polynomials[1][i] * eta; + T0 += sorted_polynomials[0][i]; sorted_list_accumulator[i] = T0; } - this->sorted_accum = sorted_list_accumulator.share(); - } - - void compute_sorted_accumulator_polynomials(const FF& eta) - { - // Compute sorted witness-table accumulator - this->compute_sorted_list_accumulator(eta); - - // Finalize fourth wire polynomial by adding lookup memory records - add_plookup_memory_records_to_wire_4(eta); + sorted_accum = sorted_list_accumulator.share(); } /** @@ -336,31 +331,25 @@ class UltraFlavor { * @tparam Flavor * @param eta challenge produced after commitment to first three wire polynomials */ - void add_plookup_memory_records_to_wire_4(const FF& eta) + void add_plookup_memory_records_to_wire_4(const FF& eta, const FF& eta_two, const FF& eta_three) { // The plookup memory record values are computed at the indicated indices as // w4 = w3 * eta^3 + w2 * eta^2 + w1 * eta + read_write_flag; // (See plookup_auxiliary_widget.hpp for details) - auto wires = this->get_wires(); + auto wires = get_wires(); // Compute read record values - for (const auto& gate_idx : this->memory_read_records) { - wires[3][gate_idx] += wires[2][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[1][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[0][gate_idx]; - wires[3][gate_idx] *= eta; + for (const auto& gate_idx : memory_read_records) { + wires[3][gate_idx] += wires[2][gate_idx] * eta_three; + wires[3][gate_idx] += wires[1][gate_idx] * eta_two; + wires[3][gate_idx] += wires[0][gate_idx] * eta; } // Compute write record values - for (const auto& gate_idx : this->memory_write_records) { - wires[3][gate_idx] += wires[2][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[1][gate_idx]; - wires[3][gate_idx] *= eta; - wires[3][gate_idx] += wires[0][gate_idx]; - wires[3][gate_idx] *= eta; + for (const auto& gate_idx : memory_write_records) { + wires[3][gate_idx] += wires[2][gate_idx] * eta_three; + wires[3][gate_idx] += wires[1][gate_idx] * eta_two; + wires[3][gate_idx] += wires[0][gate_idx] * eta; wires[3][gate_idx] += 1; } } diff --git a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp index 85120696e25..bf220475341 100644 --- a/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp +++ b/barretenberg/cpp/src/barretenberg/stdlib_circuit_builders/ultra_recursive_flavor.hpp @@ -81,7 +81,7 @@ template class UltraRecursiveFlavor_ { static constexpr size_t MAX_PARTIAL_RELATION_LENGTH = compute_max_partial_relation_length(); static_assert(MAX_PARTIAL_RELATION_LENGTH == 6); static constexpr size_t MAX_TOTAL_RELATION_LENGTH = compute_max_total_relation_length(); - static_assert(MAX_TOTAL_RELATION_LENGTH == 12); + static_assert(MAX_TOTAL_RELATION_LENGTH == 11); // BATCHED_RELATION_PARTIAL_LENGTH = algebraic degree of sumcheck relation *after* multiplying by the `pow_zeta` // random polynomial e.g. For \sum(x) [A(x) * B(x) + C(x)] * PowZeta(X), relation length = 2 and random relation diff --git a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp index bd45fe665f0..c4f9a0966e7 100644 --- a/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp +++ b/barretenberg/cpp/src/barretenberg/sumcheck/instance/prover_instance.test.cpp @@ -59,23 +59,21 @@ template class InstanceTests : public testing::Test { // Get random challenge eta auto eta = FF::random_element(); + auto eta_two = FF::random_element(); + auto eta_three = FF::random_element(); auto sorted_list_polynomials = instance.proving_key->sorted_polynomials; // Method 1: computed sorted list accumulator polynomial using prover library method - instance.proving_key->compute_sorted_list_accumulator(eta); + instance.proving_key->compute_sorted_list_accumulator(eta, eta_two, eta_three); auto sorted_list_accumulator = instance.proving_key->sorted_accum; - // Method 2: Compute local sorted list accumulator simply and inefficiently - const FF eta_sqr = eta.sqr(); - const FF eta_cube = eta_sqr * eta; - // Compute s = s_1 + η*s_2 + η²*s_3 + η³*s_4 Polynomial sorted_list_accumulator_expected{ sorted_list_polynomials[0] }; for (size_t i = 0; i < instance.proving_key->circuit_size; ++i) { sorted_list_accumulator_expected[i] += sorted_list_polynomials[1][i] * eta + - sorted_list_polynomials[2][i] * eta_sqr + - sorted_list_polynomials[3][i] * eta_cube; + sorted_list_polynomials[2][i] * eta_two + + sorted_list_polynomials[3][i] * eta_three; } EXPECT_EQ(sorted_list_accumulator, sorted_list_accumulator_expected); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_transcript.test.cpp index 82370a525e5..64d10ee0f25 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/goblin_ultra_transcript.test.cpp @@ -60,7 +60,7 @@ class GoblinUltraTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "ECC_OP_WIRE_4", frs_per_G); manifest_expected.add_entry(round, "CALLDATA", frs_per_G); manifest_expected.add_entry(round, "CALLDATA_READ_COUNTS", frs_per_G); - manifest_expected.add_challenge(round, "eta"); + manifest_expected.add_challenge(round, "eta", "eta_two", "eta_three"); round++; manifest_expected.add_entry(round, "SORTED_ACCUM", frs_per_G); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp index 1a8a8d123d0..b5a5047443b 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_prover.cpp @@ -98,8 +98,14 @@ template void OinkProver::execute_wire_commitment template void OinkProver::execute_sorted_list_accumulator_round() { - relation_parameters.eta = transcript->template get_challenge(domain_separator + "eta"); - proving_key->compute_sorted_accumulator_polynomials(relation_parameters.eta); + auto [eta, eta_two, eta_three] = transcript->template get_challenges( + domain_separator + "eta", domain_separator + "eta_two", domain_separator + "eta_three"); + relation_parameters.eta = eta; + relation_parameters.eta_two = eta_two; + relation_parameters.eta_three = eta_three; + + proving_key->compute_sorted_accumulator_polynomials( + relation_parameters.eta, relation_parameters.eta_two, relation_parameters.eta_three); // Commit to the sorted witness-table accumulator and the finalized (i.e. with memory records) fourth wire // polynomial witness_commitments.sorted_accum = commitment_key->commit(proving_key->sorted_accum); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp index a79e610c7a7..47c21e9bb42 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/oink_verifier.cpp @@ -82,9 +82,11 @@ template void OinkVerifier::execute_wire_commitme template void OinkVerifier::execute_sorted_list_accumulator_round() { // Get challenge for sorted list batching and wire four memory records - FF eta = transcript->template get_challenge(domain_separator + "eta"); + auto [eta, eta_two, eta_three] = transcript->template get_challenges( + domain_separator + "eta", domain_separator + "eta_two", domain_separator + "eta_three"); relation_parameters.eta = eta; - + relation_parameters.eta_two = eta_two; + relation_parameters.eta_three = eta_three; // Get commitments to sorted list accumulator and fourth wire witness_comms.sorted_accum = transcript->template receive_from_prover(domain_separator + comm_labels.sorted_accum); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp index 9a8f16b282b..7c21616cd32 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/relation_correctness.test.cpp @@ -267,10 +267,14 @@ TEST_F(UltraRelationCorrectnessTests, Ultra) // Generate eta, beta and gamma instance->relation_parameters.eta = FF::random_element(); + instance->relation_parameters.eta_two = FF::random_element(); + instance->relation_parameters.eta_three = FF::random_element(); instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key->compute_sorted_accumulator_polynomials(instance->relation_parameters.eta); + instance->proving_key->compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); instance->proving_key->compute_grand_product_polynomials(instance->relation_parameters); instance->prover_polynomials = Flavor::ProverPolynomials(instance->proving_key); @@ -319,10 +323,14 @@ TEST_F(UltraRelationCorrectnessTests, GoblinUltra) // Generate eta, beta and gamma instance->relation_parameters.eta = FF::random_element(); + instance->relation_parameters.eta_two = FF::random_element(); + instance->relation_parameters.eta_three = FF::random_element(); instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key->compute_sorted_accumulator_polynomials(instance->relation_parameters.eta); + instance->proving_key->compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); instance->proving_key->compute_logderivative_inverse(instance->relation_parameters); instance->proving_key->compute_grand_product_polynomials(instance->relation_parameters); instance->prover_polynomials = Flavor::ProverPolynomials(instance->proving_key); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp index 9bb65c3dec6..1ac3f6d5d10 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/sumcheck.test.cpp @@ -151,10 +151,15 @@ TEST_F(SumcheckTestsRealCircuit, Ultra) // Generate eta, beta and gamma instance->relation_parameters.eta = FF::random_element(); + instance->relation_parameters.eta = FF::random_element(); + instance->relation_parameters.eta_two = FF::random_element(); + instance->relation_parameters.eta_three = FF::random_element(); instance->relation_parameters.beta = FF::random_element(); instance->relation_parameters.gamma = FF::random_element(); - instance->proving_key->compute_sorted_accumulator_polynomials(instance->relation_parameters.eta); + instance->proving_key->compute_sorted_accumulator_polynomials(instance->relation_parameters.eta, + instance->relation_parameters.eta_two, + instance->relation_parameters.eta_three); instance->proving_key->compute_grand_product_polynomials(instance->relation_parameters); instance->prover_polynomials = Flavor::ProverPolynomials(instance->proving_key); diff --git a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp index cf1cc93c681..544bccaa11f 100644 --- a/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp +++ b/barretenberg/cpp/src/barretenberg/ultra_honk/ultra_transcript.test.cpp @@ -55,7 +55,7 @@ class UltraTranscriptTests : public ::testing::Test { manifest_expected.add_entry(round, "W_L", frs_per_G); manifest_expected.add_entry(round, "W_R", frs_per_G); manifest_expected.add_entry(round, "W_O", frs_per_G); - manifest_expected.add_challenge(round, "eta"); + manifest_expected.add_challenge(round, "eta", "eta_two", "eta_three"); round++; manifest_expected.add_entry(round, "SORTED_ACCUM", frs_per_G);