From 35f82e975673472178214a84f0e8e37c8280bfcc Mon Sep 17 00:00:00 2001 From: Vasiliy Olekhov Date: Fri, 19 Apr 2024 15:51:31 +0300 Subject: [PATCH] wip #355 --- .../weierstrass/plonk/mnt4_miller_loop.hpp | 120 +++++++++++++----- test/CMakeLists.txt | 1 + 2 files changed, 87 insertions(+), 34 deletions(-) diff --git a/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt4_miller_loop.hpp b/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt4_miller_loop.hpp index 2c4ef89f2..be2299992 100644 --- a/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt4_miller_loop.hpp +++ b/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt4_miller_loop.hpp @@ -28,6 +28,7 @@ #ifndef CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_MNT4_MILLER_LOOP_HPP #define CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_MNT4_MILLER_LOOP_HPP +#include #include #include @@ -43,18 +44,19 @@ #include #include +#include namespace nil { namespace blueprint { namespace components { namespace detail { - template - std::vector base(T x) { - std::vector res = {(unsigned short int)(x % B)}; + template + std::vector base(T x) { + std::vector res = {(std::uint8_t)(x % B)}; if (x > 0) { x /= B; while (x > 0) { - res.insert(res.begin(), x % B); + res.insert(res.begin(), std::uint8_t(x % B)); x /= B; } } @@ -111,8 +113,6 @@ namespace nil { using var = typename component_type::var; using manifest_type = plonk_component_manifest; - using point_addition_type = mnt4_g2_point_addition< - crypto3::zk::snark::plonk_constraint_system>; class gate_manifest_type : public component_gate_manifest { public: @@ -130,8 +130,7 @@ namespace nil { std::size_t lookup_column_amount) { gate_manifest manifest = - gate_manifest(gate_manifest_type(witness_amount)) - .merge_with(point_addition_type::get_gate_manifest(witness_amount,lookup_column_amount)); + gate_manifest(gate_manifest_type(witness_amount)); return manifest; } @@ -140,7 +139,7 @@ namespace nil { static manifest_type manifest = manifest_type( std::shared_ptr(new manifest_single_value_param(14)), true // constant column required - ).merge_with(point_addition_type::get_manifest()); + ); return manifest; } @@ -148,7 +147,7 @@ namespace nil { std::size_t witness_amount, std::size_t lookup_column_amount) { - std::vector C_bin = base<2>(C_val); + std::vector C_bin = base<2>(C_val); std::size_t result = 0; @@ -162,7 +161,7 @@ namespace nil { } constexpr static integral_type C_val = mnt4_pairing_params::ate_loop_count; - std::vector C_bin = base<2>(C_val); + std::vector C_bin = base<2>(C_val); constexpr static const std::size_t gates_amount = 2; const std::size_t rows_amount = get_rows_amount(this->witness_amount(), 0); @@ -232,13 +231,11 @@ namespace nil { using policy_type_fp2 = crypto3::algebra::fields::fp2; using fp2_element = typename policy_type_fp2::value_type; using curve_point = std::array; - using point_addition_type = typename component_type::point_addition_type; using curve_type = nil::crypto3::algebra::curves::mnt4<298>; - std::vector C_bin = component.C_bin; + std::vector C_bin = component.C_bin; - point_addition_type point_addition_instance( component._W, component._C, component._PI); value_type xP = var_value(assignment, instance_input.P[0]), @@ -275,10 +272,10 @@ namespace nil { auto insert_row_doubling = [&double_point, &assignment, &component, &start_row_index, &xP, &yP] (fp4_element const& f, curve_point& T, std::size_t row) { - fp4_element x, y, x1, y1, g; + fp4_element x, y, x1, y1, g, three({{3,0},{0,0}}); - x = fp4_element::one() * xP; - y = fp4_element::one() * yP; + x = fp4_element({ {xP, 0}, {0, 0} }); + y = fp4_element({ {yP, 0}, {0, 0} }); // Untwisting: E'/Fp2 -> E/Fp4 // x * u^-1, y * (uv)^-1 @@ -296,13 +293,13 @@ namespace nil { // Y: ((x0,x1),(0,0)) * ((0,0),(1/nr,0)) = ( (0, 0), (x0/nr, x1/nr) ) // // - value_type nri = fp2_element::params_type::non_residue.inversed(); + value_type nri = policy_type_fp2::extension_policy::non_residue.inversed(); x1 = fp4_element({ {T[0].data[1], T[0].data[0]*nri }, {0,0} }); y1 = fp4_element({ {0,0}, {T[1].data[0]*nri, T[1].data[1]*nri}}); - fp4_element a(curve_type::g1_type<>::params_type::a,0,0,0); - g = f.pow(2) * ((3*x1.pow(2) + a)*(x-x1)*((2*y1).inversed()) + y1 - y); + fp4_element a({{curve_type::g1_type<>::params_type::a,0},{0,0}}); + g = f.pow(2) * ((three*x1.pow(2) + a)*(x-x1)*((y1+y1).inversed()) + y1 - y); // f assignment.witness(component.W(0),start_row_index + row) = f.data[0].data[0]; @@ -335,17 +332,17 @@ namespace nil { { fp4_element x, y, x1, y1, x2, y2, l, g; - x = fp4_element::one() * xP; - y = fp4_element::one() * yP; + x = fp4_element({ {xP, 0}, {0, 0} }); + y = fp4_element({ {yP, 0}, {0, 0} }); - value_type nri = fp2_element::params_type::non_residue.inversed(); + value_type nri = policy_type_fp2::extension_policy::non_residue.inversed(); // Untwist T and Q: E'/Fp2 -> E/Fp4 x1 = fp4_element({ {T[0].data[1], T[0].data[0]*nri }, {0,0} }); y1 = fp4_element({ {0, 0}, {T[1].data[0]*nri, T[1].data[1]*nri}}); - x2 = fp4_element({ {xQ[1], xQ[0]*nri }, {0,0} }); - y2 = fp4_element({ {0,0}, {yQ[0]*nri, yQ[1]*nri}}); + x2 = fp4_element({ {Q[0].data[1], Q[0].data[0]*nri }, {0,0} }); + y2 = fp4_element({ {0,0}, {Q[1].data[0]*nri, Q[1].data[1]*nri}}); l = (y2-y1)*(x2-x1).inversed(); g = f * (l*(x-x1) + y1 - y); @@ -386,7 +383,7 @@ namespace nil { for(std::size_t i = 1; i < C_bin.size(); ++i) { f = insert_row_doubling(f, T, rel_row++); if (C_bin[i]) { - f = insert_row_doubling(f, T, rel_row++); + f = insert_row_addition(f, T, rel_row++); } } @@ -430,26 +427,55 @@ namespace nil { { using var = typename plonk_miller_loop::var; using constraint_type = crypto3::zk::snark::plonk_constraint; + using curve_type = nil::crypto3::algebra::curves::mnt4<298>; - /* using fp2_constraint = detail::abstract_fp2_element< constraint_type, typename mnt4_g2_params::field_type::value_type >; - */ using fp4_constraint = detail::mnt4_fp4_element; + fp2_constraint C; + std::vector gate_list = {}; + constraint_type c_zero = constraint_type(), c_one = c_zero + 1; + constraint_type c_a = c_zero + curve_type::g1_type<>::params_type::a; /* Constraints for the doubling row */ /* 1. f = f_prev^2 * line_doubling(T,T,P) - * 2. T = T_prev + T_prev + * 2. T_next = T + T */ std::vector doubling_constrs = {}; // - // TODO: + // TODO: f + // + + // constraint for doubling: Tnext = T + T: + // Tnext.x = (3*T.x^2+a)^2/(2T.y)^2 - 2T.x + // Tnext.y = (3*T.x^2+a)/2T.y *(T.x-Tnext.x)-T.y + // + // Rewrite: + // (Tnext.x +2 * Tx)*(2*T.y)^2 - (3*T.x^2+a)^2 = 0 + // (Tnext.y + T.y) * (2*T.y) - (3*T.x^2+a)*(T.x-Tnext.x) =0 // + fp2_constraint one = {c_one, c_zero}, + a = {c_a, c_zero}, + Tx = {var(component.W(6), 0, true), var(component.W(7), 0, true)}, + Ty = {var(component.W(8), 0, true), var(component.W(9), 0, true)}, + Tnx = {var(component.W(6), 1, true), var(component.W(7), 1, true)}, + Tny = {var(component.W(8), 1, true), var(component.W(9), 1, true)}; + + C = (Tnx + 2*Tx)*(2*Ty)*(2*Ty) - (3*Tx*Tx + a)*(3*Tx*Tx + a); + doubling_constrs.push_back(C[0]); + doubling_constrs.push_back(C[1]); + + C = (Tny + Ty)*(2*Ty) - (3*Tx*Tx + a)*(Tx - Tnx); + doubling_constrs.push_back(C[0]); + doubling_constrs.push_back(C[1]); + + // Should we check for zero ? + gate_list.push_back(bp.add_gate(doubling_constrs)); /* Constraints for the addition row */ @@ -459,8 +485,31 @@ namespace nil { */ std::vector adding_constrs = {}; // - // TODO: + // TODO: f // + + // constraint for addition: Tnext = T + Q: + // Tnext.x = (Q.y - T.y)^2/(Q.x - T.x)^2- T.x - Q.x + // Tnext.y = (Q.y - T.y)/(Q.x - T.x)*(T.x - Tnext.x) - Q.y + // + // Rewrite: + // (Tnext.x + T.x + Q.x)*(Q.x - T.x)^2 - (Q.y - T.y)^2 = 0 + // (Tnext.y + Q.y)*(Q.x - T.x) - (Q.y - T.y) * (T.x - Tnext.x) = 0 + // + fp2_constraint + Qx = {var(component.W(10), 0, true), var(component.W(11), 0, true)}, + Qy = {var(component.W(12), 0, true), var(component.W(13), 0, true)}; + + C = (Tnx + Tx + Qx)*(Qx - Tx)*(Qx - Tx) - (Qy - Ty)*(Qy - Ty); + adding_constrs.push_back(C[0]); + adding_constrs.push_back(C[1]); + + C = (Tny + Qy)*(Qx - Tx) - (Qy - Ty)*(Tx - Tnx); + adding_constrs.push_back(C[0]); + adding_constrs.push_back(C[1]); + + // Should we check for zero? + gate_list.push_back(bp.add_gate(adding_constrs)); return gate_list; @@ -492,6 +541,12 @@ namespace nil { var(0, start_row_index, false, var::column_type::constant), var(component.W(3), start_row_index, false)}); + /* T on the first row is Q */ + bp.add_copy_constraint({var(component.W(6), start_row_index), instance_input.Q[0]}); + bp.add_copy_constraint({var(component.W(7), start_row_index), instance_input.Q[1]}); + bp.add_copy_constraint({var(component.W(8), start_row_index), instance_input.Q[2]}); + bp.add_copy_constraint({var(component.W(9), start_row_index), instance_input.Q[3]}); + std::size_t row = 0; /* Copy P and Q along the circuit */ @@ -523,9 +578,6 @@ namespace nil { { using component_type = plonk_miller_loop; using var = typename component_type::var; - using point_addition_type = typename component_type::point_addition_type; - - point_addition_type point_addition_instance( component._W, component._C, component._PI); std::vector selector_index = generate_gates(component, bp, assignment, instance_input); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f8ea47ee3..7d95dc711 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -188,6 +188,7 @@ set(HASHES_TESTS_FILES "hashes/r1cs/pedersen") set(PAIRING_TESTS_FILES + "algebra/pairing/weierstrass/plonk/mnt4_pairing" "algebra/pairing/weierstrass/r1cs/miller_loop" "algebra/pairing/weierstrass/r1cs/precomputation")