diff --git a/include/nil/blueprint/components/algebra/fields/plonk/non_native/mnt4_fp4_fixed_power.hpp b/include/nil/blueprint/components/algebra/fields/plonk/non_native/mnt4_fp4_fixed_power.hpp index 78e715171..e4a402c29 100644 --- a/include/nil/blueprint/components/algebra/fields/plonk/non_native/mnt4_fp4_fixed_power.hpp +++ b/include/nil/blueprint/components/algebra/fields/plonk/non_native/mnt4_fp4_fixed_power.hpp @@ -99,7 +99,7 @@ namespace nil { public: using manifest_type = plonk_component_manifest; - const integral_type power/* = pairing::detail::pairing_params::final_exponent_last_chunk_abs_of_w0*/; + const integral_type power; const std::vector exp_plan, exp_precompute; const std::size_t rows_amount; @@ -259,7 +259,6 @@ namespace nil { { using value_type = typename BlueprintFieldType::value_type; - using policy_type = typename component_type::policy_type; const std::vector exp_plan = component.exp_plan, diff --git a/include/nil/blueprint/components/algebra/fields/plonk/non_native/mnt6_fp6_fixed_power.hpp b/include/nil/blueprint/components/algebra/fields/plonk/non_native/mnt6_fp6_fixed_power.hpp index 755449b06..87c141f8e 100644 --- a/include/nil/blueprint/components/algebra/fields/plonk/non_native/mnt6_fp6_fixed_power.hpp +++ b/include/nil/blueprint/components/algebra/fields/plonk/non_native/mnt6_fp6_fixed_power.hpp @@ -259,7 +259,6 @@ namespace nil { { using value_type = typename BlueprintFieldType::value_type; - using policy_type = typename component_type::policy_type; const std::vector exp_plan = component.exp_plan, diff --git a/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt4_exponentiation.hpp b/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt4_exponentiation.hpp index 76ed0c60f..eed3ce006 100644 --- a/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt4_exponentiation.hpp +++ b/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt4_exponentiation.hpp @@ -22,6 +22,10 @@ // SOFTWARE. //---------------------------------------------------------------------------// // @file Circuit for final exponentiation for MNT4 elliptic curve pairings +// Circuit summary: +// 4 witness, 0 constant, 7 gates, 198 rows +// 248 copy constraints +// each gate has 4 constraints, max degree is 2 //---------------------------------------------------------------------------// #ifndef CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_MNT4_EXPONENTIATION_HPP @@ -69,8 +73,7 @@ namespace nil { // Gate 2: "Multiplication" // Gate 3: "Squaring" // Gate 4: "Cubing" - // Gate 5: "Fourth power" - // Gates 3-5 are used for powering to w0 + // Gates 3-4 are used for powering to w0 using namespace detail; template @@ -102,7 +105,8 @@ namespace nil { static gate_manifest get_gate_manifest( std::size_t witness_amount) { - static gate_manifest manifest = gate_manifest(gate_manifest_type()); + static gate_manifest manifest = gate_manifest(gate_manifest_type()) + .merge_with(fixed_power_type::get_gate_manifest(witness_amount, crypto3::algebra::pairing::detail::pairing_params::final_exponent_last_chunk_abs_of_w0)); return manifest; } @@ -118,12 +122,13 @@ namespace nil { constexpr static std::size_t get_rows_amount( std::size_t witness_amount) { - return fixed_power_type::get_rows_amount(witness_amount, + return fixed_power_type::get_rows_amount( + witness_amount, crypto3::algebra::pairing::detail::pairing_params::final_exponent_last_chunk_abs_of_w0) - + 9 - 1; + + 9; } - constexpr static const std::size_t gates_amount = 7; + constexpr static const std::size_t gates_amount = 3; const std::size_t rows_amount = get_rows_amount(0); struct input_type { @@ -191,9 +196,12 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; using curve_type = nil::crypto3::algebra::curves::mnt4<298>; - using fixed_power_type = mnt4_fp4_fixed_power, BlueprintFieldType>; + using fixed_power_type = mnt4_fp4_fixed_power< + crypto3::zk::snark::plonk_constraint_system, BlueprintFieldType>; - fixed_power_type fixed_power_instance(component._W, component._C, component._PI, crypto3::algebra::pairing::detail::pairing_params::final_exponent_last_chunk_abs_of_w0); + fixed_power_type fixed_power_instance( + component._W, component._C, component._PI, + crypto3::algebra::pairing::detail::pairing_params::final_exponent_last_chunk_abs_of_w0); std::array x; @@ -263,7 +271,7 @@ namespace nil { } }); // Now elt3 holds x^(p^2-1)*w0 - // fill_row(elt3); + fill_row(elt3); // Final result is elt2*elt3 = x^((p^2-1)*p) * x^((p^2-1)*w0) = x^(p^2-1)*(p+w0) fill_row(elt2); @@ -324,10 +332,9 @@ namespace nil { R = Xn*X - Xp; constrs.clear(); - constrs.push_back(R[0]); - constrs.push_back(R[1]); - constrs.push_back(R[2]); - constrs.push_back(R[3]); + for(std::size_t i = 0; i < 4; ++i) { + constrs.push_back(R[i]); + } gate_list.push_back(bp.add_gate(constrs)); } @@ -339,10 +346,9 @@ namespace nil { R = Xn - X*Xp; constrs.clear(); - constrs.push_back(R[0]); - constrs.push_back(R[1]); - constrs.push_back(R[2]); - constrs.push_back(R[3]); + for(std::size_t i = 0; i < 4; ++i) { + constrs.push_back(R[i]); + } gate_list.push_back(bp.add_gate(constrs)); } @@ -380,7 +386,7 @@ namespace nil { // Copy from 5 row to R+6 row for(std::size_t i = 0; i < 4; ++i) { bp.add_copy_constraint({ - var(component.W(i), start_row_index + R + 6, false), + var(component.W(i), start_row_index + R + 7, false), var(component.W(i), start_row_index + 5, false), }); } @@ -402,7 +408,6 @@ namespace nil { fixed_power_type power_instance( component._W, component._C, component._PI, crypto3::algebra::pairing::detail::pairing_params::final_exponent_last_chunk_abs_of_w0); - std::size_t R = power_instance.rows_amount; std::vector selector_index = generate_gates(component, bp, assignment, instance_input); @@ -424,11 +429,18 @@ namespace nil { typename fixed_power_type::input_type power_input = { power_input_vars }; typename fixed_power_type::result_type power_output = generate_circuit(power_instance, bp, assignment, power_input, start_row_index + 6); + std::size_t R = power_instance.rows_amount; - // expect result at start_rows_index + 6 + R + // Copy from subcircuit result to R + 7 row + for(std::size_t i = 0; i < 4; ++i) { + bp.add_copy_constraint({ + var(component.W(i), start_row_index + R + 6, false), + power_output.output[i] + }); + } - // Multiplication gate - assignment.enable_selector(selector_index[2], start_row_index + R + 6); + // Multiplication gate at R + 7 + assignment.enable_selector(selector_index[2], start_row_index + R + 7); generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); 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 0d4627367..abe83c5cb 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 @@ -22,6 +22,10 @@ // SOFTWARE. //---------------------------------------------------------------------------// // @file Declaration of Miller loop component for MNT4 pairings +// Circuit summary: +// 16 witness, 1 constant, 2 gates, 219 rows +// 724 copy constraints +// each gate has 12 constraints, max degree is 4 //---------------------------------------------------------------------------// #ifndef CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_MNT4_MILLER_LOOP_HPP @@ -79,7 +83,7 @@ namespace nil { // // Each iteration of the Miller loop adds "doubling" row to the circuit: // - // f0 f1 f2 f3 P0 P1 T0 T1 T2 T3 Q0 Q1 Q2 Q3 L0 L1 L2 L3 + // f0 f1 f2 f3 P0 P1 T0 T1 T2 T3 Q0 Q1 Q2 Q3 [L0] [L1] L2 L3 // Gate 0: "doubling" // Constraints: // 0. UT = untwisted T @@ -88,7 +92,7 @@ namespace nil { // 3. T_next = T + T // // If current iteration needs to add addition, then "addition" row is inserted: - // f0 f1 f2 f3 P0 P1 T0 T1 T2 T3 Q0 Q1 Q2 Q3 L0 L1 L2 L3 + // f0 f1 f2 f3 P0 P1 T0 T1 T2 T3 Q0 Q1 Q2 Q3 [L0] [L1] L2 L3 // Gate 1: "addition" // Constraints: // 0. UT = untwisted T, UQ = untwisted Q @@ -101,18 +105,7 @@ namespace nil { // Q is copied only in addition rows. // Initial value f (1,0,0,0) is copied from constants column // - // Total number of copy constraints: 724 = 4+2*147+6*71 - // - // We can reduce number of copy constraints by next trick: - // 1. Copy Q in doubling rows too - // 2. To each gate (doubling and addition) add addition 6 constraints: - // w_i = w_i_rot(1), i = 2,4 (P), 9,10,11,12 (Q) - // 3. Leave copy constraints for P and Q on the first row - // Total number of copy constraints will be: - // 4+2+6 = 12 - // At the expense of adding 6 additional constraints to each gate - // - // Witnesses for L0 and L1 could be removed as they are always zero + // Witnesses for L0 and L1 are removed as they are always zero using namespace detail; using detail::base; @@ -153,7 +146,8 @@ namespace nil { static manifest_type get_manifest() { static manifest_type manifest = manifest_type( - std::shared_ptr(new manifest_single_value_param(18)), + std::shared_ptr( + new manifest_single_value_param(16)), true // constant column required ); return manifest; @@ -239,8 +233,6 @@ namespace nil { typename plonk_miller_loop::input_type const& instance_input, const std::uint32_t start_row_index) { - using component_type = plonk_miller_loop; - using var = typename component_type::var; using value_type = typename BlueprintFieldType::value_type; using policy_type_fp2 = crypto3::algebra::fields::fp2; @@ -254,15 +246,22 @@ namespace nil { yP = var_value(assignment, instance_input.P[1]); std::array - xQ = {var_value(assignment, instance_input.Q[0]), var_value(assignment, instance_input.Q[1])}, - yQ = {var_value(assignment, instance_input.Q[2]), var_value(assignment, instance_input.Q[3])}; + xQ = { + var_value(assignment, instance_input.Q[0]), + var_value(assignment, instance_input.Q[1]) + }, + yQ = { + var_value(assignment, instance_input.Q[2]), + var_value(assignment, instance_input.Q[3]) + }; curve_point Q = { fp2_element(xQ[0], xQ[1]), fp2_element(yQ[0], yQ[1])}; /* Calculate point doubling on E', affine coordinates */ auto double_point = [](curve_point const& T) { - fp2_element a(curve_type::g2_type<>::params_type::a), - lambda = (3*T[0].pow(2) + a) / (2*T[1]), + fp2_element + a(curve_type::g2_type<>::params_type::a), + lambda = (3*T[0].pow(2) + a) * (2*T[1]).inversed(), xR = lambda.pow(2) - 2*T[0], yR = (3*T[0])*lambda - lambda.pow(3) - T[1]; return curve_point({xR, yR}); @@ -271,7 +270,7 @@ namespace nil { /* Calculate point addition on E', affine coordinates */ auto add_points = [](curve_point const& T, curve_point const& Q) { fp2_element - lambda = (T[1] - Q[1])/(T[0] - Q[0]), + lambda = (T[1] - Q[1])*(T[0] - Q[0]).inversed(), xR = lambda*lambda - T[0] - Q[0], yR = (2*T[0] + Q[0])*lambda - lambda.pow(3) - T[1]; return curve_point({xR, yR}); @@ -338,10 +337,9 @@ namespace nil { assignment.witness(component.W(13),start_row_index + row) = 0; // lf - assignment.witness(component.W(14),start_row_index + row) = lf.data[0].data[0]; - assignment.witness(component.W(15),start_row_index + row) = lf.data[0].data[1]; - assignment.witness(component.W(16),start_row_index + row) = lf.data[1].data[0]; - assignment.witness(component.W(17),start_row_index + row) = lf.data[1].data[1]; + // lf.data[0] is always zero, not inserted into witness columns + assignment.witness(component.W(14),start_row_index + row) = lf.data[1].data[0]; + assignment.witness(component.W(15),start_row_index + row) = lf.data[1].data[1]; return g; }; @@ -390,10 +388,9 @@ namespace nil { assignment.witness(component.W(13),start_row_index + row) = Q[1].data[1]; // lf - assignment.witness(component.W(14),start_row_index + row) = lf.data[0].data[0]; - assignment.witness(component.W(15),start_row_index + row) = lf.data[0].data[1]; - assignment.witness(component.W(16),start_row_index + row) = lf.data[1].data[0]; - assignment.witness(component.W(17),start_row_index + row) = lf.data[1].data[1]; + // lf.data[0] is always zero, not inserted into witness columns + assignment.witness(component.W(14),start_row_index + row) = lf.data[1].data[0]; + assignment.witness(component.W(15),start_row_index + row) = lf.data[1].data[1]; return g; }; @@ -462,7 +459,7 @@ namespace nil { using value_type = typename BlueprintFieldType::value_type; - fp2_constraint C; + fp2_constraint C2; fp4_constraint C4; std::vector gate_list = {}; @@ -470,6 +467,7 @@ namespace nil { constraint_type c_g1_a = c_zero + curve_type::g1_type<>::params_type::a; constraint_type c_g2_a0 = c_zero + curve_type::g2_type<>::params_type::a.data[0]; constraint_type c_g2_a1 = c_zero + curve_type::g2_type<>::params_type::a.data[1]; + value_type nri = policy_type_fp2::extension_policy::non_residue.inversed(); /* Constraints for the doubling gate @@ -512,23 +510,20 @@ namespace nil { var(component.W(9), 0, true) * nri }, lf = { + c_zero, c_zero, var(component.W(14), 0, true), var(component.W(15), 0, true), - var(component.W(16), 0, true), - var(component.W(17), 0, true) }; C4 = lf*(2*y1) - (3*x1*x1 + a4); - doubling_constrs.push_back(C4[0]); - doubling_constrs.push_back(C4[1]); - doubling_constrs.push_back(C4[2]); - doubling_constrs.push_back(C4[3]); + for(auto const& c: C4.x) { + doubling_constrs.push_back(c); + } C4 = fnext - f*f*(lf*(x - x1) - (y - y1)); - doubling_constrs.push_back(C4[0]); - doubling_constrs.push_back(C4[1]); - doubling_constrs.push_back(C4[2]); - doubling_constrs.push_back(C4[3]); + for(auto const& c: C4.x) { + doubling_constrs.push_back(c); + } } /* Constraints for point doubling: Tnext = T + T: @@ -545,13 +540,13 @@ namespace nil { 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]); + C2 = (Tnx + 2*Tx)*(2*Ty)*(2*Ty) - (3*Tx*Tx + a)*(3*Tx*Tx + a); + doubling_constrs.push_back(C2[0]); + doubling_constrs.push_back(C2[1]); - C = (Tny + Ty)*(2*Ty) - (3*Tx*Tx + a)*(Tx - Tnx); - doubling_constrs.push_back(C[0]); - doubling_constrs.push_back(C[1]); + C2 = (Tny + Ty)*(2*Ty) - (3*Tx*Tx + a)*(Tx - Tnx); + doubling_constrs.push_back(C2[0]); + doubling_constrs.push_back(C2[1]); gate_list.push_back(bp.add_gate(doubling_constrs)); @@ -603,23 +598,21 @@ namespace nil { var(component.W(13), 0, true) * nri }, lf = { + c_zero, c_zero, var(component.W(14), 0, true), var(component.W(15), 0, true), - var(component.W(16), 0, true), - var(component.W(17), 0, true) }; C4 = lf*(x2 - x1) - (y2 - y1); - adding_constrs.push_back(C4[0]); - adding_constrs.push_back(C4[1]); - adding_constrs.push_back(C4[2]); - adding_constrs.push_back(C4[3]); + for(auto const& c: C4.x) { + adding_constrs.push_back(c); + } C4 = fnext - f*(lf*(x-x1) - (y-y1)); - adding_constrs.push_back(C4[0]); - adding_constrs.push_back(C4[1]); - adding_constrs.push_back(C4[2]); - adding_constrs.push_back(C4[3]); + for(auto const& c: C4.x) { + adding_constrs.push_back(c); + } + } /* Constraints for point addition: Tnext = T + Q: @@ -633,13 +626,13 @@ namespace nil { 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]); + C2 = (Tnx + Tx + Qx)*(Qx - Tx)*(Qx - Tx) - (Qy - Ty)*(Qy - Ty); + adding_constrs.push_back(C2[0]); + adding_constrs.push_back(C2[1]); - C = (Tny + Ty)*(Qx - Tx) - (Qy - Ty)*(Tx - Tnx); - adding_constrs.push_back(C[0]); - adding_constrs.push_back(C[1]); + C2 = (Tny + Ty)*(Qx - Tx) - (Qy - Ty)*(Tx - Tnx); + adding_constrs.push_back(C2[0]); + adding_constrs.push_back(C2[1]); gate_list.push_back(bp.add_gate(adding_constrs)); @@ -710,9 +703,6 @@ namespace nil { const typename plonk_miller_loop::input_type &instance_input, const std::size_t start_row_index) { - using component_type = plonk_miller_loop; - using var = typename component_type::var; - std::vector selector_index = generate_gates(component, bp, assignment, instance_input); generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); diff --git a/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt6_exponentiation.hpp b/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt6_exponentiation.hpp index 90772c319..2b108ae8b 100644 --- a/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt6_exponentiation.hpp +++ b/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt6_exponentiation.hpp @@ -22,6 +22,10 @@ // SOFTWARE. //---------------------------------------------------------------------------// // @file Circuit for final exponentiation for MNT6 elliptic curve pairings +// Circuit summary: +// 6 witness, 0 constant, 7 gates, 199 rows +// 366 copy constraints +// each gate has 6 constraints, max degree is 2 //---------------------------------------------------------------------------// #ifndef CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_MNT6_EXPONENTIATION_HPP @@ -73,7 +77,6 @@ namespace nil { // Gate 3: "Multiplication" // Gate 4: "Squaring" // Gate 5: "Cubing" - // Gate 6: "Fourth power" // Gates 3-5 are used for powering to w_0 using namespace detail; @@ -123,12 +126,10 @@ namespace nil { constexpr static std::size_t get_rows_amount( std::size_t witness_amount) { - auto x = fixed_power_type::get_rows_amount( + return fixed_power_type::get_rows_amount( witness_amount, crypto3::algebra::pairing::detail::pairing_params::final_exponent_last_chunk_abs_of_w0) + 12; - std::cout << "Get rows: " << x << std::endl; - return x; } constexpr static const std::size_t gates_amount = 3; @@ -291,14 +292,13 @@ namespace nil { } }); // Now elt3 holds x^((p^3-1)*(p+1)*w0) - // Do not fill as sub-circuit output results are on the last row - // fill_row(elt3); + // The output of "fixed_power" circuit is copied into 9+R row - // 8+R-1: Final result is elt/elt3 = x^((p^3-1)*(p+1)*p) * x^(-(p^3-1)(p+1)*w0) = x^((p^3-1)*(p+1)*(p-w0)) + // 8+R: Final result is elt/elt3 = x^((p^3-1)*(p+1)*p) * x^(-(p^3-1)(p+1)*w0) = x^((p^3-1)*(p+1)*(p-w0)) fill_row(elt); fill_row(elt3); elt = elt*elt3.inversed(); - // 10+R-1 + // 10+R fill_row(elt); return typename plonk_mnt6_exponentiation::result_type( @@ -404,12 +404,12 @@ namespace nil { crypto3::algebra::pairing::detail::pairing_params::final_exponent_last_chunk_abs_of_w0); std::size_t R = power_instance.rows_amount; - // initial data in row 0 + // Initial data in row 0 for(std::size_t i = 0; i < 6; ++i) { bp.add_copy_constraint({var(component.W(i), start_row_index, false), instance_input.x[i]}); } - // initial data in row 4 + // Initial data in row 4 for(std::size_t i = 0; i < 6; ++i) { bp.add_copy_constraint({var(component.W(i), start_row_index + 4, false), instance_input.x[i]}); } @@ -421,15 +421,7 @@ namespace nil { var(component.W(i), start_row_index + 8, false), }); } - - // Copy from R+8 row to R+10 row - for(std::size_t i = 0; i < 6; ++i) { - bp.add_copy_constraint({ - var(component.W(i), start_row_index + R + 10, false), - var(component.W(i), start_row_index + R + 8, false), - }); - } - } + } template typename plonk_mnt6_exponentiation::result_type @@ -475,9 +467,15 @@ namespace nil { generate_circuit(power_instance, bp, assignment, power_input, start_row_index + 9); std::size_t R = power_instance.rows_amount; - // expect result at start_rows_index + R + 9 + // Copy from subcircuit result to R+10 row + for(std::size_t i = 0; i < 6; ++i) { + bp.add_copy_constraint({ + var(component.W(i), start_row_index + R + 10, false), + power_output.output[i] + }); + } - // Inverse division gate + // Division gate at R + 10 assignment.enable_selector(selector_index[1], start_row_index + R + 10); generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); diff --git a/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt6_miller_loop.hpp b/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt6_miller_loop.hpp index c9b1c8132..a959f033a 100644 --- a/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt6_miller_loop.hpp +++ b/include/nil/blueprint/components/algebra/pairing/weierstrass/plonk/mnt6_miller_loop.hpp @@ -22,6 +22,10 @@ // SOFTWARE. //---------------------------------------------------------------------------// // @file Declaration of Miller loop component for MNT6 pairings +// Circuit summary: +// 23 witness, 1 constant, 2 gates, 219 rows +// 868 copy constraints +// each gate has 18 constraints, max degree 4 //---------------------------------------------------------------------------// #ifndef CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_MNT6_MILLER_LOOP_HPP @@ -79,7 +83,7 @@ namespace nil { // // Each iteration of the Miller loop adds "doubling" row to the circuit: // - // f0 f1 f2 f3 f4 f5 P0 P1 T0 T1 T2 T3 T4 T5 Q0 Q1 Q2 Q3 Q4 Q5 L0 L1 L2 L3 L4 L5 + // f0 f1 f2 f3 f4 f5 P0 P1 T0 T1 T2 T3 T4 T5 Q0 Q1 Q2 Q3 Q4 Q5 [L0] [L1] [L2] L3 L4 L5 // Gate 0: "doubling" // Constraints: // 0. UT = untwisted T @@ -88,7 +92,7 @@ namespace nil { // 3. T_next = T + T // // If current iteration needs to add addition, then "addition" row is inserted: - // f0 f1 f2 f3 f4 f5 P0 P1 T0 T1 T2 T3 T4 T5 Q0 Q1 Q2 Q3 Q4 Q5 L0 L1 L2 L3 L4 L5 + // f0 f1 f2 f3 f4 f5 P0 P1 T0 T1 T2 T3 T4 T5 Q0 Q1 Q2 Q3 Q4 Q5 [L0] [L1] [L2] L3 L4 L5 // Gate 1: "addition" // Constraints: // 0. UT = untwisted T, UQ = untwisted Q @@ -101,18 +105,7 @@ namespace nil { // Q is copied only in addition rows. // Initial value f (1,0,0,0,0) is copied from constants column // - // Total number of copy constraints: 724 = 4+2*147+6*71 - // - // We can reduce number of copy constraints by next trick: - // 1. Copy Q in doubling rows too - // 2. To each gate (doubling and addition) add addition 6 constraints: - // w_i = w_i_rot(1), i = 6,7 (P), 14..19 (Q) - // 3. Leave copy constraints for P and Q on the first row - // Total number of copy constraints will be: - // 4+2+6 = 12 //xz - // At the expense of adding 6 additional constraints to each gate - // - // Witnesses for L0 and L1, L2 could be removed as they are always zero + // Witnesses for L0, L1, L2 are removed as they are always zero using namespace detail; using detail::base; @@ -153,7 +146,8 @@ namespace nil { static manifest_type get_manifest() { static manifest_type manifest = manifest_type( - std::shared_ptr(new manifest_single_value_param(18)), + std::shared_ptr( + new manifest_single_value_param(23)), true // constant column required ); return manifest; @@ -239,8 +233,6 @@ namespace nil { typename plonk_miller_loop::input_type const& instance_input, const std::uint32_t start_row_index) { - using component_type = plonk_miller_loop; - using var = typename component_type::var; using value_type = typename BlueprintFieldType::value_type; using policy_type_fp3 = crypto3::algebra::fields::fp3; @@ -269,7 +261,8 @@ namespace nil { /* Calculate point doubling on E', affine coordinates */ auto double_point = [](curve_point const& T) { - fp3_element a(curve_type::g2_type<>::params_type::a), + fp3_element + a(curve_type::g2_type<>::params_type::a), lambda = (3*T[0].pow(2) + a) * (2*T[1]).inversed(), xR = lambda.pow(2) - 2*T[0], yR = (3*T[0])*lambda - lambda.pow(3) - T[1]; @@ -353,12 +346,10 @@ namespace nil { assignment.witness(component.W(19),start_row_index + row) = 0; // lf - assignment.witness(component.W(20),start_row_index + row) = lf.data[0].data[0]; - assignment.witness(component.W(21),start_row_index + row) = lf.data[0].data[1]; - assignment.witness(component.W(22),start_row_index + row) = lf.data[0].data[2]; - assignment.witness(component.W(23),start_row_index + row) = lf.data[1].data[0]; - assignment.witness(component.W(24),start_row_index + row) = lf.data[1].data[1]; - assignment.witness(component.W(25),start_row_index + row) = lf.data[1].data[2]; + // lf.data[0] is always zero, not inserted into witness columns + assignment.witness(component.W(20),start_row_index + row) = lf.data[1].data[0]; + assignment.witness(component.W(21),start_row_index + row) = lf.data[1].data[1]; + assignment.witness(component.W(22),start_row_index + row) = lf.data[1].data[2]; return g; }; @@ -413,12 +404,10 @@ namespace nil { assignment.witness(component.W(19),start_row_index + row) = Q[1].data[2]; // lf - assignment.witness(component.W(20),start_row_index + row) = lf.data[0].data[0]; - assignment.witness(component.W(21),start_row_index + row) = lf.data[0].data[1]; - assignment.witness(component.W(22),start_row_index + row) = lf.data[0].data[2]; - assignment.witness(component.W(23),start_row_index + row) = lf.data[1].data[0]; - assignment.witness(component.W(24),start_row_index + row) = lf.data[1].data[1]; - assignment.witness(component.W(25),start_row_index + row) = lf.data[1].data[2]; + // lf.data[0] is always zero, not inserted into witness columns + assignment.witness(component.W(20),start_row_index + row) = lf.data[1].data[0]; + assignment.witness(component.W(21),start_row_index + row) = lf.data[1].data[1]; + assignment.witness(component.W(22),start_row_index + row) = lf.data[1].data[2]; return g; }; @@ -550,12 +539,10 @@ namespace nil { var(component.W(12), 0, true) * nri, }, lf = { + c_zero, c_zero, c_zero, var(component.W(20), 0, true), var(component.W(21), 0, true), var(component.W(22), 0, true), - var(component.W(23), 0, true), - var(component.W(24), 0, true), - var(component.W(25), 0, true) }; C6 = lf*(2*y1) - (3*x1*x1 + a6); @@ -651,12 +638,10 @@ namespace nil { var(component.W(18), 0, true) * nri, }, lf = { + c_zero, c_zero, c_zero, var(component.W(20), 0, true), var(component.W(21), 0, true), var(component.W(22), 0, true), - var(component.W(23), 0, true), - var(component.W(24), 0, true), - var(component.W(25), 0, true) }; @@ -772,9 +757,6 @@ namespace nil { const typename plonk_miller_loop::input_type &instance_input, const std::size_t start_row_index) { - using component_type = plonk_miller_loop; - using var = typename component_type::var; - std::vector selector_index = generate_gates(component, bp, assignment, instance_input); generate_copy_constraints(component, bp, assignment, instance_input, start_row_index); diff --git a/test/algebra/pairing/weierstrass/plonk/mnt4_exponentiation.cpp b/test/algebra/pairing/weierstrass/plonk/mnt4_exponentiation.cpp index 9ee6868c7..d81a71d0e 100644 --- a/test/algebra/pairing/weierstrass/plonk/mnt4_exponentiation.cpp +++ b/test/algebra/pairing/weierstrass/plonk/mnt4_exponentiation.cpp @@ -54,7 +54,7 @@ template void test_mnt4_298_exponentiation(std::vector public_input, std::vector expected_res) { constexpr std::size_t PublicInputColumns = 1; - constexpr std::size_t ConstantColumns = 1; + constexpr std::size_t ConstantColumns = 0; constexpr std::size_t SelectorColumns = 8; zk::snark::plonk_table_description desc( @@ -110,7 +110,6 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt4_pairing_test) { using curve_type = crypto3::algebra::curves::mnt4_298; using gt_group_type = typename curve_type::gt_type; - using base_field_value = curve_type::base_field_type::value_type; using field_type = typename curve_type::gt_type::base_field_type; nil::crypto3::random::algebraic_engine generate_random; @@ -133,6 +132,30 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt4_pairing_test) { std::cout << "MNT4-298 Final exponentiation test\n"; test_mnt4_298_exponentiation(AB_ML, AB_FE); + + for(std::size_t i = 0; i < random_tests_amount; ++i) { + typename gt_group_type::value_type + A = crypto3::algebra::random_element(), + A_FE = final_exponentiation(A); + + std::vector + input = { + A.data[0].data[0], + A.data[0].data[1], + A.data[1].data[0], + A.data[1].data[1], + }, + result = { + A_FE.data[0].data[0], + A_FE.data[0].data[1], + A_FE.data[1].data[0], + A_FE.data[1].data[1], + }; + + std::cout << "mnt4-298 Final exponentiation random test " << i << std::endl; + test_mnt4_298_exponentiation(input, result); + + } } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/algebra/pairing/weierstrass/plonk/mnt4_miller_loop.cpp b/test/algebra/pairing/weierstrass/plonk/mnt4_miller_loop.cpp index 4c2067746..d1a30e29b 100644 --- a/test/algebra/pairing/weierstrass/plonk/mnt4_miller_loop.cpp +++ b/test/algebra/pairing/weierstrass/plonk/mnt4_miller_loop.cpp @@ -36,7 +36,6 @@ #include #include -#include #include @@ -55,7 +54,7 @@ void test_mnt4_298_miller_loop(std::vector publi std::vector expected_res) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = (WitnessColumns == 12)? (4 + 8) : (4 + 9); + constexpr std::size_t SelectorColumns = 2; zk::snark::plonk_table_description desc( WitnessColumns, PublicInputColumns, ConstantColumns, SelectorColumns); @@ -70,13 +69,17 @@ void test_mnt4_298_miller_loop(std::vector publi using component_type = blueprint::components::mnt4_miller_loop; typename component_type::input_type instance_input = { - var(0,0, false, var::column_type::public_input), // xP - var(0,1, false, var::column_type::public_input), // yP - var(0,2, false, var::column_type::public_input), // xQ[0] - var(0,3, false, var::column_type::public_input), // xQ[1] - var(0,4, false, var::column_type::public_input), // yQ[0] - var(0,5, false, var::column_type::public_input) // yQ[1] - }; + { + var(0,0, false, var::column_type::public_input), // xP + var(0,1, false, var::column_type::public_input), // yP + }, + { + var(0,2, false, var::column_type::public_input), // xQ[0] + var(0,3, false, var::column_type::public_input), // xQ[1] + var(0,4, false, var::column_type::public_input), // yQ[0] + var(0,5, false, var::column_type::public_input) // yQ[1] + } + }; auto result_check = [&expected_res](AssignmentType const& assignment, typename component_type::result_type const& real_res) { @@ -105,20 +108,12 @@ void test_mnt4_298_miller_loop(std::vector publi component_instance, desc, public_input, result_check, instance_input); } -static const std::size_t random_tests_amount = 5; - BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt4_miller_loop_test) { using curve_type = crypto3::algebra::curves::mnt4_298; - using g2_group_type = typename curve_type::g2_type<>; - using base_field_value = curve_type::base_field_type::value_type; using field_type = typename curve_type::g2_type<>::field_type::base_field_type; - nil::crypto3::random::algebraic_engine generate_random; - boost::random::mt19937 seed_seq; - generate_random.seed(seed_seq); - std::vector AB = { // A :[ @@ -127,11 +122,11 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt4_miller_loop_test) { // ] // B :[ [ - 0x012212f4ac5a2b6262dcd15a0fb4e54d276d734d80e3868dc93a074b3a9ebeb598641aa2310d_cppui298, - 0x017600e8757679e06b66de2c48b3370e582443d4c0091ef1e6d96dadb92150ff642709dd806b_cppui298, - 0x02a1135b45f576b0988c2f5e852def5e829508beddae07427cc68929ffbeaa49de4d370cfa69_cppui298, - 0x0246c479956c92096a1dfa7cdb992b53ecb05f96d581fcb755045898fb459fd569753da2c2a7_cppui298 - // ]] + 0x012212f4ac5a2b6262dcd15a0fb4e54d276d734d80e3868dc93a074b3a9ebeb598641aa2310d_cppui298, + 0x017600e8757679e06b66de2c48b3370e582443d4c0091ef1e6d96dadb92150ff642709dd806b_cppui298, + 0x02a1135b45f576b0988c2f5e852def5e829508beddae07427cc68929ffbeaa49de4d370cfa69_cppui298, + 0x0246c479956c92096a1dfa7cdb992b53ecb05f96d581fcb755045898fb459fd569753da2c2a7_cppui298 + // ]] }, AB_ML = { 0x01f3f02a39499cca91c7c3a108cc0721047455bc2def95bcb613a1749c1bbe0fb0d88088699b_cppui298, @@ -141,7 +136,7 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt4_miller_loop_test) { }; std::cout << "MNT4-298 Miller loop test\n"; - test_mnt4_298_miller_loop(AB, AB_ML); + test_mnt4_298_miller_loop(AB, AB_ML); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/algebra/pairing/weierstrass/plonk/mnt6_exponentiation.cpp b/test/algebra/pairing/weierstrass/plonk/mnt6_exponentiation.cpp index 5abeeb2f6..581a92cb8 100644 --- a/test/algebra/pairing/weierstrass/plonk/mnt6_exponentiation.cpp +++ b/test/algebra/pairing/weierstrass/plonk/mnt6_exponentiation.cpp @@ -112,7 +112,6 @@ BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt6_pairing_test) { using curve_type = crypto3::algebra::curves::mnt6_298; using gt_group_type = typename curve_type::gt_type; - using base_field_value = curve_type::base_field_type::value_type; using field_type = typename curve_type::gt_type::base_field_type; nil::crypto3::random::algebraic_engine generate_random; @@ -129,14 +128,6 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt6_pairing_test) { 0x01b5c328e47a03bddb00f0992ddbd9945af3e0f4bb8244d29b9b24ca2390e92ecc5666a76191_cppui298 }, AB_FE = { - /* - 0x15dec519566f20aa6a3bd4ddb0cee93f9ea157499f20273124883934daeea1867ea53ac4b9b_cppui298, - 0x3b5fc396c41a54c7c661b3d34ead6f284a50886534f036c004eb31d8d7cb061d3419f6a9d58_cppui298, - 0x1b79ac259f41bfdc8aa623c65075d0a0fb1823467b174c4ac82cada904d96f3640fd491baf7_cppui298, - 0x667fef1c7f96557416d9728951128edb921b4ecad5592fd898db5867bf40dfa20de956a717_cppui298, - 0x39143f4b1cee4646b2a1a77d27fc21aead95a0922a4a5f9facb82d88120b01737fafb1f1d8d_cppui298, - 0x2f84e7545b29729839b5871c25a131756558cd8bba38d2ef7439f20b5cb54be2a271a3c1bba_cppui298, - */ 0x025aba200efbefa81017a858457abfc1e83ce8f7e92788e414fe90bacd465395dec8463bf09a_cppui298, 0x002ca86c9adeb0cfd62db143cc3fc5b6adb9fd09419a43b6c5b841f129a0ef71fa3881a4b743_cppui298, 0x00e7bc013d484cc770ddcaa994422f153265c143a64549b916f6893c2e2ab5458e7c3ea5f3d7_cppui298, @@ -145,8 +136,36 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt6_pairing_test) { 0x037f4a31f3bc24e9876d57a5b224d8f6475d36407e092bc03144d1bf042a0aee471639db2439_cppui298 }; - std::cout << "mnt6-298 Final exponentiation test\n"; - test_mnt6_298_exponentiation(AB_ML, AB_FE); + std::cout << "mnt6-298 Final exponentiation test\n"; + test_mnt6_298_exponentiation(AB_ML, AB_FE); + + for(std::size_t i = 0; i < random_tests_amount; ++i) { + typename gt_group_type::value_type + A = crypto3::algebra::random_element(), + A_FE = final_exponentiation(A); + + std::vector + input = { + A.data[0].data[0], + A.data[0].data[1], + A.data[0].data[2], + A.data[1].data[0], + A.data[1].data[1], + A.data[1].data[2], + }, + result = { + A_FE.data[0].data[0], + A_FE.data[0].data[1], + A_FE.data[0].data[2], + A_FE.data[1].data[0], + A_FE.data[1].data[1], + A_FE.data[1].data[2], + }; + + std::cout << "mnt6-298 Final exponentiation random test " << i << std::endl; + test_mnt6_298_exponentiation(input, result); + + } } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/algebra/pairing/weierstrass/plonk/mnt6_miller_loop.cpp b/test/algebra/pairing/weierstrass/plonk/mnt6_miller_loop.cpp index eaabf0e2c..c81abdb0b 100644 --- a/test/algebra/pairing/weierstrass/plonk/mnt6_miller_loop.cpp +++ b/test/algebra/pairing/weierstrass/plonk/mnt6_miller_loop.cpp @@ -40,7 +40,6 @@ #include #include -#include #include @@ -59,7 +58,7 @@ void test_mnt6_298_miller_loop(std::vector publi std::vector expected_res) { constexpr std::size_t PublicInputColumns = 1; constexpr std::size_t ConstantColumns = 1; - constexpr std::size_t SelectorColumns = (WitnessColumns == 12)? (4 + 8) : (4 + 9); + constexpr std::size_t SelectorColumns = 2; zk::snark::plonk_table_description desc( WitnessColumns, PublicInputColumns, ConstantColumns, SelectorColumns); @@ -74,15 +73,19 @@ void test_mnt6_298_miller_loop(std::vector publi using component_type = blueprint::components::mnt6_miller_loop; typename component_type::input_type instance_input = { - var(0,0, false, var::column_type::public_input), // xP - var(0,1, false, var::column_type::public_input), // yP - var(0,2, false, var::column_type::public_input), // xQ[0] - var(0,3, false, var::column_type::public_input), // xQ[1] - var(0,4, false, var::column_type::public_input), // xQ[2] - var(0,5, false, var::column_type::public_input), // yQ[0] - var(0,6, false, var::column_type::public_input), // yQ[1] - var(0,7, false, var::column_type::public_input) // yQ[2] - }; + { + var(0,0, false, var::column_type::public_input), // xP + var(0,1, false, var::column_type::public_input), // yP + }, + { + var(0,2, false, var::column_type::public_input), // xQ[0] + var(0,3, false, var::column_type::public_input), // xQ[1] + var(0,4, false, var::column_type::public_input), // xQ[2] + var(0,5, false, var::column_type::public_input), // yQ[0] + var(0,6, false, var::column_type::public_input), // yQ[1] + var(0,7, false, var::column_type::public_input) // yQ[2] + } + }; auto result_check = [&expected_res](AssignmentType const& assignment, typename component_type::result_type const& real_res) { @@ -111,19 +114,11 @@ void test_mnt6_298_miller_loop(std::vector publi component_instance, desc, public_input, result_check, instance_input); } -static const std::size_t random_tests_amount = 5; - BOOST_AUTO_TEST_SUITE(blueprint_plonk_test_suite) BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt6_miller_loop_test) { using curve_type = crypto3::algebra::curves::mnt6_298; - using g2_group_type = typename curve_type::g2_type<>; - using base_field_value = curve_type::base_field_type::value_type; - using field_type = typename curve_type::g2_type<>::field_type::base_field_type; - - nil::crypto3::random::algebraic_engine generate_random; - boost::random::mt19937 seed_seq; - generate_random.seed(seed_seq); + using field_type = typename curve_type::base_field_type; std::vector AB = { @@ -139,7 +134,6 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt6_miller_loop_test) { 0x0243124387533c863787fbaa1d58a942fe571660b77d80f3df036874309c7f1fcaef47611977_cppui298, 0x00b5be310d4b9f76606e3206c435d1bee679ff0e1efe668e437e720d0e6e31965db04109f38c_cppui298, 0x001638d3b614667d3bb2c0c2e6e2e8b675d5453cdf3dd15810e4b06fde235f90d7b48f4676c0_cppui298, - // ]] }, AB_ML = { @@ -151,8 +145,8 @@ BOOST_AUTO_TEST_CASE(blueprint_plonk_mnt6_miller_loop_test) { 0x016b1fef1c14c52e7f400545f8b548aed78670a0a47d7681b36ec686f504975ad26df1201fdc_cppui298 }; - std::cout << "mnt6-298 Miller loop test\n"; - test_mnt6_298_miller_loop(AB, AB_ML); + std::cout << "mnt6-298 Miller loop test\n"; + test_mnt6_298_miller_loop(AB, AB_ML); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/test_plonk_component.hpp b/test/test_plonk_component.hpp index 3db63a73f..268e5825d 100644 --- a/test/test_plonk_component.hpp +++ b/test/test_plonk_component.hpp @@ -252,7 +252,8 @@ namespace nil { variable.get() = assignment.get_batch_variable_map().at(variable); } } -#if 1 + +#ifdef BLUEPRINT_PLONK_PROFILING_ENABLED std::ofstream fass("circuit.tbl"); assignment.export_table(fass); fass.close(); @@ -261,6 +262,7 @@ namespace nil { bp.export_circuit(fcirc); fcirc.close(); #endif + result_check(assignment, component_result); if constexpr (!PrivateInput) { @@ -283,8 +285,8 @@ namespace nil { // blueprint::detail::export_connectedness_zones( // zones, assignment, instance_input.all_vars(), start_row, rows_after_batching - start_row, std::cout); - // BOOST_ASSERT_MSG(is_connected, - // "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); + BOOST_ASSERT_MSG(is_connected, + "Component disconnected! See comment above this assert for a way to output a visual representation of the connectedness graph."); } desc.usable_rows_amount = assignment.rows_amount();