From 89edfd86179c460d6efd76896e09789454410c78 Mon Sep 17 00:00:00 2001 From: Rumata888 Date: Mon, 16 Oct 2023 13:33:24 +0000 Subject: [PATCH 1/5] feat: Goblin translator non-native field relation (Goblin Translator part 6) --- ...n_translator_relation_consistency.test.cpp | 153 ++++++++++++ .../relations/non_native_field_relation.hpp | 225 ++++++++++++++++++ .../relations/relation_parameters.hpp | 34 +++ 3 files changed, 412 insertions(+) create mode 100644 barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp index 24d7d3051b2..af031e3197f 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp @@ -15,6 +15,7 @@ #include "barretenberg/proof_system/relations/decomposition_relation.hpp" #include "barretenberg/proof_system/relations/extra_relations.hpp" #include "barretenberg/proof_system/relations/gen_perm_sort_relation.hpp" +#include "barretenberg/proof_system/relations/non_native_field_relation.hpp" #include "barretenberg/proof_system/relations/permutation_relation.hpp" #include "decomposition_relation.hpp" #include "extra_relations.hpp" @@ -980,4 +981,156 @@ TEST_F(GoblinTranslatorRelationConsistency, AccumulatorTransferRelation) run_test(/*random_inputs=*/true); }; +TEST_F(GoblinTranslatorRelationConsistency, NonNativeFieldRelation) +{ + const auto run_test = [](bool random_inputs) { + constexpr size_t NUM_LIMB_BITS = 68; + constexpr FF shift = FF(uint256_t(1) << NUM_LIMB_BITS); + constexpr FF shiftx2 = FF(uint256_t(1) << (NUM_LIMB_BITS * 2)); + constexpr FF shiftx3 = FF(uint256_t(1) << (NUM_LIMB_BITS * 3)); + constexpr uint512_t MODULUS_U512 = uint512_t(curve::BN254::BaseField::modulus); + constexpr uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (NUM_LIMB_BITS << 2); + constexpr uint512_t NEGATIVE_PRIME_MODULUS = BINARY_BASIS_MODULUS - MODULUS_U512; + constexpr std::array NEGATIVE_MODULUS_LIMBS = { + FF(NEGATIVE_PRIME_MODULUS.slice(0, NUM_LIMB_BITS).lo), + FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2).lo), + FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3).lo), + FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4).lo), + -FF(curve::BN254::BaseField::modulus) + }; + + using Relation = GoblinTranslatorNonNativeFieldRelation; + using RelationValues = typename Relation::ArrayOfValuesOverSubrelations; + + const InputElements input_elements = random_inputs ? InputElements::get_random() : InputElements::get_special(); + + auto& op = input_elements.op; + auto& p_x_low_limbs = input_elements.p_x_low_limbs; + auto& p_y_low_limbs = input_elements.p_y_low_limbs; + auto& p_x_high_limbs = input_elements.p_x_high_limbs; + auto& p_y_high_limbs = input_elements.p_y_high_limbs; + auto& accumulators_binary_limbs_0 = input_elements.accumulators_binary_limbs_0; + auto& accumulators_binary_limbs_1 = input_elements.accumulators_binary_limbs_1; + auto& accumulators_binary_limbs_2 = input_elements.accumulators_binary_limbs_2; + auto& accumulators_binary_limbs_3 = input_elements.accumulators_binary_limbs_3; + auto& z_low_limbs = input_elements.z_low_limbs; + auto& z_high_limbs = input_elements.z_high_limbs; + auto& quotient_low_binary_limbs = input_elements.quotient_low_binary_limbs; + auto& quotient_high_binary_limbs = input_elements.quotient_high_binary_limbs; + auto& p_x_low_limbs_shift = input_elements.p_x_low_limbs_shift; + auto& p_y_low_limbs_shift = input_elements.p_y_low_limbs_shift; + auto& p_x_high_limbs_shift = input_elements.p_x_high_limbs_shift; + auto& p_y_high_limbs_shift = input_elements.p_y_high_limbs_shift; + auto& accumulators_binary_limbs_0_shift = input_elements.accumulators_binary_limbs_0_shift; + auto& accumulators_binary_limbs_1_shift = input_elements.accumulators_binary_limbs_1_shift; + auto& accumulators_binary_limbs_2_shift = input_elements.accumulators_binary_limbs_2_shift; + auto& accumulators_binary_limbs_3_shift = input_elements.accumulators_binary_limbs_3_shift; + auto& z_low_limbs_shift = input_elements.z_low_limbs_shift; + auto& z_high_limbs_shift = input_elements.z_high_limbs_shift; + auto& quotient_low_binary_limbs_shift = input_elements.quotient_low_binary_limbs_shift; + auto& quotient_high_binary_limbs_shift = input_elements.quotient_high_binary_limbs_shift; + auto& relation_wide_limbs = input_elements.relation_wide_limbs; + auto& relation_wide_limbs_shift = input_elements.relation_wide_limbs_shift; + auto& lagrange_odd = input_elements.lagrange_odd; + + RelationValues expected_values; + + const auto parameters = RelationParameters::get_random(); + + // A detailed description of these subrelations is located in the relation's documentation + + // Lower wide limb (lower 136 bits) subrelation + expected_values[0] = + (accumulators_binary_limbs_0_shift * parameters.evaluation_input_x[0] + op + + p_x_low_limbs * parameters.batching_challenge_v[0][0] + + p_y_low_limbs * parameters.batching_challenge_v[1][0] + + z_low_limbs * parameters.batching_challenge_v[2][0] + + z_low_limbs_shift * parameters.batching_challenge_v[3][0] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_0 + + (accumulators_binary_limbs_1_shift * parameters.evaluation_input_x[0] + + accumulators_binary_limbs_0_shift * parameters.evaluation_input_x[1] + + p_x_low_limbs * parameters.batching_challenge_v[0][1] + + p_x_low_limbs_shift * parameters.batching_challenge_v[0][0] + + p_y_low_limbs * parameters.batching_challenge_v[1][1] + + p_y_low_limbs_shift * parameters.batching_challenge_v[1][0] + + z_low_limbs * parameters.batching_challenge_v[2][1] + + z_high_limbs * parameters.batching_challenge_v[2][0] + + z_low_limbs_shift * parameters.batching_challenge_v[3][1] + + z_high_limbs_shift * parameters.batching_challenge_v[3][0] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_1) * + shift - + relation_wide_limbs * shiftx2) * + lagrange_odd; + + expected_values[1] = + (relation_wide_limbs + accumulators_binary_limbs_2_shift * parameters.evaluation_input_x[0] + + accumulators_binary_limbs_1_shift * parameters.evaluation_input_x[1] + + accumulators_binary_limbs_0_shift * parameters.evaluation_input_x[2] + + p_x_high_limbs * parameters.batching_challenge_v[0][0] + + p_x_low_limbs_shift * parameters.batching_challenge_v[0][1] + + p_x_low_limbs * parameters.batching_challenge_v[0][2] + + p_y_high_limbs * parameters.batching_challenge_v[1][0] + + p_y_low_limbs_shift * parameters.batching_challenge_v[1][1] + + p_y_low_limbs * parameters.batching_challenge_v[1][2] + + z_high_limbs * parameters.batching_challenge_v[2][1] + + z_low_limbs * parameters.batching_challenge_v[2][2] + + z_high_limbs_shift * parameters.batching_challenge_v[3][1] + + z_low_limbs_shift * parameters.batching_challenge_v[3][2] + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] - accumulators_binary_limbs_2 + + (accumulators_binary_limbs_3_shift * parameters.evaluation_input_x[0] + + accumulators_binary_limbs_2_shift * parameters.evaluation_input_x[1] + + accumulators_binary_limbs_1_shift * parameters.evaluation_input_x[2] + + accumulators_binary_limbs_0_shift * parameters.evaluation_input_x[3] + + p_x_high_limbs_shift * parameters.batching_challenge_v[0][0] + + p_x_high_limbs * parameters.batching_challenge_v[0][1] + + p_x_low_limbs_shift * parameters.batching_challenge_v[0][2] + + p_x_low_limbs * parameters.batching_challenge_v[0][3] + + p_y_high_limbs_shift * parameters.batching_challenge_v[1][0] + + p_y_high_limbs * parameters.batching_challenge_v[1][1] + + p_y_low_limbs_shift * parameters.batching_challenge_v[1][2] + + p_y_low_limbs * parameters.batching_challenge_v[1][3] + + z_high_limbs * parameters.batching_challenge_v[2][2] + + z_low_limbs * parameters.batching_challenge_v[2][3] + + z_high_limbs_shift * parameters.batching_challenge_v[3][2] + + z_low_limbs_shift * parameters.batching_challenge_v[3][3] + + quotient_high_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[2] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[3] - accumulators_binary_limbs_3) * + shift - + relation_wide_limbs_shift * shiftx2) * + lagrange_odd; + auto reconstructed_p_x = + (p_x_low_limbs + p_x_low_limbs_shift * shift + p_x_high_limbs * shiftx2 + p_x_high_limbs_shift * shiftx3); + auto reconstructed_p_y = + (p_y_low_limbs + p_y_low_limbs_shift * shift + p_y_high_limbs * shiftx2 + p_y_high_limbs_shift * shiftx3); + auto reconstructed_previous_accumulator = + (accumulators_binary_limbs_0_shift + accumulators_binary_limbs_1_shift * shift + + accumulators_binary_limbs_2_shift * shiftx2 + accumulators_binary_limbs_3_shift * shiftx3); + auto reconstructed_current_accumulator = + (accumulators_binary_limbs_0 + accumulators_binary_limbs_1 * shift + accumulators_binary_limbs_2 * shiftx2 + + accumulators_binary_limbs_3 * shiftx3); + auto reconstructed_z1 = (z_low_limbs + z_high_limbs * shift); + auto reconstructed_z2 = (z_low_limbs_shift + z_high_limbs_shift * shift); + auto reconstructed_quotient = + (quotient_low_binary_limbs + quotient_low_binary_limbs_shift * shift + + quotient_high_binary_limbs * shiftx2 + quotient_high_binary_limbs_shift * shiftx3); + + expected_values[2] = (reconstructed_previous_accumulator * parameters.evaluation_input_x[4] + op + + reconstructed_p_x * parameters.batching_challenge_v[0][4] + + reconstructed_p_y * parameters.batching_challenge_v[1][4] + + reconstructed_z1 * parameters.batching_challenge_v[2][4] + + reconstructed_z2 * parameters.batching_challenge_v[3][4] + + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator) * + lagrange_odd; + + validate_relation_execution(expected_values, input_elements, parameters); + }; + run_test(/*random_inputs=*/false); + run_test(/*random_inputs=*/true); +}; + } // namespace proof_system::ultra_relation_consistency_tests diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp new file mode 100644 index 00000000000..8ef722494ab --- /dev/null +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp @@ -0,0 +1,225 @@ +#pragma once +#include "barretenberg/ecc/curves/bn254/bn254.hpp" +#include "barretenberg/numeric/uintx/uintx.hpp" +#include "relation_parameters.hpp" +#include "relation_types.hpp" + +namespace proof_system { + +template class GoblinTranslatorNonNativeFieldRelationImpl { + public: + using FF = FF_; + + // 1 + polynomial degree of this relation + static constexpr size_t RELATION_LENGTH = 3; // degree((lagrange_odd-1)(a*b-c*d)) = 2 + static constexpr std::array SUBRELATION_LENGTHS{ + 3, // Lower wide limb subrelation (checks result is 0 mod 2¹³⁶) + 3, // Higher wide limb subrelation (checks result is 0 in higher mod 2¹³⁶), + 3 // Prime subrelation (checks result in native field) + }; + + /** + * @brief Expression for the computation of Goblin Translator accumulator in integers through 68-bit limbs and + * native field (prime) limb + * @details This relation is a part of system of relations that enforce a formula in non-native field (base field of + * bn254 curve Fp (p - modulus of Fp)). We are trying to compute: + * + * `current_accumulator = previous_accumulator ⋅ x + op + P.x ⋅ v + P.y ⋅ v² +z1 ⋅ v³ + z2 ⋅ v⁴ mod p`. + * + * However, we can only operate in Fr (scalar field of bn254) with + * modulus r. To emulate arithmetic in Fp we rephrase the equation in integers: + * + * `previous_accumulator ⋅ x + op + P.x ⋅ v + P.y ⋅ v² +z1 ⋅ v³ + z2 ⋅ v⁴ - quotient⋅p - current_accumulator = 0` + * + * We can't operate over unbounded integers, but since we know the maximum value of each element (we also treat + * powers of v as new constants constrained to 254 bits) we know that the maximum values of the sum of the positive + * products is ~2⁵¹⁴, so we only need to make sure that no overflow happens till that bound. We calculate integer + * logic until the bound 2²⁷²⋅r (which is more than 2⁵¹⁴) by using the representations modulo 2²⁷² (requires limb + * computation over native scalar field) and r (native scalar field computation). + * + * We perform modulo 2²⁷² computations by separating each of values into 4 68-bit limbs (z1 and z2 are just two + * since they represent the values < 2¹²⁸ and op is just itself). Then we compute the first subrelation (index means + * sublimb and we use 2²⁷² - p instead of -p): + * `previous_accumulator[0]⋅x[0] + op + P.x[0]⋅v[0]+ P.y[0]⋅v²[0] +z1[0] ⋅ v³[0] + z2[0] ⋅ v⁴[0] + + * quotient[0]⋅(-p)[0] - current_accumulator[0] + 2⁶⁸⋅(previous_accumulator[1]⋅x[0]+ P.x[1]⋅v[0]+ P.y[1]⋅v²[0] + * +z1[1] ⋅ v³[0] + z2[1] ⋅ v⁴[0] + quotient[1]⋅(-p)[0] + previous_accumulator[0]⋅x[1] + P.x[0]⋅v[1]+ P.y[0]⋅v²[1] + * +z1[0] ⋅ v³[1] + z2[0] ⋅ v⁴[1] + quotient[0]⋅(-p)[1] - current_accumulator[1]) - 2¹³⁶⋅relation_wide_lower_limb = + * 0` + * + * We show that the evaluation in 2 lower limbs results in relation_wide_lower_limb multiplied by 2¹³⁶. If + * relation_wide_lower_limb is propertly constrained (this is performed in over relations), then that means that the + * lower 136 bits of the result are 0. This is the first subrelation. + * + * We then use the relation_wide_lower_limb as carry and add it to the next expression, computing the evaluation in + * higher bits (carry + combinations of limbs (0,2), (1,1), (2,0), (0,3), (2,1), (1,2), (0,3)) and checking that it + * results in 2¹³⁶⋅relation_wide_higher_limb. This ensures that the logic was sound modulo 2²⁷². This is the second + * subrelation. + * + * Finally, we check that the relation holds in the native field. For this we reconstruct each value, for example: + * `previous_accumulator_native = previous_accumulator[0] + 2⁶⁸⋅previous_accumulator[1] + + * 2¹³⁶⋅previous_accumulator[2] + 2²⁰⁴⋅previous accumulator[3] mod r` + * + * Then the last subrelation is simply checking the interger equation in this native form + * + * @param evals transformed to `evals + C(in(X)...)*scaling_factor` + * @param in an std::array containing the fully extended Univariate edges. + * @param parameters contains beta, gamma, and public_input_delta, .... + * @param scaling_factor optional term to scale the evaluation before adding to evals. + */ + template + void static accumulate(ContainerOverSubrelations& accumulators, + const AllEntitites& in, + const RelationParameters& relation_parameters, + const FF& scaling_factor) + { + + using Accumulator = std::tuple_element_t<0, ContainerOverSubrelations>; + using View = typename Accumulator::View; + + static constexpr size_t NUM_LIMB_BITS = 68; + static constexpr FF shift = FF(uint256_t(1) << NUM_LIMB_BITS); + static constexpr FF shiftx2 = FF(uint256_t(1) << (NUM_LIMB_BITS * 2)); + static constexpr FF shiftx3 = FF(uint256_t(1) << (NUM_LIMB_BITS * 3)); + static constexpr uint512_t MODULUS_U512 = uint512_t(curve::BN254::BaseField::modulus); + static constexpr uint512_t BINARY_BASIS_MODULUS = uint512_t(1) << (NUM_LIMB_BITS << 2); + static constexpr uint512_t NEGATIVE_PRIME_MODULUS = BINARY_BASIS_MODULUS - MODULUS_U512; + static constexpr std::array NEGATIVE_MODULUS_LIMBS = { + FF(NEGATIVE_PRIME_MODULUS.slice(0, NUM_LIMB_BITS).lo), + FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS, NUM_LIMB_BITS * 2).lo), + FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS * 2, NUM_LIMB_BITS * 3).lo), + FF(NEGATIVE_PRIME_MODULUS.slice(NUM_LIMB_BITS * 3, NUM_LIMB_BITS * 4).lo), + -FF(curve::BN254::BaseField::modulus) + }; + + const auto& op = View(in.op); + const auto& p_x_low_limbs = View(in.p_x_low_limbs); + const auto& p_y_low_limbs = View(in.p_y_low_limbs); + const auto& p_x_high_limbs = View(in.p_x_high_limbs); + const auto& p_y_high_limbs = View(in.p_y_high_limbs); + const auto& accumulators_binary_limbs_0 = View(in.accumulators_binary_limbs_0); + const auto& accumulators_binary_limbs_1 = View(in.accumulators_binary_limbs_1); + const auto& accumulators_binary_limbs_2 = View(in.accumulators_binary_limbs_2); + const auto& accumulators_binary_limbs_3 = View(in.accumulators_binary_limbs_3); + const auto& z_low_limbs = View(in.z_low_limbs); + const auto& z_high_limbs = View(in.z_high_limbs); + const auto& quotient_low_binary_limbs = View(in.quotient_low_binary_limbs); + const auto& quotient_high_binary_limbs = View(in.quotient_high_binary_limbs); + const auto& p_x_low_limbs_shift = View(in.p_x_low_limbs_shift); + const auto& p_y_low_limbs_shift = View(in.p_y_low_limbs_shift); + const auto& p_x_high_limbs_shift = View(in.p_x_high_limbs_shift); + const auto& p_y_high_limbs_shift = View(in.p_y_high_limbs_shift); + const auto& accumulators_binary_limbs_0_shift = View(in.accumulators_binary_limbs_0_shift); + const auto& accumulators_binary_limbs_1_shift = View(in.accumulators_binary_limbs_1_shift); + const auto& accumulators_binary_limbs_2_shift = View(in.accumulators_binary_limbs_2_shift); + const auto& accumulators_binary_limbs_3_shift = View(in.accumulators_binary_limbs_3_shift); + const auto& z_low_limbs_shift = View(in.z_low_limbs_shift); + const auto& z_high_limbs_shift = View(in.z_high_limbs_shift); + const auto& quotient_low_binary_limbs_shift = View(in.quotient_low_binary_limbs_shift); + const auto& quotient_high_binary_limbs_shift = View(in.quotient_high_binary_limbs_shift); + const auto& relation_wide_limbs = View(in.relation_wide_limbs); + const auto& relation_wide_limbs_shift = View(in.relation_wide_limbs_shift); + const auto& lagrange_odd = View(in.lagrange_odd); + + // Contribution (1) Computing the mod 2²⁷² relation over lower 136 bits + auto tmp_1 = accumulators_binary_limbs_0_shift * relation_parameters.evaluation_input_x[0] + op + + p_x_low_limbs * relation_parameters.batching_challenge_v[0][0] + + p_y_low_limbs * relation_parameters.batching_challenge_v[1][0] + + z_low_limbs * relation_parameters.batching_challenge_v[2][0] + + z_low_limbs_shift * relation_parameters.batching_challenge_v[3][0] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_0; + tmp_1 += (accumulators_binary_limbs_1_shift * relation_parameters.evaluation_input_x[0] + + accumulators_binary_limbs_0_shift * relation_parameters.evaluation_input_x[1] + + p_x_low_limbs * relation_parameters.batching_challenge_v[0][1] + + p_x_low_limbs_shift * relation_parameters.batching_challenge_v[0][0] + + p_y_low_limbs * relation_parameters.batching_challenge_v[1][1] + + p_y_low_limbs_shift * relation_parameters.batching_challenge_v[1][0] + + z_low_limbs * relation_parameters.batching_challenge_v[2][1] + + z_high_limbs * relation_parameters.batching_challenge_v[2][0] + + z_low_limbs_shift * relation_parameters.batching_challenge_v[3][1] + + z_high_limbs_shift * relation_parameters.batching_challenge_v[3][0] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_1) * + shift; + tmp_1 -= relation_wide_limbs * shiftx2; + tmp_1 *= lagrange_odd; + tmp_1 *= scaling_factor; + std::get<0>(accumulators) += tmp_1; + + // Contribution (2) Computing the 2²⁷² relatioin over higher 136 bits + auto tmp_2 = relation_wide_limbs + + accumulators_binary_limbs_2_shift * relation_parameters.evaluation_input_x[0] + + accumulators_binary_limbs_1_shift * relation_parameters.evaluation_input_x[1] + + accumulators_binary_limbs_0_shift * relation_parameters.evaluation_input_x[2] + + p_x_high_limbs * relation_parameters.batching_challenge_v[0][0] + + p_x_low_limbs_shift * relation_parameters.batching_challenge_v[0][1] + + p_x_low_limbs * relation_parameters.batching_challenge_v[0][2] + + p_y_high_limbs * relation_parameters.batching_challenge_v[1][0] + + p_y_low_limbs_shift * relation_parameters.batching_challenge_v[1][1] + + p_y_low_limbs * relation_parameters.batching_challenge_v[1][2] + + z_high_limbs * relation_parameters.batching_challenge_v[2][1] + + z_low_limbs * relation_parameters.batching_challenge_v[2][2] + + z_high_limbs_shift * relation_parameters.batching_challenge_v[3][1] + + z_low_limbs_shift * relation_parameters.batching_challenge_v[3][2] + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] - accumulators_binary_limbs_2; + tmp_2 += (accumulators_binary_limbs_3_shift * relation_parameters.evaluation_input_x[0] + + accumulators_binary_limbs_2_shift * relation_parameters.evaluation_input_x[1] + + accumulators_binary_limbs_1_shift * relation_parameters.evaluation_input_x[2] + + accumulators_binary_limbs_0_shift * relation_parameters.evaluation_input_x[3] + + p_x_high_limbs_shift * relation_parameters.batching_challenge_v[0][0] + + p_x_high_limbs * relation_parameters.batching_challenge_v[0][1] + + p_x_low_limbs_shift * relation_parameters.batching_challenge_v[0][2] + + p_x_low_limbs * relation_parameters.batching_challenge_v[0][3] + + p_y_high_limbs_shift * relation_parameters.batching_challenge_v[1][0] + + p_y_high_limbs * relation_parameters.batching_challenge_v[1][1] + + p_y_low_limbs_shift * relation_parameters.batching_challenge_v[1][2] + + p_y_low_limbs * relation_parameters.batching_challenge_v[1][3] + + z_high_limbs * relation_parameters.batching_challenge_v[2][2] + + z_low_limbs * relation_parameters.batching_challenge_v[2][3] + + z_high_limbs_shift * relation_parameters.batching_challenge_v[3][2] + + z_low_limbs_shift * relation_parameters.batching_challenge_v[3][3] + + quotient_high_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[2] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[3] - accumulators_binary_limbs_3) * + shift; + tmp_2 -= relation_wide_limbs_shift * shiftx2; + tmp_2 *= lagrange_odd; + tmp_2 *= scaling_factor; + std::get<1>(accumulators) += tmp_2; + + // Reconstructing native versions of values + auto reconstructed_p_x = + (p_x_low_limbs + p_x_low_limbs_shift * shift + p_x_high_limbs * shiftx2 + p_x_high_limbs_shift * shiftx3); + auto reconstructed_p_y = + (p_y_low_limbs + p_y_low_limbs_shift * shift + p_y_high_limbs * shiftx2 + p_y_high_limbs_shift * shiftx3); + auto reconstructed_previous_accumulator = + (accumulators_binary_limbs_0_shift + accumulators_binary_limbs_1_shift * shift + + accumulators_binary_limbs_2_shift * shiftx2 + accumulators_binary_limbs_3_shift * shiftx3); + auto reconstructed_current_accumulator = + (accumulators_binary_limbs_0 + accumulators_binary_limbs_1 * shift + accumulators_binary_limbs_2 * shiftx2 + + accumulators_binary_limbs_3 * shiftx3); + auto reconstructed_z1 = (z_low_limbs + z_high_limbs * shift); + auto reconstructed_z2 = (z_low_limbs_shift + z_high_limbs_shift * shift); + auto reconstructed_quotient = + (quotient_low_binary_limbs + quotient_low_binary_limbs_shift * shift + + quotient_high_binary_limbs * shiftx2 + quotient_high_binary_limbs_shift * shiftx3); + + // Contribution (3). Evaluating integer relation over native field + auto tmp_3 = reconstructed_previous_accumulator * relation_parameters.evaluation_input_x[4] + op + + reconstructed_p_x * relation_parameters.batching_challenge_v[0][4] + + reconstructed_p_y * relation_parameters.batching_challenge_v[1][4] + + reconstructed_z1 * relation_parameters.batching_challenge_v[2][4] + + reconstructed_z2 * relation_parameters.batching_challenge_v[3][4] + + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator; + tmp_3 *= lagrange_odd; + tmp_3 *= scaling_factor; + std::get<2>(accumulators) += tmp_3; + }; +}; + +template +using GoblinTranslatorNonNativeFieldRelation = Relation>; + +} // namespace proof_system diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp index 4f218c0b709..f52aaa40718 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp @@ -9,6 +9,8 @@ namespace proof_system { */ template struct RelationParameters { static const int NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR = 4; + static const int NUM_NATIVE_LIMBS_IN_GOBLIN_TRANSLATOR = 1; + static const int NUM_CHALLENGE_POWERS_IN_GOBLIN_TRANSLATOR = 4; FF eta = FF(0); // Lookup FF beta = FF(0); // Permutation + Lookup FF gamma = FF(0); // Permutation + Lookup @@ -20,6 +22,12 @@ template struct RelationParameters { // We can remove this by modifying the relation, but increases complexity FF eccvm_set_permutation_delta = 0; std::array accumulated_result = { FF(0) }; // Goblin Translator + std::array evaluation_input_x = { + FF(0) + }; // Goblin Translator + std::array, + NUM_CHALLENGE_POWERS_IN_GOBLIN_TRANSLATOR> + batching_challenge_v = { { { FF(0) } } }; static RelationParameters get_random() { @@ -38,6 +46,32 @@ template struct RelationParameters { FF::random_element(), FF::random_element(), FF::random_element(), FF::random_element() }; + result.evaluation_input_x = { + FF::random_element(), FF::random_element(), FF::random_element(), FF::random_element(), FF::random_element() + }; + result.batching_challenge_v = { + std::array{ FF::random_element(), + FF::random_element(), + FF::random_element(), + FF::random_element(), + FF::random_element() }, + { FF::random_element(), + FF::random_element(), + FF::random_element(), + FF::random_element(), + FF::random_element() }, + { FF::random_element(), + FF::random_element(), + FF::random_element(), + FF::random_element(), + FF::random_element() }, + { FF::random_element(), + FF::random_element(), + FF::random_element(), + FF::random_element(), + FF::random_element() }, + }; + return result; } }; From 1dd8976bdee88181d7919a7affef172bf096734e Mon Sep 17 00:00:00 2001 From: Rumata888 Date: Mon, 16 Oct 2023 13:39:21 +0000 Subject: [PATCH 2/5] A few more comments --- .../goblin_translator_relation_consistency.test.cpp | 2 ++ .../relations/non_native_field_relation.hpp | 12 +++++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp index af031e3197f..d74d23c7232 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp @@ -1063,6 +1063,7 @@ TEST_F(GoblinTranslatorRelationConsistency, NonNativeFieldRelation) relation_wide_limbs * shiftx2) * lagrange_odd; + // Higher wide limb subrelation expected_values[1] = (relation_wide_limbs + accumulators_binary_limbs_2_shift * parameters.evaluation_input_x[0] + accumulators_binary_limbs_1_shift * parameters.evaluation_input_x[1] + @@ -1119,6 +1120,7 @@ TEST_F(GoblinTranslatorRelationConsistency, NonNativeFieldRelation) (quotient_low_binary_limbs + quotient_low_binary_limbs_shift * shift + quotient_high_binary_limbs * shiftx2 + quotient_high_binary_limbs_shift * shiftx3); + // Native field relation expected_values[2] = (reconstructed_previous_accumulator * parameters.evaluation_input_x[4] + op + reconstructed_p_x * parameters.batching_challenge_v[0][4] + reconstructed_p_y * parameters.batching_challenge_v[1][4] + diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp index 8ef722494ab..33976db42fb 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp @@ -207,11 +207,13 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { quotient_high_binary_limbs * shiftx2 + quotient_high_binary_limbs_shift * shiftx3); // Contribution (3). Evaluating integer relation over native field - auto tmp_3 = reconstructed_previous_accumulator * relation_parameters.evaluation_input_x[4] + op + - reconstructed_p_x * relation_parameters.batching_challenge_v[0][4] + - reconstructed_p_y * relation_parameters.batching_challenge_v[1][4] + - reconstructed_z1 * relation_parameters.batching_challenge_v[2][4] + - reconstructed_z2 * relation_parameters.batching_challenge_v[3][4] + + const size_t NATIVE_LIMB_INDEX = + 4; // This value in relation parameters is dependent on the other 4 and is only precomputed for efficiency + auto tmp_3 = reconstructed_previous_accumulator * relation_parameters.evaluation_input_x[NATIVE_LIMB_INDEX] + + op + reconstructed_p_x * relation_parameters.batching_challenge_v[0][NATIVE_LIMB_INDEX] + + reconstructed_p_y * relation_parameters.batching_challenge_v[1][NATIVE_LIMB_INDEX] + + reconstructed_z1 * relation_parameters.batching_challenge_v[2][NATIVE_LIMB_INDEX] + + reconstructed_z2 * relation_parameters.batching_challenge_v[3][NATIVE_LIMB_INDEX] + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator; tmp_3 *= lagrange_odd; tmp_3 *= scaling_factor; From ce1e83022346c13895ce7cc65f33fe200bfe72c6 Mon Sep 17 00:00:00 2001 From: codygunton Date: Wed, 18 Oct 2023 23:58:50 +0000 Subject: [PATCH 3/5] Suggested changes. --- .../relations/non_native_field_relation.hpp | 263 +++++++++++------- .../relations/relation_parameters.hpp | 6 +- 2 files changed, 164 insertions(+), 105 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp index 33976db42fb..bce98b0661b 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp @@ -11,7 +11,6 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { using FF = FF_; // 1 + polynomial degree of this relation - static constexpr size_t RELATION_LENGTH = 3; // degree((lagrange_odd-1)(a*b-c*d)) = 2 static constexpr std::array SUBRELATION_LENGTHS{ 3, // Lower wide limb subrelation (checks result is 0 mod 2¹³⁶) 3, // Higher wide limb subrelation (checks result is 0 in higher mod 2¹³⁶), @@ -40,15 +39,18 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { * We perform modulo 2²⁷² computations by separating each of values into 4 68-bit limbs (z1 and z2 are just two * since they represent the values < 2¹²⁸ and op is just itself). Then we compute the first subrelation (index means * sublimb and we use 2²⁷² - p instead of -p): - * `previous_accumulator[0]⋅x[0] + op + P.x[0]⋅v[0]+ P.y[0]⋅v²[0] +z1[0] ⋅ v³[0] + z2[0] ⋅ v⁴[0] + - * quotient[0]⋅(-p)[0] - current_accumulator[0] + 2⁶⁸⋅(previous_accumulator[1]⋅x[0]+ P.x[1]⋅v[0]+ P.y[1]⋅v²[0] - * +z1[1] ⋅ v³[0] + z2[1] ⋅ v⁴[0] + quotient[1]⋅(-p)[0] + previous_accumulator[0]⋅x[1] + P.x[0]⋅v[1]+ P.y[0]⋅v²[1] - * +z1[0] ⋅ v³[1] + z2[0] ⋅ v⁴[1] + quotient[0]⋅(-p)[1] - current_accumulator[1]) - 2¹³⁶⋅relation_wide_lower_limb = - * 0` + * ` previous_accumulator[0]⋅x[0] + op + P.x[0]⋅v[0] + P.y[0]⋅v²[0] + z1[0] ⋅ v³[0] + z2[0] ⋅ v⁴[0] + * + quotient[0]⋅(-p)[0] - current_accumulator[0] + * + 2⁶⁸⋅(previous_accumulator[1]⋅x[0] + P.x[1]⋅v[0] + P.y[1]⋅v²[0] + z1[1] ⋅ v³[0] + z2[1] ⋅ v⁴[0] + * + quotient[1]⋅(-p)[0] + + * previous_accumulator[0]⋅x[1] + P.x[0]⋅v[1] + P.y[0]⋅v²[1] + z1[0] ⋅ v³[1] + z2[0] ⋅ v⁴[1] + * + quotient[0]⋅(-p)[1] - current_accumulator[1]) + * - 2¹³⁶⋅relation_wide_lower_limb + * == 0` * * We show that the evaluation in 2 lower limbs results in relation_wide_lower_limb multiplied by 2¹³⁶. If - * relation_wide_lower_limb is propertly constrained (this is performed in over relations), then that means that the - * lower 136 bits of the result are 0. This is the first subrelation. + * relation_wide_lower_limb is propertly constrained (this is performed in other relations), then that means that + * the lower 136 bits of the result are 0. This is the first subrelation. * * We then use the relation_wide_lower_limb as carry and add it to the next expression, computing the evaluation in * higher bits (carry + combinations of limbs (0,2), (1,1), (2,0), (0,3), (2,1), (1,2), (0,3)) and checking that it @@ -56,10 +58,10 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { * subrelation. * * Finally, we check that the relation holds in the native field. For this we reconstruct each value, for example: - * `previous_accumulator_native = previous_accumulator[0] + 2⁶⁸⋅previous_accumulator[1] + - * 2¹³⁶⋅previous_accumulator[2] + 2²⁰⁴⋅previous accumulator[3] mod r` + * `previous_accumulator_native = previous_accumulator[0] + 2⁶⁸ ⋅previous_accumulator[1] + * + 2¹³⁶⋅previous_accumulator[2] + 2²⁰⁴⋅previous accumulator[3] mod r` * - * Then the last subrelation is simply checking the interger equation in this native form + * Then the last subrelation is simply checking the integer equation in this native form.g * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. @@ -91,6 +93,34 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { -FF(curve::BN254::BaseField::modulus) }; + const auto& evaluation_input_x_0 = relation_parameters.evaluation_input_x[0]; + const auto& evaluation_input_x_1 = relation_parameters.evaluation_input_x[1]; + const auto& evaluation_input_x_2 = relation_parameters.evaluation_input_x[2]; + const auto& evaluation_input_x_3 = relation_parameters.evaluation_input_x[3]; + const auto& evaluation_input_x_4 = relation_parameters.evaluation_input_x[4]; + // for j < 4, v_i_j is the j-th limb of v^{1+i} + // v_i_4 is v^{1+i} in the native field + const auto& v_0_0 = relation_parameters.batching_challenge_v[0][0]; + const auto& v_0_1 = relation_parameters.batching_challenge_v[0][1]; + const auto& v_0_2 = relation_parameters.batching_challenge_v[0][2]; + const auto& v_0_3 = relation_parameters.batching_challenge_v[0][3]; + const auto& v_0_4 = relation_parameters.batching_challenge_v[0][4]; + const auto& v_1_0 = relation_parameters.batching_challenge_v[1][0]; + const auto& v_1_1 = relation_parameters.batching_challenge_v[1][1]; + const auto& v_1_2 = relation_parameters.batching_challenge_v[1][2]; + const auto& v_1_3 = relation_parameters.batching_challenge_v[1][3]; + const auto& v_1_4 = relation_parameters.batching_challenge_v[1][4]; + const auto& v_2_0 = relation_parameters.batching_challenge_v[2][0]; + const auto& v_2_1 = relation_parameters.batching_challenge_v[2][1]; + const auto& v_2_2 = relation_parameters.batching_challenge_v[2][2]; + const auto& v_2_3 = relation_parameters.batching_challenge_v[2][3]; + const auto& v_2_4 = relation_parameters.batching_challenge_v[2][4]; + const auto& v_3_0 = relation_parameters.batching_challenge_v[3][0]; + const auto& v_3_1 = relation_parameters.batching_challenge_v[3][1]; + const auto& v_3_2 = relation_parameters.batching_challenge_v[3][2]; + const auto& v_3_3 = relation_parameters.batching_challenge_v[3][3]; + const auto& v_3_4 = relation_parameters.batching_challenge_v[3][4]; + const auto& op = View(in.op); const auto& p_x_low_limbs = View(in.p_x_low_limbs); const auto& p_y_low_limbs = View(in.p_y_low_limbs); @@ -121,103 +151,132 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { const auto& lagrange_odd = View(in.lagrange_odd); // Contribution (1) Computing the mod 2²⁷² relation over lower 136 bits - auto tmp_1 = accumulators_binary_limbs_0_shift * relation_parameters.evaluation_input_x[0] + op + - p_x_low_limbs * relation_parameters.batching_challenge_v[0][0] + - p_y_low_limbs * relation_parameters.batching_challenge_v[1][0] + - z_low_limbs * relation_parameters.batching_challenge_v[2][0] + - z_low_limbs_shift * relation_parameters.batching_challenge_v[3][0] + - quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_0; - tmp_1 += (accumulators_binary_limbs_1_shift * relation_parameters.evaluation_input_x[0] + - accumulators_binary_limbs_0_shift * relation_parameters.evaluation_input_x[1] + - p_x_low_limbs * relation_parameters.batching_challenge_v[0][1] + - p_x_low_limbs_shift * relation_parameters.batching_challenge_v[0][0] + - p_y_low_limbs * relation_parameters.batching_challenge_v[1][1] + - p_y_low_limbs_shift * relation_parameters.batching_challenge_v[1][0] + - z_low_limbs * relation_parameters.batching_challenge_v[2][1] + - z_high_limbs * relation_parameters.batching_challenge_v[2][0] + - z_low_limbs_shift * relation_parameters.batching_challenge_v[3][1] + - z_high_limbs_shift * relation_parameters.batching_challenge_v[3][0] + - quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + - quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] - accumulators_binary_limbs_1) * - shift; - tmp_1 -= relation_wide_limbs * shiftx2; - tmp_1 *= lagrange_odd; - tmp_1 *= scaling_factor; - std::get<0>(accumulators) += tmp_1; - - // Contribution (2) Computing the 2²⁷² relatioin over higher 136 bits - auto tmp_2 = relation_wide_limbs + - accumulators_binary_limbs_2_shift * relation_parameters.evaluation_input_x[0] + - accumulators_binary_limbs_1_shift * relation_parameters.evaluation_input_x[1] + - accumulators_binary_limbs_0_shift * relation_parameters.evaluation_input_x[2] + - p_x_high_limbs * relation_parameters.batching_challenge_v[0][0] + - p_x_low_limbs_shift * relation_parameters.batching_challenge_v[0][1] + - p_x_low_limbs * relation_parameters.batching_challenge_v[0][2] + - p_y_high_limbs * relation_parameters.batching_challenge_v[1][0] + - p_y_low_limbs_shift * relation_parameters.batching_challenge_v[1][1] + - p_y_low_limbs * relation_parameters.batching_challenge_v[1][2] + - z_high_limbs * relation_parameters.batching_challenge_v[2][1] + - z_low_limbs * relation_parameters.batching_challenge_v[2][2] + - z_high_limbs_shift * relation_parameters.batching_challenge_v[3][1] + - z_low_limbs_shift * relation_parameters.batching_challenge_v[3][2] + - quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + - quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[1] + - quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] - accumulators_binary_limbs_2; - tmp_2 += (accumulators_binary_limbs_3_shift * relation_parameters.evaluation_input_x[0] + - accumulators_binary_limbs_2_shift * relation_parameters.evaluation_input_x[1] + - accumulators_binary_limbs_1_shift * relation_parameters.evaluation_input_x[2] + - accumulators_binary_limbs_0_shift * relation_parameters.evaluation_input_x[3] + - p_x_high_limbs_shift * relation_parameters.batching_challenge_v[0][0] + - p_x_high_limbs * relation_parameters.batching_challenge_v[0][1] + - p_x_low_limbs_shift * relation_parameters.batching_challenge_v[0][2] + - p_x_low_limbs * relation_parameters.batching_challenge_v[0][3] + - p_y_high_limbs_shift * relation_parameters.batching_challenge_v[1][0] + - p_y_high_limbs * relation_parameters.batching_challenge_v[1][1] + - p_y_low_limbs_shift * relation_parameters.batching_challenge_v[1][2] + - p_y_low_limbs * relation_parameters.batching_challenge_v[1][3] + - z_high_limbs * relation_parameters.batching_challenge_v[2][2] + - z_low_limbs * relation_parameters.batching_challenge_v[2][3] + - z_high_limbs_shift * relation_parameters.batching_challenge_v[3][2] + - z_low_limbs_shift * relation_parameters.batching_challenge_v[3][3] + - quotient_high_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] + - quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + - quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[2] + - quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[3] - accumulators_binary_limbs_3) * - shift; - tmp_2 -= relation_wide_limbs_shift * shiftx2; - tmp_2 *= lagrange_odd; - tmp_2 *= scaling_factor; - std::get<1>(accumulators) += tmp_2; + // clang-format off + // the index-0 limb + auto tmp = accumulators_binary_limbs_0_shift * evaluation_input_x_0 + + op + + p_x_low_limbs * v_0_0 + + p_y_low_limbs * v_1_0 + + z_low_limbs * v_2_0 + + z_low_limbs_shift * v_3_0 + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + - accumulators_binary_limbs_0; + + // the index-1 limb + tmp += shift + * (accumulators_binary_limbs_1_shift * evaluation_input_x_0 + + accumulators_binary_limbs_0_shift * evaluation_input_x_1 + + p_x_low_limbs * v_0_1 + + p_x_low_limbs_shift * v_0_0 + + p_y_low_limbs * v_1_1 + + p_y_low_limbs_shift * v_1_0 + + z_low_limbs * v_2_1 + + z_high_limbs * v_2_0 + + z_low_limbs_shift * v_3_1 + + z_high_limbs_shift * v_3_0 + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] + - accumulators_binary_limbs_1); + // clang-format on + // subtract large value; vanishing shows the desired relation holds on low 136-bit limb + tmp -= relation_wide_limbs * shiftx2; + tmp *= lagrange_odd; + tmp *= scaling_factor; + std::get<0>(accumulators) += tmp; + + // Contribution (2) Computing the 2²⁷² relation over higher 136 bits + // why declare another temporary? + // clang-format off + // the index-2 limb, with a carry from the previous calculation + tmp = relation_wide_limbs + + accumulators_binary_limbs_2_shift * evaluation_input_x_0 + + accumulators_binary_limbs_1_shift * evaluation_input_x_1 + + accumulators_binary_limbs_0_shift * evaluation_input_x_2 + + p_x_high_limbs * v_0_0 + + p_x_low_limbs_shift * v_0_1 + + p_x_low_limbs * v_0_2 + + p_y_high_limbs * v_1_0 + + p_y_low_limbs_shift * v_1_1 + + p_y_low_limbs * v_1_2 + + z_high_limbs * v_2_1 + + z_low_limbs * v_2_2 + + z_high_limbs_shift * v_3_1 + + z_low_limbs_shift * v_3_2 + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] + - accumulators_binary_limbs_2; + + // the index-2 limb + tmp += shift + * (accumulators_binary_limbs_2_shift * evaluation_input_x_1 + + accumulators_binary_limbs_1_shift * evaluation_input_x_2 + + accumulators_binary_limbs_0_shift * evaluation_input_x_3 + + p_x_high_limbs_shift * v_0_0 + + p_x_high_limbs * v_0_1 + + p_x_low_limbs_shift * v_0_2 + + p_x_low_limbs * v_0_3 + + p_y_high_limbs_shift * v_1_0 + + p_y_high_limbs * v_1_1 + + p_y_low_limbs_shift * v_1_2 + + p_y_low_limbs * v_1_3 + + z_high_limbs * v_2_2 + + z_low_limbs * v_2_3 + + z_high_limbs_shift * v_3_2 + + z_low_limbs_shift * v_3_3 + + quotient_high_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[0] + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[2] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[3] + - accumulators_binary_limbs_3); + // clang-format on + // subtract large value; vanishing shows the desired relation holds on high 136-bit limb + tmp -= relation_wide_limbs_shift * shiftx2; + tmp *= lagrange_odd; + tmp *= scaling_factor; + std::get<1>(accumulators) += tmp; + + const auto reconstruct_from_two = [](const auto& l0, const auto& l1) { return l0 + l1 * shift; }; + + const auto reconstruct_from_four = [](const auto& l0, const auto& l1, const auto& l2, const auto& l3) { + return l0 + l1 * shift + l2 * shiftx2 + l3 * shiftx3; + }; // Reconstructing native versions of values auto reconstructed_p_x = - (p_x_low_limbs + p_x_low_limbs_shift * shift + p_x_high_limbs * shiftx2 + p_x_high_limbs_shift * shiftx3); + reconstruct_from_four(p_x_low_limbs, p_x_low_limbs_shift, p_x_high_limbs, p_x_high_limbs_shift); auto reconstructed_p_y = - (p_y_low_limbs + p_y_low_limbs_shift * shift + p_y_high_limbs * shiftx2 + p_y_high_limbs_shift * shiftx3); - auto reconstructed_previous_accumulator = - (accumulators_binary_limbs_0_shift + accumulators_binary_limbs_1_shift * shift + - accumulators_binary_limbs_2_shift * shiftx2 + accumulators_binary_limbs_3_shift * shiftx3); - auto reconstructed_current_accumulator = - (accumulators_binary_limbs_0 + accumulators_binary_limbs_1 * shift + accumulators_binary_limbs_2 * shiftx2 + - accumulators_binary_limbs_3 * shiftx3); - auto reconstructed_z1 = (z_low_limbs + z_high_limbs * shift); - auto reconstructed_z2 = (z_low_limbs_shift + z_high_limbs_shift * shift); - auto reconstructed_quotient = - (quotient_low_binary_limbs + quotient_low_binary_limbs_shift * shift + - quotient_high_binary_limbs * shiftx2 + quotient_high_binary_limbs_shift * shiftx3); + reconstruct_from_four(p_y_low_limbs, p_y_low_limbs_shift, p_y_high_limbs, p_y_high_limbs_shift); + auto reconstructed_previous_accumulator = reconstruct_from_four(accumulators_binary_limbs_0_shift, + accumulators_binary_limbs_1_shift, + accumulators_binary_limbs_2_shift, + accumulators_binary_limbs_3_shift); + auto reconstructed_current_accumulator = reconstruct_from_four(accumulators_binary_limbs_0, + accumulators_binary_limbs_1, + accumulators_binary_limbs_2, + accumulators_binary_limbs_3); + auto reconstructed_z1 = reconstruct_from_two(z_low_limbs, z_high_limbs); + auto reconstructed_z2 = reconstruct_from_two(z_low_limbs_shift, z_high_limbs_shift); + auto reconstructed_quotient = reconstruct_from_four(quotient_low_binary_limbs, + quotient_low_binary_limbs_shift, + quotient_high_binary_limbs, + quotient_high_binary_limbs_shift); // Contribution (3). Evaluating integer relation over native field - const size_t NATIVE_LIMB_INDEX = - 4; // This value in relation parameters is dependent on the other 4 and is only precomputed for efficiency - auto tmp_3 = reconstructed_previous_accumulator * relation_parameters.evaluation_input_x[NATIVE_LIMB_INDEX] + - op + reconstructed_p_x * relation_parameters.batching_challenge_v[0][NATIVE_LIMB_INDEX] + - reconstructed_p_y * relation_parameters.batching_challenge_v[1][NATIVE_LIMB_INDEX] + - reconstructed_z1 * relation_parameters.batching_challenge_v[2][NATIVE_LIMB_INDEX] + - reconstructed_z2 * relation_parameters.batching_challenge_v[3][NATIVE_LIMB_INDEX] + - reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] - reconstructed_current_accumulator; - tmp_3 *= lagrange_odd; - tmp_3 *= scaling_factor; - std::get<2>(accumulators) += tmp_3; + // clang-format off + // the native limb index is 4 + tmp = reconstructed_previous_accumulator * evaluation_input_x_4 + + op + + reconstructed_p_x * v_0_4 + + reconstructed_p_y * v_1_4 + + reconstructed_z1 * v_2_4 + + reconstructed_z2 * v_3_4 + + reconstructed_quotient * NEGATIVE_MODULUS_LIMBS[4] + - reconstructed_current_accumulator; + // clang-format on + tmp *= lagrange_odd; + tmp *= scaling_factor; + std::get<2>(accumulators) += tmp; }; }; diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp index f52aaa40718..678f77d4909 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp @@ -8,9 +8,9 @@ namespace proof_system { * @tparam FF */ template struct RelationParameters { - static const int NUM_BINARY_LIMBS_IN_GOBLIN_TRANSLATOR = 4; - static const int NUM_NATIVE_LIMBS_IN_GOBLIN_TRANSLATOR = 1; - static const int NUM_CHALLENGE_POWERS_IN_GOBLIN_TRANSLATOR = 4; + 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; FF eta = FF(0); // Lookup FF beta = FF(0); // Permutation + Lookup FF gamma = FF(0); // Permutation + Lookup From 1a1260d1241582c4901d1df3dbe700097fe43342 Mon Sep 17 00:00:00 2001 From: codygunton Date: Thu, 19 Oct 2023 03:55:06 +0000 Subject: [PATCH 4/5] Reinstate line dropped in reorg. --- .../relations/non_native_field_relation.hpp | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp index bce98b0661b..71e21ce4cbc 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp @@ -154,13 +154,13 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { // clang-format off // the index-0 limb auto tmp = accumulators_binary_limbs_0_shift * evaluation_input_x_0 - + op - + p_x_low_limbs * v_0_0 - + p_y_low_limbs * v_1_0 - + z_low_limbs * v_2_0 - + z_low_limbs_shift * v_3_0 - + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] - - accumulators_binary_limbs_0; + + op + + p_x_low_limbs * v_0_0 + + p_y_low_limbs * v_1_0 + + z_low_limbs * v_2_0 + + z_low_limbs_shift * v_3_0 + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + - accumulators_binary_limbs_0; // the index-1 limb tmp += shift @@ -189,27 +189,28 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { // clang-format off // the index-2 limb, with a carry from the previous calculation tmp = relation_wide_limbs - + accumulators_binary_limbs_2_shift * evaluation_input_x_0 - + accumulators_binary_limbs_1_shift * evaluation_input_x_1 - + accumulators_binary_limbs_0_shift * evaluation_input_x_2 - + p_x_high_limbs * v_0_0 - + p_x_low_limbs_shift * v_0_1 - + p_x_low_limbs * v_0_2 - + p_y_high_limbs * v_1_0 - + p_y_low_limbs_shift * v_1_1 - + p_y_low_limbs * v_1_2 - + z_high_limbs * v_2_1 - + z_low_limbs * v_2_2 - + z_high_limbs_shift * v_3_1 - + z_low_limbs_shift * v_3_2 - + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] - + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[1] - + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] - - accumulators_binary_limbs_2; + + accumulators_binary_limbs_2_shift * evaluation_input_x_0 + + accumulators_binary_limbs_1_shift * evaluation_input_x_1 + + accumulators_binary_limbs_0_shift * evaluation_input_x_2 + + p_x_high_limbs * v_0_0 + + p_x_low_limbs_shift * v_0_1 + + p_x_low_limbs * v_0_2 + + p_y_high_limbs * v_1_0 + + p_y_low_limbs_shift * v_1_1 + + p_y_low_limbs * v_1_2 + + z_high_limbs * v_2_1 + + z_low_limbs * v_2_2 + + z_high_limbs_shift * v_3_1 + + z_low_limbs_shift * v_3_2 + + quotient_high_binary_limbs * NEGATIVE_MODULUS_LIMBS[0] + + quotient_low_binary_limbs_shift * NEGATIVE_MODULUS_LIMBS[1] + + quotient_low_binary_limbs * NEGATIVE_MODULUS_LIMBS[2] + - accumulators_binary_limbs_2; // the index-2 limb tmp += shift - * (accumulators_binary_limbs_2_shift * evaluation_input_x_1 + * (accumulators_binary_limbs_3_shift * evaluation_input_x_0 + + accumulators_binary_limbs_2_shift * evaluation_input_x_1 + accumulators_binary_limbs_1_shift * evaluation_input_x_2 + accumulators_binary_limbs_0_shift * evaluation_input_x_3 + p_x_high_limbs_shift * v_0_0 From bca7ef42945b4d7f731c3343374c4d5bb0238f7d Mon Sep 17 00:00:00 2001 From: Rumata888 Date: Thu, 19 Oct 2023 12:20:49 +0000 Subject: [PATCH 5/5] Added comments for Cody --- .../goblin_translator_relation_consistency.test.cpp | 2 +- .../relations/non_native_field_relation.hpp | 13 ++++++++++++- .../proof_system/relations/relation_parameters.hpp | 11 ++++++++--- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp index d74d23c7232..59e242fa167 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/goblin_translator_relation_consistency.test.cpp @@ -1000,7 +1000,7 @@ TEST_F(GoblinTranslatorRelationConsistency, NonNativeFieldRelation) }; using Relation = GoblinTranslatorNonNativeFieldRelation; - using RelationValues = typename Relation::ArrayOfValuesOverSubrelations; + using RelationValues = typename Relation::SumcheckArrayOfValuesOverSubrelations; const InputElements input_elements = random_inputs ? InputElements::get_random() : InputElements::get_special(); diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp index 71e21ce4cbc..92ed2f2d3d5 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/non_native_field_relation.hpp @@ -48,6 +48,10 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { * - 2¹³⁶⋅relation_wide_lower_limb * == 0` * + * We use 2 relation wide limbs which are called wide, because they contain the results of products (like you needed + * EDX:EAX in x86 to hold the product results of two standard 32-bit registers) and because they are constrained to + * 84 bits instead of 68 or lower by other relations. + * * We show that the evaluation in 2 lower limbs results in relation_wide_lower_limb multiplied by 2¹³⁶. If * relation_wide_lower_limb is propertly constrained (this is performed in other relations), then that means that * the lower 136 bits of the result are 0. This is the first subrelation. @@ -61,7 +65,14 @@ template class GoblinTranslatorNonNativeFieldRelationImpl { * `previous_accumulator_native = previous_accumulator[0] + 2⁶⁸ ⋅previous_accumulator[1] * + 2¹³⁶⋅previous_accumulator[2] + 2²⁰⁴⋅previous accumulator[3] mod r` * - * Then the last subrelation is simply checking the integer equation in this native form.g + * Then the last subrelation is simply checking the integer equation in this native form + * + * All of these subrelations are multiplied by lagrange_odd, which is a polynomial with 1 at each odd index less + * than the size of the mini-circuit (16 times smaller than the final circuit and the only part over which we need + * to calculate non-permutation relations). All other indices are set to zero. Each EccOpQueue entry (operation) + * occupies 2 rows in bn254 transcripts. So the Goblin Translator VM has a 2-row cycle and we need to switch the + * checks being performed depending on which row we are at right now. We have half a cycle of accumulation, + * where we perform this computation, and half a cycle where we just copy accumulator data. * * @param evals transformed to `evals + C(in(X)...)*scaling_factor` * @param in an std::array containing the fully extended Univariate edges. diff --git a/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp b/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp index 678f77d4909..59e76b613c4 100644 --- a/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp +++ b/barretenberg/cpp/src/barretenberg/proof_system/relations/relation_parameters.hpp @@ -21,13 +21,18 @@ template struct RelationParameters { // eccvm_set_permutation_delta is used in the set membership gadget in eccvm/ecc_set_relation.hpp // We can remove this by modifying the relation, but increases complexity FF eccvm_set_permutation_delta = 0; - std::array accumulated_result = { FF(0) }; // Goblin Translator + std::array accumulated_result = { + FF(0), FF(0), FF(0), FF(0) + }; // Goblin Translator std::array evaluation_input_x = { - FF(0) + FF(0), FF(0), FF(0), FF(0), FF(0) }; // Goblin Translator std::array, NUM_CHALLENGE_POWERS_IN_GOBLIN_TRANSLATOR> - batching_challenge_v = { { { FF(0) } } }; + batching_challenge_v = { { { FF(0), FF(0), FF(0), FF(0), FF(0) }, + { FF(0), FF(0), FF(0), FF(0), FF(0) }, + { FF(0), FF(0), FF(0), FF(0), FF(0) }, + { FF(0), FF(0), FF(0), FF(0), FF(0) } } }; static RelationParameters get_random() {