From b8dc491e5fdd371f6d4d7e157f544026793b0973 Mon Sep 17 00:00:00 2001 From: "e.tatuzova" Date: Mon, 8 Apr 2024 22:19:31 +0400 Subject: [PATCH] FRI x_indices, FRI round proof poly values ordering, lookup and permutation argument partition products, copy_constraints, commitment_params #305 --- .../detail/polynomial/basic_fri.hpp | 307 +++++++++++---- .../detail/polynomial/proof_of_work.hpp | 41 +-- .../crypto3/zk/commitments/polynomial/fri.hpp | 13 +- .../crypto3/zk/commitments/polynomial/kzg.hpp | 279 +------------- .../zk/commitments/polynomial/kzg_v2.hpp | 348 ++++++++++++++++++ .../crypto3/zk/commitments/polynomial/lpc.hpp | 96 ++--- .../crypto3/zk/commitments/type_traits.hpp | 32 +- .../plonk/constraint_system.hpp | 18 +- .../arithmetization/plonk/copy_constraint.hpp | 70 +++- .../plonk/table_description.hpp | 16 + .../placeholder/{ => detail}/profiling.hpp | 68 +++- .../plonk/placeholder/lookup_argument.hpp | 264 +++++++++++-- .../placeholder/permutation_argument.hpp | 206 ++++++++--- .../plonk/placeholder/preprocessor.hpp | 176 +++++---- .../snark/systems/plonk/placeholder/proof.hpp | 4 +- .../systems/plonk/placeholder/prover.hpp | 37 +- .../systems/plonk/placeholder/verifier.hpp | 170 +++++---- test/commitment/fri.cpp | 7 +- test/commitment/kzg.cpp | 3 +- test/commitment/lpc.cpp | 42 ++- test/commitment/lpc_performance.cpp | 21 +- test/commitment/proof_of_work.cpp | 21 +- test/systems/plonk/placeholder/circuits.hpp | 116 ++++-- .../systems/plonk/placeholder/performance.cpp | 27 +- .../systems/plonk/placeholder/placeholder.cpp | 281 +++++++------- test/systems/plonk/plonk_constraint.cpp | 38 +- 26 files changed, 1833 insertions(+), 868 deletions(-) create mode 100644 include/nil/crypto3/zk/commitments/polynomial/kzg_v2.hpp rename include/nil/crypto3/zk/snark/systems/plonk/placeholder/{ => detail}/profiling.hpp (58%) diff --git a/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp b/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp index 1d65d0613..4734d690c 100644 --- a/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp +++ b/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include @@ -73,15 +75,13 @@ namespace nil { * */ template> + std::size_t M, typename GrindingType = nil::crypto3::zk::commitments::proof_of_work> struct basic_batched_fri { BOOST_STATIC_ASSERT_MSG(M == 2, "unsupported m value!"); - constexpr static const std::size_t m = M; - constexpr static const std::size_t lambda = Lambda; + constexpr static const bool is_fri = true; - constexpr static const bool use_grinding = UseGrinding; + constexpr static const std::size_t m = M; using grinding_type = GrindingType; typedef FieldType field_type; @@ -120,18 +120,81 @@ namespace nil { // needs to be marshalled is a part of params_type. using grinding_type = GrindingType; - constexpr static std::size_t lambda = Lambda; + std::size_t lambda; + bool use_grinding; + std::size_t grinding_parameter; constexpr static std::size_t m = M; - constexpr static bool use_grinding = UseGrinding; - params_type(const params_type &other) = default; - params_type() = default; + static std::vector generate_random_step_list(const std::size_t r, const int max_step) { + using dist_type = std::uniform_int_distribution; + static std::random_device random_engine; + + std::vector step_list; + std::size_t steps_sum = 0; + while (steps_sum != r) { + if (r - steps_sum <= max_step) { + while (r - steps_sum != 1) { + step_list.emplace_back(r - steps_sum - 1); + steps_sum += step_list.back(); + } + step_list.emplace_back(1); + steps_sum += step_list.back(); + } else { + step_list.emplace_back(dist_type(1, max_step)(random_engine)); + steps_sum += step_list.back(); + } + } + return step_list; + } + + //params_type(const params_type &other){} + // TODO when marshalling will be fine + params_type( + std::size_t max_step, + std::size_t degree_log, + std::size_t lambda, + std::size_t expand_factor, + bool use_grinding = false, + std::size_t grinding_parameter = 0xFFFF + ): lambda(lambda) + , use_grinding(use_grinding) + , grinding_parameter(grinding_parameter) + , max_degree((1 << degree_log) - 1) + , D(math::calculate_domain_set(degree_log + expand_factor, degree_log - 1)) + , r( degree_log - 1 ) + , step_list(generate_random_step_list(r, max_step)) + , expand_factor(expand_factor) + { } + + params_type( + std::vector step_list_in, + std::size_t degree_log, + std::size_t lambda, + std::size_t expand_factor, + bool use_grinding = false, + std::size_t grinding_parameter = 0xFFFF + ): lambda(lambda) + , use_grinding(use_grinding) + , grinding_parameter(grinding_parameter) + , max_degree((1 << degree_log) - 1) + , D(math::calculate_domain_set(degree_log + expand_factor, std::accumulate(step_list_in.begin(), step_list_in.end(), 0))) + , r(std::accumulate(step_list_in.begin(), step_list_in.end(), 0)) + , step_list(step_list_in) + , expand_factor(expand_factor) + { } + params_type( std::size_t max_degree, std::vector>> D, std::vector step_list_in, - std::size_t expand_factor - ) : max_degree(max_degree) + std::size_t expand_factor, + std::size_t lambda, + bool use_grinding = false, + std::size_t grinding_parameter = 0xFFFF + ) : lambda(lambda) + , use_grinding(use_grinding) + , grinding_parameter(grinding_parameter) + , max_degree(max_degree) , D(D) , r(std::accumulate(step_list_in.begin(), step_list_in.end(), 0)) , step_list(step_list_in) @@ -139,7 +202,24 @@ namespace nil { {} bool operator==(const params_type &rhs) const { - return r == rhs.r && max_degree == rhs.max_degree && D == rhs.D && step_list == rhs.step_list; + if( D.size() != rhs.D.size() ){ + return false; + } + for( std::size_t i = 0; i < D.size(); i++){ + if( D[i]->get_domain_element(1) != rhs.D[i]->get_domain_element(1) ){ + return false; + } + } + if(use_grinding && rhs.use_grinding && grinding_parameter != rhs.grinding_parameter){ + return false; + } + return r == rhs.r + && max_degree == rhs.max_degree + && step_list == rhs.step_list + && expand_factor == rhs.expand_factor + && lambda == rhs.lambda + && use_grinding == rhs.use_grinding + ; } bool operator!=(const params_type &rhs) const { @@ -213,15 +293,10 @@ namespace nil { std::vector fri_roots; // 0,..step_list.size() math::polynomial final_polynomial; - std::array query_proofs; // 0...lambda - 1 + std::vector query_proofs; // 0...lambda - 1 typename GrindingType::output_type proof_of_work; }; }; - template - constexpr bool use_grinding() - { - return FRI::use_grinding; - } } // namespace detail } // namespace commitments @@ -231,8 +306,8 @@ namespace nil { std::is_base_of< commitments::detail::basic_batched_fri< typename FRI::field_type, typename FRI::merkle_tree_hash_type, - typename FRI::transcript_hash_type, FRI::lambda, FRI::m, - FRI::use_grinding, typename FRI::grinding_type + typename FRI::transcript_hash_type, FRI::m, + typename FRI::grinding_type >, FRI >::value, @@ -247,8 +322,8 @@ namespace nil { std::is_base_of< commitments::detail::basic_batched_fri< typename FRI::field_type, typename FRI::merkle_tree_hash_type, - typename FRI::transcript_hash_type, FRI::lambda, FRI::m, - FRI::use_grinding, typename FRI::grinding_type + typename FRI::transcript_hash_type, FRI::m, + typename FRI::grinding_type >, FRI>::value, bool>::type = true> @@ -274,8 +349,7 @@ namespace nil { typename FRI::field_type, typename FRI::merkle_tree_hash_type, typename FRI::transcript_hash_type, - FRI::lambda, FRI::m, - FRI::use_grinding, typename FRI::grinding_type + FRI::m, typename FRI::grinding_type >, FRI>::value, bool>::type = true> @@ -334,8 +408,7 @@ namespace nil { commitments::detail::basic_batched_fri< typename FRI::field_type, typename FRI::merkle_tree_hash_type, typename FRI::transcript_hash_type, - FRI::lambda, FRI::m, - FRI::use_grinding, typename FRI::grinding_type + FRI::m, typename FRI::grinding_type >, FRI>::value, bool>::type = true> @@ -356,8 +429,8 @@ namespace nil { std::is_base_of< commitments::detail::basic_batched_fri< typename FRI::field_type, typename FRI::merkle_tree_hash_type, - typename FRI::transcript_hash_type, FRI::lambda, FRI::m, - FRI::use_grinding, typename FRI::grinding_type>, + typename FRI::transcript_hash_type, + FRI::m, typename FRI::grinding_type>, FRI>::value, bool>::type = true> static typename std::enable_if< @@ -425,8 +498,7 @@ namespace nil { commitments::detail::basic_batched_fri< typename FRI::field_type, typename FRI::merkle_tree_hash_type, typename FRI::transcript_hash_type, - FRI::lambda, FRI::m, - FRI::use_grinding, typename FRI::grinding_type>, + FRI::m, typename FRI::grinding_type>, FRI>::value, bool>::type = true> static typename std::enable_if< @@ -594,8 +666,7 @@ namespace nil { commitments::detail::basic_batched_fri< typename FRI::field_type, typename FRI::merkle_tree_hash_type, typename FRI::transcript_hash_type, - FRI::lambda, FRI::m, - FRI::use_grinding, typename FRI::grinding_type>, + FRI::m, typename FRI::grinding_type>, FRI>::value, bool>::type = true> static typename FRI::proof_type proof_eval( @@ -666,12 +737,12 @@ namespace nil { } // Grinding - if( FRI::use_grinding ){ - proof.proof_of_work = FRI::grinding_type::generate(transcript); + if( fri_params.use_grinding ){ + proof.proof_of_work = FRI::grinding_type::generate(transcript, fri_params.grinding_parameter); } // Query phase - std::array query_proofs; + std::vector query_proofs(fri_params.lambda); // If we have DFS polynomials, and we are going to resize them, better convert them to coefficients form, // and compute their values in those 2 * FRI::lambda points each, which is normally 2 * 20. @@ -700,10 +771,16 @@ namespace nil { } } - for (std::size_t query_id = 0; query_id < FRI::lambda; query_id++) { + for (std::size_t query_id = 0; query_id < fri_params.lambda; query_id++) { std::size_t domain_size = fri_params.D[0]->size(); - std::uint64_t x_index = (transcript.template int_challenge()) % domain_size; - typename FRI::field_type::value_type x = fri_params.D[0]->get_domain_element(x_index); + typename FRI::field_type::value_type x = transcript.template challenge(); + x = x.pow((FRI::field_type::modulus - 1)/domain_size); + std::uint64_t x_index = 0; + for( x_index = 0; x_index < domain_size; x_index++ ){ + if( fri_params.D[0]->get_domain_element(x_index) == x ){ + break; + } + } t = 0; std::vector> s; @@ -732,22 +809,43 @@ namespace nil { ) { if (g_k[polynomial_index].size() == fri_params.D[0]->size()) { for (std::size_t j = 0; j < coset_size / FRI::m; j++) { - initial_proof[k].values[polynomial_index][j][0] = g_k[polynomial_index][s_indices[j][0]]; - initial_proof[k].values[polynomial_index][j][1] = g_k[polynomial_index][s_indices[j][1]]; + std::size_t ind0 = std::min(s_indices[j][0], s_indices[j][1]); + std::size_t ind1 = std::max(s_indices[j][0], s_indices[j][1]); + initial_proof[k].values[polynomial_index][j][0] = g_k[polynomial_index][ind0]; + initial_proof[k].values[polynomial_index][j][1] = g_k[polynomial_index][ind1]; } } else { // Convert to coefficients form and evaluate. coset_size / FRI::m is usually just 1, // It makes no sense to resize in dfs form to then use just 2 values in 2 points. for (std::size_t j = 0; j < coset_size / FRI::m; j++) { - initial_proof[k].values[polynomial_index][j][0] = g_coeffs[k][polynomial_index].evaluate(s[j][0]); - initial_proof[k].values[polynomial_index][j][1] = g_coeffs[k][polynomial_index].evaluate(s[j][1]); + typename FRI::field_type::value_type s0; + typename FRI::field_type::value_type s1; + if( s_indices[j][0] < s_indices[j][1]){ + s0 = s[j][0]; + s1 = s[j][1]; + } else { + s0 = s[j][1]; + s1 = s[j][0]; + } + initial_proof[k].values[polynomial_index][j][0] = g_coeffs[k][polynomial_index].evaluate(s0); + initial_proof[k].values[polynomial_index][j][1] = g_coeffs[k][polynomial_index].evaluate(s1); } } } else { // Same for poly in coefficients form. for (std::size_t j = 0; j < coset_size / FRI::m; j++) { - initial_proof[k].values[polynomial_index][j][0] = g_k[polynomial_index].evaluate(s[j][0]); - initial_proof[k].values[polynomial_index][j][1] = g_k[polynomial_index].evaluate(s[j][1]); + typename FRI::field_type::value_type s0; + typename FRI::field_type::value_type s1; + + if( s_indices[j][0] < s_indices[j][1]){ + s0 = s[j][0]; + s1 = s[j][1]; + } else { + s0 = s[j][1]; + s1 = s[j][0]; + } + initial_proof[k].values[polynomial_index][j][0] = g_k[polynomial_index].evaluate(s0); + initial_proof[k].values[polynomial_index][j][1] = g_k[polynomial_index].evaluate(s1); } } } @@ -759,7 +857,7 @@ namespace nil { ); } - // Fill query proofs + // Fill round proofs std::vector round_proofs; t = 0; round_proofs.resize(fri_params.step_list.size()); @@ -776,8 +874,9 @@ namespace nil { if (i < fri_params.step_list.size() - 1) { x_index %= fri_params.D[t]->size(); x = fri_params.D[t]->get_domain_element(x_index); - std::tie(s, s_indices) = calculate_s(x, x_index, fri_params.step_list[i + 1], - fri_params.D[t]); + std::tie(s, s_indices) = calculate_s( + x, x_index, fri_params.step_list[i + 1], fri_params.D[t] + ); std::size_t coset_size = 1 << fri_params.step_list[i + 1]; BOOST_ASSERT(coset_size / FRI::m == s.size()); @@ -787,20 +886,33 @@ namespace nil { for (std::size_t j = 0; j < coset_size / FRI::m; j++) { if constexpr (std::is_same, PolynomialType>::value) { - round_proofs[i].y[j][0] = fs[i + 1][s_indices[j][0]]; - round_proofs[i].y[j][1] = fs[i + 1][s_indices[j][1]]; + std::size_t ind0 = std::min(s_indices[j][0], s_indices[j][1]); + std::size_t ind1 = std::max(s_indices[j][0], s_indices[j][1]); + round_proofs[i].y[j][0] = fs[i + 1][ind0]; + round_proofs[i].y[j][1] = fs[i + 1][ind1]; } else { - round_proofs[i].y[j][0] = fs[i + 1].evaluate(s[j][0]); - round_proofs[i].y[j][1] = fs[i + 1].evaluate(s[j][1]); + typename FRI::field_type::value_type s0 = (s_indices[j][0] < s_indices[j][1] ? s[j][0] : s[j][1]); + typename FRI::field_type::value_type s1 = (s_indices[j][0] > s_indices[j][1] ? s[j][0] : s[j][1]); + round_proofs[i].y[j][0] = fs[i + 1].evaluate(s0); + round_proofs[i].y[j][1] = fs[i + 1].evaluate(s1); } } } else { x_index %= fri_params.D[t - 1]->size(); x = fri_params.D[t - 1]->get_domain_element(x_index); x = x * x; + + // Last step + // Assume that FRI rounds continues with step == 1 + // x_index % (domain_size / 2) -- index in the next round + // fri_params.D[t-1]->size()/4 -- half of the next domain size + // Then next round values will be written in the straight order if next round index < next domain size - 1 + // Otherwise, they will be written in the reverse order. + + std::size_t ind = (x_index %(fri_params.D[t-1]->size()/2) < fri_params.D[t-1]->size()/4)? 0: 1; round_proofs[i].y.resize(1); - round_proofs[i].y[0][0] = final_polynomial.evaluate(x); - round_proofs[i].y[0][1] = final_polynomial.evaluate(-x); + round_proofs[i].y[0][ind] = final_polynomial.evaluate(x); + round_proofs[i].y[0][1-ind] = final_polynomial.evaluate(-x); } } typename FRI::query_proof_type query_proof = {std::move(initial_proof), std::move(round_proofs)}; @@ -811,7 +923,7 @@ namespace nil { proof.final_polynomial = std::move(final_polynomial); proof.query_proofs = std::move(query_proofs); - return proof;//typename FRI::proof_type{fri_roots, final_polynomial, query_proofs}; + return proof; } template @@ -846,16 +958,22 @@ namespace nil { } } - if(FRI::use_grinding && !FRI::grinding_type::verify(transcript, proof.proof_of_work)){ + if(fri_params.use_grinding && !FRI::grinding_type::verify(transcript, proof.proof_of_work, fri_params.grinding_parameter)){ return false; } - for (std::size_t query_id = 0; query_id < FRI::lambda; query_id++) { + for (std::size_t query_id = 0; query_id < fri_params.lambda; query_id++) { const typename FRI::query_proof_type &query_proof = proof.query_proofs[query_id]; std::size_t domain_size = fri_params.D[0]->size(); std::size_t coset_size = 1 << fri_params.step_list[0]; - std::uint64_t x_index = (transcript.template int_challenge()) % domain_size; - typename FRI::field_type::value_type x = fri_params.D[0]->get_domain_element(x_index); + typename FRI::field_type::value_type x_challenge = transcript.template challenge(); + typename FRI::field_type::value_type x = x_challenge.pow((FRI::field_type::modulus - 1)/domain_size); + std::uint64_t x_index = 0; + for( x_index = 0; x_index < domain_size; x_index++ ){ + if( fri_params.D[0]->get_domain_element(x_index) == x ){ + break; + } + } std::vector> s; std::vector> s_indices; @@ -876,11 +994,11 @@ namespace nil { for (std::size_t i = 0; i < query_proof.initial_proof.at(k).values.size(); i++) { for (auto [idx, pair_idx] : correct_order_idx) { typename FRI::field_element_type leaf_val0( - query_proof.initial_proof.at(k).values[i][idx][pair_idx] + query_proof.initial_proof.at(k).values[i][idx][0] ); leaf_val0.write(write_iter, FRI::field_element_type::length()); typename FRI::field_element_type leaf_val1( - query_proof.initial_proof.at(k).values[i][idx][1-pair_idx] + query_proof.initial_proof.at(k).values[i][idx][1] ); leaf_val1.write(write_iter, FRI::field_element_type::length()); } @@ -912,15 +1030,16 @@ namespace nil { theta_acc *= theta; } for (size_t j = 0; j < coset_size / FRI::m; j++) { + std::size_t id0 = s_indices[j][0] < s_indices[j][1] ? 0 : 1; + std::size_t id1 = s_indices[j][0] < s_indices[j][1] ? 1 : 0; Q[j][0] -= combined_U[p]; Q[j][1] -= combined_U[p]; - Q[j][0] /= denominators[p].evaluate(s[j][0]); - Q[j][1] /= denominators[p].evaluate(s[j][1]); + Q[j][0] /= denominators[p].evaluate(s[j][id0]); + Q[j][1] /= denominators[p].evaluate(s[j][id1]); y[j][0] += Q[j][0]; y[j][1] += Q[j][1]; } } - // Check round proofs std::size_t t = 0; typename FRI::polynomial_values_type y_next; @@ -935,9 +1054,9 @@ namespace nil { auto correct_order_idx = get_correct_order(x_index, domain_size, fri_params.step_list[i], s_indices); for (auto [idx, pair_idx]: correct_order_idx) { - typename FRI::field_element_type leaf_val0(y[idx][pair_idx]); + typename FRI::field_element_type leaf_val0(y[idx][0]); leaf_val0.write(write_iter, FRI::field_element_type::length()); - typename FRI::field_element_type leaf_val1(y[idx][1 - pair_idx]); + typename FRI::field_element_type leaf_val1(y[idx][1]); leaf_val1.write(write_iter, FRI::field_element_type::length()); } if (!query_proof.round_proofs[i].p.validate(leaf_data)) { @@ -952,57 +1071,89 @@ namespace nil { domain_size = fri_params.D[t]->size(); x_index %= domain_size; x = fri_params.D[t]->get_domain_element(x_index); + auto [s_next, s_indices_next] = calculate_s( + x *x , x_index% fri_params.D[t+1]->size(), + fri_params.step_list[i], fri_params.D[t+1] + ); std::tie(s, s_indices) = calculate_s(x, x_index, fri_params.step_list[i], fri_params.D[t]); + std::size_t new_domain_size = domain_size; for (std::size_t y_ind = 0; y_ind < y_next.size(); y_ind++) { + std::size_t ind0 = s_indices[2 * y_ind][0] < s_indices[2 * y_ind][1] ? 0 : 1; + auto s_ch = s[2*y_ind][ind0]; + std::vector> interpolation_points_l{ - std::make_pair(s[2 * y_ind][0], y[2 * y_ind][0]), - std::make_pair(s[2 * y_ind][1], y[2 * y_ind][1]), + std::make_pair(s_ch, y[2 * y_ind][0]), + std::make_pair(-s_ch, y[2 * y_ind][1]), }; math::polynomial interpolant_l = math::lagrange_interpolation(interpolation_points_l); - y_next[y_ind][0] = interpolant_l.evaluate(alphas[t]); + ind0 = s_indices[2 * y_ind + 1][0] < s_indices[2 * y_ind + 1][1] ? 0 : 1; + s_ch = s[2*y_ind + 1][ind0]; std::vector> interpolation_points_r{ - std::make_pair(s[2 * y_ind + 1][0], y[2 * y_ind + 1][0]), - std::make_pair(s[2 * y_ind + 1][1], y[2 * y_ind + 1][1]), + std::make_pair(s_ch, y[2 * y_ind + 1][0]), + std::make_pair(-s_ch, y[2 * y_ind + 1][1]), }; math::polynomial interpolant_r = math::lagrange_interpolation(interpolation_points_r); - y_next[y_ind][1] = interpolant_r.evaluate(alphas[t]); + + new_domain_size /= FRI::m; + + std::size_t interpolant_index_l = s_indices_next[y_ind][0]; + std::size_t interpolant_index_r = s_indices_next[y_ind][1]; + + if( interpolant_index_l < interpolant_index_r){ + y_next[y_ind][0] = interpolant_l.evaluate(alphas[t]); + y_next[y_ind][1] = interpolant_r.evaluate(alphas[t]); + } else { + y_next[y_ind][0] = interpolant_r.evaluate(alphas[t]); + y_next[y_ind][1] = interpolant_l.evaluate(alphas[t]); + } } x = x * x; y = y_next; } + domain_size = fri_params.D[t]->size(); + x_index %= domain_size; + x = fri_params.D[t]->get_domain_element(x_index); std::tie(s, s_indices) = calculate_s(x, x_index, fri_params.step_list[i], fri_params.D[t]); + std::size_t ind0 = s_indices[0][0] < s_indices[0][1] ? 0 : 1; + auto s_ch = s[0][ind0]; std::vector> interpolation_points{ - std::make_pair(s[0][0], y[0][0]), - std::make_pair(s[0][1], y[0][1]), + std::make_pair(s_ch, y[0][0]), + std::make_pair(-s_ch, y[0][1]), }; math::polynomial interpolant_poly = math::lagrange_interpolation(interpolation_points); auto interpolant = interpolant_poly.evaluate(alphas[t]); - if (interpolant != query_proof.round_proofs[i].y[0][0]) { + + std::size_t ind = s_indices[0][ind0] % (fri_params.D[t]->size()/2) < fri_params.D[t]->size() / 4 ? 0 : 1; + if (interpolant != query_proof.round_proofs[i].y[0][ind]) { return false; } // For the last round we check final polynomial nor colinear_check - t++; y = query_proof.round_proofs[i].y; if (i < fri_params.step_list.size() - 1) { + t++; domain_size = fri_params.D[t]->size(); x_index %= domain_size; x = fri_params.D[t]->get_domain_element(x_index); } } + // Final polynomial check + x_index %= fri_params.D[t]->size(); + x = fri_params.D[t]->get_domain_element(x_index); x = x * x; - if (y[0][0] != proof.final_polynomial.evaluate(x)) { + std::size_t ind = x_index % (fri_params.D[t]->size() / 2) < fri_params.D[t]->size() / 4 ? 0 : 1; + if (y[0][ind] != proof.final_polynomial.evaluate(x)) { return false; } - if (y[0][1] != proof.final_polynomial.evaluate(-x)) { + if (y[0][1-ind] != proof.final_polynomial.evaluate(-x)) { return false; } } @@ -1014,4 +1165,4 @@ namespace nil { } // namespace crypto3 } // namespace nil -#endif // CRYPTO3_ZK_COMMITMENTS_BASIC_FRI_HPP \ No newline at end of file +#endif // CRYPTO3_ZK_COMMITMENTS_BASIC_FRI_HPP diff --git a/include/nil/crypto3/zk/commitments/detail/polynomial/proof_of_work.hpp b/include/nil/crypto3/zk/commitments/detail/polynomial/proof_of_work.hpp index f7f855f1d..28be4b534 100644 --- a/include/nil/crypto3/zk/commitments/detail/polynomial/proof_of_work.hpp +++ b/include/nil/crypto3/zk/commitments/detail/polynomial/proof_of_work.hpp @@ -37,22 +37,14 @@ namespace nil { namespace crypto3 { namespace zk { namespace commitments { - template + template class proof_of_work { public: using transcript_hash_type = TranscriptHashType; using transcript_type = transcript::fiat_shamir_heuristic_sequential; using output_type = OutType; - constexpr static std::uint32_t mask = MASK; - - static inline boost::property_tree::ptree get_params() { - boost::property_tree::ptree params; - params.put("mask", mask); - return params; - } - - static inline OutType generate(transcript_type &transcript) { + static inline OutType generate(transcript_type &transcript, OutType mask=0xFFFF) { output_type proof_of_work = std::rand(); output_type result; std::vector bytes(4); @@ -75,7 +67,7 @@ namespace nil { return proof_of_work; } - static inline bool verify(transcript_type &transcript, output_type proof_of_work) { + static inline bool verify(transcript_type &transcript, output_type proof_of_work, OutType mask=0xFFFF) { std::vector bytes(4); bytes[0] = std::uint8_t((proof_of_work&0xFF000000)>>24); bytes[1] = std::uint8_t((proof_of_work&0x00FF0000)>>16); @@ -91,7 +83,7 @@ namespace nil { // amount of bits for grinding instead of the mask. // This was done because the actual mask is applied to the high bits instead of the low bits // which makes manually setting the mask error-prone. - template + template class field_proof_of_work { public: using transcript_hash_type = TranscriptHashType; @@ -99,23 +91,17 @@ namespace nil { using value_type = typename FieldType::value_type; using integral_type = typename FieldType::integral_type; - constexpr static const integral_type mask = - (GrindingBits > 0 ? - ((integral_type(2) << GrindingBits - 1) - 1) << (FieldType::modulus_bits - GrindingBits) - : 0); - - static inline boost::property_tree::ptree get_params() { - boost::property_tree::ptree params; - params.put("mask", mask); - return params; - } - - static inline value_type generate(transcript_type &transcript) { + static inline value_type generate(transcript_type &transcript, std::size_t GrindingBits=16) { static boost::random::random_device dev; static nil::crypto3::random::algebraic_engine random_engine(dev); value_type proof_of_work = random_engine(); integral_type result; + integral_type mask = + (GrindingBits > 0 ? + ((integral_type(1) << GrindingBits) - 1) << (FieldType::modulus_bits - GrindingBits) + : 0); + while( true ) { transcript_type tmp_transcript = transcript; tmp_transcript(proof_of_work); @@ -129,8 +115,13 @@ namespace nil { return proof_of_work; } - static inline bool verify(transcript_type &transcript, value_type proof_of_work) { + static inline bool verify(transcript_type &transcript, value_type proof_of_work, std::size_t GrindingBits=16) { transcript(proof_of_work); + integral_type mask = + (GrindingBits > 0 ? + ((integral_type(1) << GrindingBits) - 1) << (FieldType::modulus_bits - GrindingBits) + : 0); + integral_type result = integral_type(transcript.template challenge().data); return ((result & mask) == 0); } diff --git a/include/nil/crypto3/zk/commitments/polynomial/fri.hpp b/include/nil/crypto3/zk/commitments/polynomial/fri.hpp index e24ccb632..4e1a85275 100644 --- a/include/nil/crypto3/zk/commitments/polynomial/fri.hpp +++ b/include/nil/crypto3/zk/commitments/polynomial/fri.hpp @@ -64,21 +64,18 @@ namespace nil { template > struct fri : public detail::basic_batched_fri { using basic_fri = detail::basic_batched_fri; + M, GrindingType>; constexpr static const std::size_t m = basic_fri::m; constexpr static const std::size_t batches_num = basic_fri::batches_num; @@ -104,8 +101,7 @@ namespace nil { typename std::enable_if, FRI>::value, @@ -129,8 +125,7 @@ namespace nil { typename FRI::field_type, typename FRI::merkle_tree_hash_type, typename FRI::transcript_hash_type, - FRI::lambda, FRI::m, - FRI::use_grinding, + FRI::m, typename FRI::grinding_type >, FRI>::value, diff --git a/include/nil/crypto3/zk/commitments/polynomial/kzg.hpp b/include/nil/crypto3/zk/commitments/polynomial/kzg.hpp index c2781f968..b8bb181be 100644 --- a/include/nil/crypto3/zk/commitments/polynomial/kzg.hpp +++ b/include/nil/crypto3/zk/commitments/polynomial/kzg.hpp @@ -3,6 +3,7 @@ // Copyright (c) 2020-2021 Nikita Kaskov // Copyright (c) 2020-2021 Ilias Khairullin // Copyright (c) 2022 Ekaterina Chukavina +// Copyright (c) 2024 Vasiliy Olekhov // // MIT License // @@ -217,6 +218,9 @@ namespace nil { typename PolynomialType = math::polynomial_dfs > struct batched_kzg { + + constexpr static bool is_kzg = true; + typedef CurveType curve_type; typedef TranscriptHashType transcript_hash_type; typedef typename curve_type::gt_type::value_type gt_value_type; @@ -235,8 +239,10 @@ namespace nil { using commitment_type = std::vector; // Used in placeholder because it's easy to push it into transcript + using eval_storage_type = eval_storage; + struct proof_type { - eval_storage z; + eval_storage_type z; single_commitment_type kzg_proof; }; @@ -246,6 +252,7 @@ namespace nil { std::vector commitment_key; std::vector verification_key; + using params_single_commitment_type = commitment_type; params_type() {}; @@ -319,7 +326,7 @@ namespace nil { static void update_transcript(const typename KZG::public_key_type &public_key, typename KZG::transcript_type &transcript) { - /* The procedure of updating the transcript is subject to review and change + /* The procedure of updating the transcript is subject to review and change * #295 */ nil::marshalling::status_type status; @@ -605,8 +612,12 @@ namespace nil { namespace commitments{ // Placeholder-friendly class - template> - class kzg_commitment_scheme : public polys_evaluator{ + template + class kzg_commitment_scheme : + public polys_evaluator< + typename KZGScheme::params_type, + typename KZGScheme::commitment_type, + typename KZGScheme::poly_type> { public: using curve_type = typename KZGScheme::curve_type; using field_type = typename KZGScheme::field_type; @@ -616,7 +627,7 @@ namespace nil { using commitment_type = typename KZGScheme::commitment_type; using transcript_type = typename KZGScheme::transcript_type; using transcript_hash_type = typename KZGScheme::transcript_hash_type; - using poly_type = PolynomialType; + using poly_type = typename KZGScheme::poly_type; using proof_type = typename KZGScheme::proof_type; using endianness = nil::marshalling::option::big_endian; private: @@ -661,7 +672,7 @@ namespace nil { } void update_transcript(std::size_t batch_ind, typename KZGScheme::transcript_type &transcript) { - /* The procedure of updating the transcript is subject to review and change + /* The procedure of updating the transcript is subject to review and change * #295 */ // Push commitments to transcript @@ -823,262 +834,6 @@ namespace nil { } }; - - // Placeholder-friendly class, KZGv2 - /** - * References: - * "Efficient polynomial commitment schemes for - * multiple points and polynomials", - * Dan Boneh, Justin Drake, Ben Fisch, - * - */ - template> - class kzg_commitment_scheme_v2 : public polys_evaluator{ - public: - using curve_type = typename KZGScheme::curve_type; - using field_type = typename KZGScheme::field_type; - using params_type = typename KZGScheme::params_type; - - // This should be marshallable and transcriptable type - using commitment_type = typename KZGScheme::commitment_type; - using verification_key_type = typename curve_type::template g2_type<>::value_type; - using transcript_type = typename KZGScheme::transcript_type; - using transcript_hash_type = typename KZGScheme::transcript_hash_type; - using poly_type = PolynomialType; - struct proof_type { - eval_storage z; - typename KZGScheme::single_commitment_type pi_1, pi_2; - }; - using endianness = nil::marshalling::option::big_endian; - private: - params_type _params; - std::map _commitments; - std::map> _ind_commitments; - std::vector _merged_points; - protected: - - // Differs from static one by input parameters - void merge_eval_points() { - std::set set; - for( auto const &it:this->_points){ - auto k = it.first; - for (std::size_t i = 0; i < this->_points[k].size(); ++i) { - set.insert(this->_points[k][i].begin(), this->_points[k][i].end()); - } - } - _merged_points = std::vector(set.begin(), set.end()); - } - - typename math::polynomial - set_difference_polynom( - std::vector merged_points, - std::vector points - ) { - std::sort(merged_points.begin(), merged_points.end()); - std::sort(points.begin(), points.end()); - std::vector result; - std::set_difference(merged_points.begin(), merged_points.end(), points.begin(), points.end(), std::back_inserter(result)); - if (result.size() == 0) { - return typename math::polynomial({{1}}); - } - BOOST_ASSERT(this->get_V(result) * this->get_V(points) == this->get_V(merged_points)); - return this->get_V(result); - } - - void update_transcript(std::size_t batch_ind, typename KZGScheme::transcript_type &transcript) { - /* The procedure of updating the transcript is subject to review and change - * #295 */ - - // Push commitments to transcript - transcript(_commitments[batch_ind]); - - // Push evaluation points to transcript - for( std::size_t i = 0; i < this->_z.get_batch_size(batch_ind); i++){ - for( std::size_t j = 0; j < this->_z.get_poly_points_number(batch_ind, i); j++ ) { - nil::marshalling::status_type status; - std::vector byteblob = - nil::marshalling::pack(this->_z.get(batch_ind, i, j), status); - BOOST_ASSERT(status == nil::marshalling::status_type::success); - transcript(byteblob); - } - } - - // Push U polynomials to transcript - for (std::size_t i = 0; i < this->_points[batch_ind].size(); i++) { - auto poly = this->get_U(batch_ind, i); - for (std::size_t j = 0; j < poly.size(); ++j) { - nil::marshalling::status_type status; - std::vector byteblob = - nil::marshalling::pack(poly[j], status); - BOOST_ASSERT(status == nil::marshalling::status_type::success); - transcript(byteblob); - } - } - } - public: - // Interface function. Isn't useful here. - void mark_batch_as_fixed(std::size_t index) { - } - - kzg_commitment_scheme_v2(params_type kzg_params) : _params(kzg_params) {} - - // Differs from static, because we pack the result into byte blob. - commitment_type commit(std::size_t index){ - this->_ind_commitments[index] = {}; - this->state_commited(index); - - std::vector result = {}; - for (std::size_t i = 0; i < this->_polys[index].size(); ++i) { - BOOST_ASSERT(this->_polys[index][i].degree() <= _params.commitment_key.size()); - auto single_commitment = nil::crypto3::zk::algorithms::commit_one(_params, this->_polys[index][i]); - this->_ind_commitments[index].push_back(single_commitment); - nil::marshalling::status_type status; - std::vector single_commitment_bytes = - nil::marshalling::pack(single_commitment, status); - BOOST_ASSERT(status == nil::marshalling::status_type::success); - result.insert(result.end(), single_commitment_bytes.begin(), single_commitment_bytes.end()); - } - _commitments[index] = result; - return result; - } - - using preprocessed_data_type = bool; - preprocessed_data_type preprocess(transcript_type& transcript) const{ - return true; - } - - void setup(transcript_type& transcript, preprocessed_data_type b = true) { - // Nothing to be done here. - } - - proof_type proof_eval(transcript_type &transcript){ - this->eval_polys(); - this->merge_eval_points(); - - for( auto const &it: this->_commitments ){ - auto k = it.first; - update_transcript(k, transcript); - } - - auto theta = transcript.template challenge(); - auto theta_i = KZGScheme::scalar_value_type::one(); - auto f = math::polynomial::zero(); - - for( auto const &it: this->_polys ){ - auto k = it.first; - for (std::size_t i = 0; i < this->_z.get_batch_size(k); ++i) { - auto diffpoly = set_difference_polynom(_merged_points, this->_points.at(k)[i]); - auto f_i = math::polynomial( this->_polys[k][i].coefficients()); - f += theta_i * (f_i - this->get_U(k, i)) * diffpoly; - theta_i *= theta; - } - } - - BOOST_ASSERT( f % this->get_V(_merged_points) == math::polynomial::zero()); - f /= this->get_V(_merged_points); - - typename KZGScheme::single_commitment_type pi_1 = nil::crypto3::zk::algorithms::commit_one(_params, f); - - nil::marshalling::status_type status; - std::vector pi1_byteblob = nil::marshalling::pack(pi_1, status); - BOOST_ASSERT(status == nil::marshalling::status_type::success); - - transcript(pi1_byteblob); - - auto theta_2 = transcript.template challenge(); - math::polynomial theta_2_vanish = { -theta_2, 1 }; - - theta_i = KZGScheme::scalar_value_type::one(); - - auto L = math::polynomial::zero(); - - for( auto const &it: this->_polys ) { - auto k = it.first; - for (std::size_t i = 0; i < this->_z.get_batch_size(k); ++i) { - auto diffpoly = set_difference_polynom(_merged_points, this->_points.at(k)[i]); - auto Z_T_S_i = diffpoly.evaluate(theta_2); - auto f_i = math::polynomial(this->_polys[k][i].coefficients()); - L += theta_i * Z_T_S_i * (f_i - this->get_U(k, i).evaluate(theta_2)); - theta_i *= theta; - } - } - - L -= this->get_V(_merged_points).evaluate(theta_2) * f; - BOOST_ASSERT( L.evaluate(theta_2) == KZGScheme::scalar_value_type::zero() ); - L /= theta_2_vanish; - - typename KZGScheme::single_commitment_type pi_2 = nil::crypto3::zk::algorithms::commit_one(_params, L); - - /* TODO: Review the necessity of sending pi_2 to transcript */ - std::vector pi2_byteblob = nil::marshalling::pack(pi_2, status); - BOOST_ASSERT(status == nil::marshalling::status_type::success); - transcript(pi2_byteblob); - - return {this->_z, pi_1, pi_2}; - } - - bool verify_eval( - const proof_type &proof, - const std::map &commitments, - transcript_type &transcript - ) { - this->merge_eval_points(); - this->_commitments = commitments; - this->_z = proof.z; - - for (auto const &it: this->_commitments) { - auto k = it.first; - update_transcript(k, transcript); - } - - auto theta = transcript.template challenge(); - nil::marshalling::status_type status; - std::vector byteblob = nil::marshalling::pack(proof.pi_1, status); - BOOST_ASSERT(status == nil::marshalling::status_type::success); - transcript(byteblob); - auto theta_2 = transcript.template challenge(); - auto theta_i = KZGScheme::scalar_value_type::one(); - - auto F = KZGScheme::single_commitment_type::zero(); - auto rsum = KZGScheme::scalar_value_type::zero(); - - for (const auto &it: this->_commitments) { - auto k = it.first; - std::size_t blob_size = this->_commitments.at(k).size() / this->_points.at(k).size(); - std::vector byteblob(blob_size); - - for (std::size_t i = 0; i < this->_points.at(k).size(); ++i) { - for (std::size_t j = 0; j < blob_size; j++) { - byteblob[j] = this->_commitments.at(k)[i * blob_size + j]; - } - nil::marshalling::status_type status; - typename curve_type::template g1_type<>::value_type - cm_i = nil::marshalling::pack(byteblob, status); - BOOST_ASSERT(status == nil::marshalling::status_type::success); - auto Z_T_S_i = set_difference_polynom(_merged_points, this->_points.at(k)[i]).evaluate(theta_2); - F += theta_i * Z_T_S_i * cm_i; - rsum += theta_i * Z_T_S_i * this->get_U(k, i).evaluate(theta_2); - - theta_i *= theta; - } - } - - F -= rsum * KZGScheme::single_commitment_type::one(); - F -= this->get_V(_merged_points).evaluate(theta_2) * proof.pi_1; - - auto left_side_pairing = nil::crypto3::algebra::pair_reduced - ( F + theta_2 * proof.pi_2, verification_key_type::one() ); - - auto right_side_pairing = nil::crypto3::algebra::pair_reduced - ( proof.pi_2, _params.verification_key[1] ); - - return left_side_pairing == right_side_pairing; - } - - const params_type& get_commitment_params() const { - return _params; - } - }; } // namespace commitments } // namespace zk } // namespace crypto3 diff --git a/include/nil/crypto3/zk/commitments/polynomial/kzg_v2.hpp b/include/nil/crypto3/zk/commitments/polynomial/kzg_v2.hpp new file mode 100644 index 000000000..718501dcd --- /dev/null +++ b/include/nil/crypto3/zk/commitments/polynomial/kzg_v2.hpp @@ -0,0 +1,348 @@ +//-----------------------------------------------------------------------// +// Copyright (c) 2018-2021 Mikhail Komarov +// Copyright (c) 2020-2021 Nikita Kaskov +// Copyright (c) 2020-2021 Ilias Khairullin +// Copyright (c) 2022 Ekaterina Chukavina +// Copyright (c) 2024 Vasiliy Olekhov +// +// MIT License +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +//---------------------------------------------------------------------------// + +#ifndef CRYPTO3_ZK_COMMITMENTS_KZG_V2_HPP +#define CRYPTO3_ZK_COMMITMENTS_KZG_V2_HPP + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +using namespace nil::crypto3::math; + +using namespace nil::crypto3; + +namespace nil { + namespace crypto3 { + namespace zk { + namespace commitments { + // Placeholder-friendly class, KZGv2 + /** + * References: + * "Efficient polynomial commitment schemes for + * multiple points and polynomials", + * Dan Boneh, Justin Drake, Ben Fisch, + * + */ + template + class kzg_commitment_scheme_v2 : + public polys_evaluator< + typename KZGScheme::params_type, + typename KZGScheme::commitment_type, + typename KZGScheme::poly_type> { + public: + static constexpr bool is_kzg(){ return true; } + + using curve_type = typename KZGScheme::curve_type; + using field_type = typename KZGScheme::field_type; + using params_type = typename KZGScheme::params_type; + + // This should be marshallable and transcriptable type + using commitment_type = typename KZGScheme::commitment_type; + using verification_key_type = typename curve_type::template g2_type<>::value_type; + using transcript_type = typename KZGScheme::transcript_type; + using transcript_hash_type = typename KZGScheme::transcript_hash_type; + using poly_type = typename KZGScheme::poly_type; + + using eval_storage_type = eval_storage; + using single_commitment_type = typename KZGScheme::single_commitment_type; + + struct proof_type { + eval_storage_type z; + single_commitment_type pi_1, pi_2; + bool operator==(proof_type const& other) const { + return (z == other.z) && (pi_1 == other.pi_1) && (pi_2 == other.pi_2); + } + bool operator!=(proof_type const& other) const { + return !(*this == other); + } + }; + using endianness = nil::marshalling::option::big_endian; + private: + params_type _params; + std::map _commitments; + std::map> _ind_commitments; + std::vector _merged_points; + protected: + + // Differs from static one by input parameters + void merge_eval_points() { + std::set set; + for( auto const &it:this->_points){ + auto k = it.first; + for (std::size_t i = 0; i < this->_points[k].size(); ++i) { + set.insert(this->_points[k][i].begin(), this->_points[k][i].end()); + } + } + _merged_points = std::vector(set.begin(), set.end()); + } + + typename math::polynomial + set_difference_polynom( + std::vector merged_points, + std::vector points + ) { + std::sort(merged_points.begin(), merged_points.end()); + std::sort(points.begin(), points.end()); + std::vector result; + std::set_difference(merged_points.begin(), merged_points.end(), points.begin(), points.end(), std::back_inserter(result)); + if (result.size() == 0) { + return typename math::polynomial({{1}}); + } + BOOST_ASSERT(this->get_V(result) * this->get_V(points) == this->get_V(merged_points)); + return this->get_V(result); + } + + void update_transcript(std::size_t batch_ind, typename KZGScheme::transcript_type &transcript) { + /* The procedure of updating the transcript is subject to review and change + * #295 */ + + // Push commitments to transcript + transcript(_commitments[batch_ind]); + + // Push evaluation points to transcript + for( std::size_t i = 0; i < this->_z.get_batch_size(batch_ind); i++){ + for( std::size_t j = 0; j < this->_z.get_poly_points_number(batch_ind, i); j++ ) { + nil::marshalling::status_type status; + std::vector byteblob = + nil::marshalling::pack(this->_z.get(batch_ind, i, j), status); + BOOST_ASSERT(status == nil::marshalling::status_type::success); + transcript(byteblob); + } + } + + // Push U polynomials to transcript + for (std::size_t i = 0; i < this->_points[batch_ind].size(); i++) { + auto poly = this->get_U(batch_ind, i); + for (std::size_t j = 0; j < poly.size(); ++j) { + nil::marshalling::status_type status; + std::vector byteblob = + nil::marshalling::pack(poly[j], status); + BOOST_ASSERT(status == nil::marshalling::status_type::success); + transcript(byteblob); + } + } + } + public: + // Interface function. Isn't useful here. + void mark_batch_as_fixed(std::size_t index) { + } + + static params_type create_params(std::size_t d, typename KZGScheme::scalar_value_type alpha) { + return params_type(d, 1, alpha); + } + + kzg_commitment_scheme_v2(params_type kzg_params) : _params(kzg_params) { + BOOST_ASSERT( kzg_params.verification_key.size() == 2); + } + + // Differs from static, because we pack the result into byte blob. + commitment_type commit(std::size_t index){ + this->_ind_commitments[index] = {}; + this->state_commited(index); + + std::vector result = {}; + for (std::size_t i = 0; i < this->_polys[index].size(); ++i) { + BOOST_ASSERT(this->_polys[index][i].degree() <= _params.commitment_key.size()); + auto single_commitment = nil::crypto3::zk::algorithms::commit_one(_params, this->_polys[index][i]); + this->_ind_commitments[index].push_back(single_commitment); + nil::marshalling::status_type status; + std::vector single_commitment_bytes = + nil::marshalling::pack(single_commitment, status); + BOOST_ASSERT(status == nil::marshalling::status_type::success); + result.insert(result.end(), single_commitment_bytes.begin(), single_commitment_bytes.end()); + } + _commitments[index] = result; + return result; + } + + using preprocessed_data_type = bool; + preprocessed_data_type preprocess(transcript_type& transcript) const{ + return true; + } + + void setup(transcript_type& transcript, preprocessed_data_type b = true) { + // Nothing to be done here. + } + + proof_type proof_eval(transcript_type &transcript){ + this->eval_polys(); + this->merge_eval_points(); + + for( auto const &it: this->_commitments ){ + auto k = it.first; + update_transcript(k, transcript); + } + + auto theta = transcript.template challenge(); + auto theta_i = KZGScheme::scalar_value_type::one(); + auto f = math::polynomial::zero(); + + for( auto const &it: this->_polys ){ + auto k = it.first; + for (std::size_t i = 0; i < this->_z.get_batch_size(k); ++i) { + auto diffpoly = set_difference_polynom(_merged_points, this->_points.at(k)[i]); + auto f_i = math::polynomial( this->_polys[k][i].coefficients()); + f += theta_i * (f_i - this->get_U(k, i)) * diffpoly; + theta_i *= theta; + } + } + + BOOST_ASSERT( f % this->get_V(_merged_points) == math::polynomial::zero()); + f /= this->get_V(_merged_points); + + typename KZGScheme::single_commitment_type pi_1 = nil::crypto3::zk::algorithms::commit_one(_params, f); + + nil::marshalling::status_type status; + std::vector pi1_byteblob = nil::marshalling::pack(pi_1, status); + BOOST_ASSERT(status == nil::marshalling::status_type::success); + + transcript(pi1_byteblob); + + auto theta_2 = transcript.template challenge(); + math::polynomial theta_2_vanish = { -theta_2, 1 }; + + theta_i = KZGScheme::scalar_value_type::one(); + + auto L = math::polynomial::zero(); + + for( auto const &it: this->_polys ) { + auto k = it.first; + for (std::size_t i = 0; i < this->_z.get_batch_size(k); ++i) { + auto diffpoly = set_difference_polynom(_merged_points, this->_points.at(k)[i]); + auto Z_T_S_i = diffpoly.evaluate(theta_2); + auto f_i = math::polynomial(this->_polys[k][i].coefficients()); + L += theta_i * Z_T_S_i * (f_i - this->get_U(k, i).evaluate(theta_2)); + theta_i *= theta; + } + } + + L -= this->get_V(_merged_points).evaluate(theta_2) * f; + BOOST_ASSERT( L.evaluate(theta_2) == KZGScheme::scalar_value_type::zero() ); + L /= theta_2_vanish; + + typename KZGScheme::single_commitment_type pi_2 = nil::crypto3::zk::algorithms::commit_one(_params, L); + + /* TODO: Review the necessity of sending pi_2 to transcript */ + std::vector pi2_byteblob = nil::marshalling::pack(pi_2, status); + BOOST_ASSERT(status == nil::marshalling::status_type::success); + transcript(pi2_byteblob); + + return {this->_z, pi_1, pi_2}; + } + + bool verify_eval( + const proof_type &proof, + const std::map &commitments, + transcript_type &transcript + ) { + this->merge_eval_points(); + this->_commitments = commitments; + this->_z = proof.z; + + for (auto const &it: this->_commitments) { + auto k = it.first; + update_transcript(k, transcript); + } + + auto theta = transcript.template challenge(); + nil::marshalling::status_type status; + std::vector byteblob = nil::marshalling::pack(proof.pi_1, status); + BOOST_ASSERT(status == nil::marshalling::status_type::success); + transcript(byteblob); + auto theta_2 = transcript.template challenge(); + auto theta_i = KZGScheme::scalar_value_type::one(); + + auto F = KZGScheme::single_commitment_type::zero(); + auto rsum = KZGScheme::scalar_value_type::zero(); + + for (const auto &it: this->_commitments) { + auto k = it.first; + std::size_t blob_size = this->_commitments.at(k).size() / this->_points.at(k).size(); + std::vector byteblob(blob_size); + + for (std::size_t i = 0; i < this->_points.at(k).size(); ++i) { + for (std::size_t j = 0; j < blob_size; j++) { + byteblob[j] = this->_commitments.at(k)[i * blob_size + j]; + } + nil::marshalling::status_type status; + typename curve_type::template g1_type<>::value_type + cm_i = nil::marshalling::pack(byteblob, status); + BOOST_ASSERT(status == nil::marshalling::status_type::success); + auto Z_T_S_i = set_difference_polynom(_merged_points, this->_points.at(k)[i]).evaluate(theta_2); + F += theta_i * Z_T_S_i * cm_i; + rsum += theta_i * Z_T_S_i * this->get_U(k, i).evaluate(theta_2); + + theta_i *= theta; + } + } + + F -= rsum * KZGScheme::single_commitment_type::one(); + F -= this->get_V(_merged_points).evaluate(theta_2) * proof.pi_1; + + auto left_side_pairing = nil::crypto3::algebra::pair_reduced + ( F + theta_2 * proof.pi_2, verification_key_type::one() ); + + auto right_side_pairing = nil::crypto3::algebra::pair_reduced + ( proof.pi_2, _params.verification_key[1] ); + + return left_side_pairing == right_side_pairing; + } + + const params_type& get_commitment_params() const { + return _params; + } + }; + } // namespace commitments + } // namespace zk + } // namespace crypto3 +} // namespace nil + +#endif // CRYPTO3_ZK_COMMITMENTS_KZG_HPP diff --git a/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp b/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp index 0441681f5..cbd5bea8c 100644 --- a/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp +++ b/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp @@ -36,7 +36,6 @@ #include #include -#include #include #include @@ -50,8 +49,9 @@ namespace nil { typename LPCScheme::params_type::field_type::value_type>> class lpc_commitment_scheme : public polys_evaluator{ - public: + static constexpr bool is_lpc(){return true;} + using field_type = typename LPCScheme::field_type; using value_type = typename field_type::value_type; using params_type = typename LPCScheme::params_type; @@ -111,11 +111,6 @@ namespace nil { } proof_type proof_eval(transcript_type &transcript) { - for (auto const& it: _batch_fixed) { - if (it.second) { - this->append_eval_point(it.first, _etha); - } - } this->eval_polys(); @@ -158,6 +153,27 @@ namespace nil { combined_Q_normal += Q_normal; } + for(std::size_t i: this->_z.get_batches()){ + if( !_batch_fixed[i] )continue; + math::polynomial Q_normal; + auto point = _etha; + V = {-point, 1}; + for(std::size_t j = 0; j < this->_z.get_batch_size(i); j++){ + math::polynomial g_normal; + if constexpr(std::is_same, PolynomialType>::value ) { + g_normal = math::polynomial(this->_polys[i][j].coefficients()); + } else { + g_normal = this->_polys[i][j]; + } + g_normal *= theta_acc; + Q_normal += g_normal; + Q_normal -= _fixed_polys_values[i][j] * theta_acc; + theta_acc *= theta; + } + Q_normal = Q_normal / V; + combined_Q_normal += Q_normal; + } + if constexpr (std::is_same, PolynomialType>::value ) { combined_Q.from_coefficients(combined_Q_normal); } else { @@ -188,28 +204,22 @@ namespace nil { const std::map &commitments, transcript_type &transcript ) { - for (auto const&[b_ind, fixed]: _batch_fixed) { - if(!fixed) continue; - this->append_eval_point(b_ind, _etha); - for( std::size_t i = 0; i < proof.z.get_batch_size(b_ind); i++) { - if(this->_fixed_polys_values[b_ind][i] != proof.z.get(b_ind, i, proof.z.get_poly_points_number(b_ind, i) - 1)) { - return false; - } - } - } - this->_z = proof.z; for (auto const &it: commitments) { transcript(commitments.at(it.first)); } auto points = this->get_unique_points(); + // List of unique eval points set. [id=>points] - typename std::vector U(points.size()); + std::size_t total_points = points.size(); + if (std::any_of(_batch_fixed.begin(), _batch_fixed.end(), [](auto i){return i.second != false;})) total_points++; + + typename std::vector U(total_points); // V is product of (x - eval_point) polynomial for each eval_point - typename std::vector> V(points.size()); + typename std::vector> V(total_points); // List of involved polynomials for each eval point [batch_id, poly_id, point_id] - typename std::vector>> poly_map(points.size()); + typename std::vector>> poly_map(total_points); value_type theta = transcript.template challenge(); value_type theta_acc(1); @@ -228,6 +238,19 @@ namespace nil { } } + if( total_points > points.size()){ + std::size_t p = points.size(); + V[p] = {-_etha, 1}; + for(std::size_t i:this->_z.get_batches()){ + if( !_batch_fixed[i] )continue; + for(std::size_t j = 0; j < this->_z.get_batch_size(i); j++){ + U[p] += _fixed_polys_values[i][j] * theta_acc; + poly_map[p].push_back(std::make_tuple(i, j)); + theta_acc *= theta; + } + } + } + if (!nil::crypto3::zk::algorithms::verify_eval( proof.fri_proof, _fri_params, @@ -254,7 +277,6 @@ namespace nil { params.put("type", "LPC"); params.put("r", _fri_params.r); params.put("m", fri_type::m); - params.put("lambda", fri_type::lambda); params.put("max_degree", _fri_params.max_degree); boost::property_tree::ptree step_list_node; @@ -272,23 +294,17 @@ namespace nil { D_omegas_node.push_back(std::make_pair("", D_omega_node)); } params.add_child("D_omegas", D_omegas_node); - - if( fri_type::use_grinding ){ - params.add_child("grinding_params", fri_type::grinding_type::get_params()); - } return params; } }; - template> + template> struct list_polynomial_commitment_params { typedef MerkleTreeHashType merkle_hash_type; typedef TranscriptHashType transcript_hash_type; - constexpr static const std::size_t lambda = Lambda; constexpr static const std::size_t m = M; - constexpr static const bool use_grinding = UseGrinding; typedef GrindingType grinding_type; }; /** @@ -312,25 +328,21 @@ namespace nil { FieldType, typename LPCParams::merkle_hash_type, typename LPCParams::transcript_hash_type, - LPCParams::lambda, LPCParams::m, - LPCParams::use_grinding, typename LPCParams::grinding_type > { using fri_type = typename detail::basic_batched_fri< FieldType, typename LPCParams::merkle_hash_type, typename LPCParams::transcript_hash_type, - LPCParams::lambda, LPCParams::m, - LPCParams::use_grinding, typename LPCParams::grinding_type >; using merkle_hash_type = typename LPCParams::merkle_hash_type; - constexpr static const std::size_t lambda = LPCParams::lambda; constexpr static const std::size_t m = LPCParams::m; constexpr static const bool is_const_size = LPCParams::is_const_size; + constexpr static const bool is_batched_list_polynomial_commitment = true; typedef LPCParams lpc_params; @@ -338,8 +350,8 @@ namespace nil { using basic_fri = detail::basic_batched_fri; + LPCParams::m, + typename LPCParams::grinding_type>; using precommitment_type = typename basic_fri::precommitment_type; using commitment_type = typename basic_fri::commitment_type; @@ -367,16 +379,16 @@ namespace nil { template using batched_lpc = batched_list_polynomial_commitment< FieldType, commitments::list_polynomial_commitment_params< - typename LPCParams::merkle_hash_type, typename LPCParams::transcript_hash_type, - LPCParams::lambda, LPCParams::m, - LPCParams::use_grinding, typename LPCParams::grinding_type + typename LPCParams::merkle_hash_type, typename LPCParams::transcript_hash_type, + LPCParams::m, + typename LPCParams::grinding_type >>; template using lpc = batched_list_polynomial_commitment< FieldType, list_polynomial_commitment_params< - typename LPCParams::merkle_hash_type, typename LPCParams::transcript_hash_type, - LPCParams::lambda, LPCParams::m, - LPCParams::use_grinding, typename LPCParams::grinding_type + typename LPCParams::merkle_hash_type, typename LPCParams::transcript_hash_type, + LPCParams::m, + typename LPCParams::grinding_type >>; template diff --git a/include/nil/crypto3/zk/commitments/type_traits.hpp b/include/nil/crypto3/zk/commitments/type_traits.hpp index b12176430..d98f98db7 100644 --- a/include/nil/crypto3/zk/commitments/type_traits.hpp +++ b/include/nil/crypto3/zk/commitments/type_traits.hpp @@ -33,7 +33,6 @@ namespace nil { namespace crypto3 { namespace zk { - BOOST_TTI_HAS_TYPE(commitment_type) BOOST_TTI_HAS_TYPE(proof_type) @@ -109,12 +108,41 @@ namespace nil { typedef T type; }; + // An idea was copied from this example: + // https://stackoverflow.com/questions/54920801/check-if-static-function-is-available-in-class-at-compile-time + + template + struct is_kzg_struct: std::false_type{ + static const bool value = false; + }; + + template + struct is_kzg_struct::value>> + : std::integral_constant + {}; + + template + constexpr bool is_kzg = is_kzg_struct::value; + + + template + struct is_lpc_struct: std::false_type{ + static const bool value = false; + }; + + template + struct is_lpc_struct::value>> + : std::integral_constant + {}; + + template + constexpr bool is_lpc = is_lpc_struct::value; + template struct select_container { using type = typename std:: conditional, std::vector>::type; }; - } // namespace zk } // namespace crypto3 } // namespace nil diff --git a/include/nil/crypto3/zk/snark/arithmetization/plonk/constraint_system.hpp b/include/nil/crypto3/zk/snark/arithmetization/plonk/constraint_system.hpp index 2e7c62ef3..6732765cb 100644 --- a/include/nil/crypto3/zk/snark/arithmetization/plonk/constraint_system.hpp +++ b/include/nil/crypto3/zk/snark/arithmetization/plonk/constraint_system.hpp @@ -37,6 +37,7 @@ #include #include +#include #include #include @@ -67,6 +68,7 @@ namespace nil { typedef math::binary_arithmetic_operation binary_operation_type; typedef math::pow_operation pow_operation_type; typedef std::vector public_input_sizes_type; + typedef FieldType field_type; protected: gates_container_type _gates; @@ -76,7 +78,6 @@ namespace nil { // If empty, then check full column public_input_sizes_type _public_input_sizes; public: - typedef FieldType field_type; plonk_constraint_system() { } @@ -97,6 +98,17 @@ namespace nil { { } + std::unordered_set permuted_columns() const{ + std::unordered_set result; + for( std::size_t i = 0; i < _copy_constraints.size(); i++){ + auto var0 = _copy_constraints[i].first; + auto var1 = _copy_constraints[i].second; + result.insert(variable_type(var0.index, 0, true, var0.type)); + result.insert(variable_type(var1.index, 0, true, var1.type)); + } + return std::move(result); + } + std::size_t public_input_total_size() const { return std::accumulate(_public_input_sizes.begin(), _public_input_sizes.end(), 0); } @@ -130,6 +142,10 @@ namespace nil { return _copy_constraints; } + copy_constraints_container_type &mutable_copy_constraints() { + return _copy_constraints; + } + const lookup_gates_container_type &lookup_gates() const { return _lookup_gates; } diff --git a/include/nil/crypto3/zk/snark/arithmetization/plonk/copy_constraint.hpp b/include/nil/crypto3/zk/snark/arithmetization/plonk/copy_constraint.hpp index 7848608f8..a7b8220af 100644 --- a/include/nil/crypto3/zk/snark/arithmetization/plonk/copy_constraint.hpp +++ b/include/nil/crypto3/zk/snark/arithmetization/plonk/copy_constraint.hpp @@ -27,6 +27,8 @@ #ifndef CRYPTO3_ZK_PLONK_COPY_CONSTRAINT_HPP #define CRYPTO3_ZK_PLONK_COPY_CONSTRAINT_HPP +#include + #include namespace nil { @@ -35,8 +37,74 @@ namespace nil { namespace snark { template - using plonk_copy_constraint = std::pair, plonk_variable>; + struct plonk_copy_constraint { + plonk_copy_constraint() = default; + plonk_copy_constraint(const plonk_copy_constraint &other){ + initialize(other.first, other.second); + } + plonk_copy_constraint( + const plonk_variable &_first, + const plonk_variable &_second + ){ + initialize(_first, _second); + } + plonk_variable first; + plonk_variable second; + bool operator==(const plonk_copy_constraint &other){ + return ((first == other.first ) && (second == other.second)); + } + protected: + void initialize( + const plonk_variable &_first, + const plonk_variable &_second + ){ + BOOST_ASSERT(_first.relative == false); + BOOST_ASSERT(_second.relative == false); + if(_first.type == _second.type){ + if(_first.index < _second.index){ + first = plonk_variable(_first); + second = plonk_variable(_second); + } else if (_first.index > _second.index){ + first = plonk_variable(_second); + second = plonk_variable(_first); + } else if (_first.rotation < _second.rotation){ + first = plonk_variable(_first); + second = plonk_variable(_second); + } else if (_first.rotation > _second.rotation){ + first = plonk_variable(_second); + second = plonk_variable(_first); + } else { + BOOST_ASSERT_MSG(false, "Copy constraint with equal variables"); + } + return; + } + if( _first.type == plonk_variable::column_type::witness){ + first = plonk_variable(_first); + second = plonk_variable(_second); + } else if ( + _first.type == plonk_variable::column_type::public_input && + _second.type != plonk_variable::column_type::witness + ){ + first = plonk_variable(_first); + second = plonk_variable(_second); + } else if( + _first.type == plonk_variable::column_type::constant && + _second.type == plonk_variable::column_type::selector + ){ + first = plonk_variable(_first); + second = plonk_variable(_second); + } else { + first = plonk_variable(_second); + second = plonk_variable(_first); + } + return; + } + }; + template + bool operator==(const plonk_copy_constraint &a, const plonk_copy_constraint &b) { + return a.first == b.first && a.second == b.second; + } } // namespace snark } // namespace zk } // namespace crypto3 diff --git a/include/nil/crypto3/zk/snark/arithmetization/plonk/table_description.hpp b/include/nil/crypto3/zk/snark/arithmetization/plonk/table_description.hpp index fd4a73251..fa4ea3e16 100644 --- a/include/nil/crypto3/zk/snark/arithmetization/plonk/table_description.hpp +++ b/include/nil/crypto3/zk/snark/arithmetization/plonk/table_description.hpp @@ -28,6 +28,7 @@ #define CRYPTO3_ZK_PLONK_PLACEHOLDER_TABLE_DESCRIPTION_HPP #include +#include namespace nil { namespace crypto3 { @@ -74,11 +75,26 @@ namespace nil { case plonk_variable::column_type::selector: return witness_columns + public_input_columns + constant_columns + a.index; } + /* unreachable*/ + return std::numeric_limits::max(); } std::size_t table_width() const { return witness_columns + public_input_columns + constant_columns + selector_columns; } + + bool operator==(const plonk_table_description &rhs) const { + return + rows_amount == rhs.rows_amount && + usable_rows_amount == rhs.usable_rows_amount && + witness_columns == rhs.witness_columns && + public_input_columns == rhs.public_input_columns && + constant_columns == rhs.constant_columns && + selector_columns == rhs.selector_columns; + } + bool operator!=(const plonk_table_description &rhs) const { + return !(rhs == *this); + } }; } // namespace snark } // namespace zk diff --git a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/profiling.hpp b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/detail/profiling.hpp similarity index 58% rename from include/nil/crypto3/zk/snark/systems/plonk/placeholder/profiling.hpp rename to include/nil/crypto3/zk/snark/systems/plonk/placeholder/detail/profiling.hpp index 302128628..a64269ec2 100644 --- a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/profiling.hpp +++ b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/detail/profiling.hpp @@ -33,14 +33,74 @@ #include #include +#include namespace nil { namespace crypto3 { namespace zk { namespace snark { - template - struct placeholder_profiling; + // We have a piece of logic that is may be easily computed from constraint system, + // common data and commitment parameters, + // but it is not convenient to place it inside any of these classes. + // + // This piece of code is used in different projects with verifiers, and it's not good ot repeat it. + struct placeholder_info{ + std::size_t batches_num; + std::vector batches_sizes; + std::size_t poly_num; + std::size_t quotient_size; + bool use_lookups; + std::size_t permutation_size; + std::size_t round_proof_layers_num; + }; + + + template + placeholder_info prepare_placeholder_info(); + + // TODO remove permutation size + template, bool> = true> + placeholder_info prepare_placeholder_info( + const typename PlaceholderParams::constraint_system_type &constraint_system, + const typename nil::crypto3::zk::snark::placeholder_public_preprocessor::preprocessed_data_type::common_data_type &common_data, + const typename PlaceholderParams::commitment_scheme_type::params_type &fri_params, + std::size_t perm_size + ) { + auto &desc = common_data.desc; + placeholder_info res; + + res.permutation_size = perm_size; + res.use_lookups = constraint_system.num_lookup_gates() != 0; + res.batches_num = res.use_lookups ? 5 : 4; + res.batches_sizes.resize(res.batches_num); + res.batches_sizes[0] = res.permutation_size * 2 + 2 + desc.constant_columns + desc.selector_columns; + res.batches_sizes[1] = desc.witness_columns + desc.public_input_columns; + res.batches_sizes[2] = res.use_lookups ? 2 : 1; + // TODO: place it to one single place to prevent code duplication + std::size_t split_polynomial_size = std::max( + (res.permutation_size + 2) * (desc.rows_amount -1 ), + (constraint_system.lookup_poly_degree_bound() + 1) * (desc.rows_amount -1 )//, + ); + split_polynomial_size = std::max( + split_polynomial_size, + (common_data.max_gates_degree + 1) * (desc.rows_amount -1) + ); + split_polynomial_size = (split_polynomial_size % desc.rows_amount != 0)? + (split_polynomial_size / desc.rows_amount + 1): + (split_polynomial_size / desc.rows_amount); + res.quotient_size = res.batches_sizes[3] = split_polynomial_size; + if(res.use_lookups) res.batches_sizes[4] = constraint_system.sorted_lookup_columns_number(); + res.poly_num = std::accumulate(res.batches_sizes.begin(), res.batches_sizes.end(), 0); + + res.round_proof_layers_num = 0; + for(std::size_t i = 0; i < fri_params.r; i++ ){ + res.round_proof_layers_num += log2(fri_params.D[i]->m) -1; + } + + return res; + } + template void print_placeholder_params( @@ -56,8 +116,8 @@ namespace nil { boost::property_tree::ptree root; root.put("test_name", circuit_name); root.put("modulus", PlaceholderParams::field_type::modulus); - root.put("rows_amount", preprocessed_data.common_data.rows_amount); - root.put("usable_rows_amount", preprocessed_data.common_data.usable_rows_amount); + root.put("rows_amount", preprocessed_data.common_data.desc.rows_amount); + root.put("usable_rows_amount", preprocessed_data.common_data.desc.usable_rows_amount); root.put("omega", preprocessed_data.common_data.basic_domain->get_domain_element(1)); root.put("verification_key", preprocessed_data.common_data.vk.to_string()); diff --git a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/lookup_argument.hpp b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/lookup_argument.hpp index 8d3e6f645..dc1acca60 100644 --- a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/lookup_argument.hpp +++ b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/lookup_argument.hpp @@ -52,6 +52,60 @@ namespace nil { namespace crypto3 { namespace zk { namespace snark { + template + std::vector lookup_parts( + const plonk_constraint_system &constraint_system, + std::size_t max_quotient_chunks + ){ + if( max_quotient_chunks == 0 ){ + return {constraint_system.sorted_lookup_columns_number()}; + } + + using VariableType = plonk_variable; + typedef math::expression_max_degree_visitor degree_visitor_type; + std::vector lookup_parts; + degree_visitor_type lookup_visitor; + + std::size_t lookup_chunk = 0; + std::size_t lookup_part = 0; + std::size_t max_constraint_degree; + for (const auto& gate :constraint_system.lookup_gates()) { + for (const auto& constr : gate.constraints) { + max_constraint_degree = 0; + for (const auto& li : constr.lookup_input) { + std::size_t deg = lookup_visitor.compute_max_degree(li); + max_constraint_degree = std::max( + max_constraint_degree, + deg + ); + } + if( lookup_chunk + max_constraint_degree + 1>= max_quotient_chunks ){ + lookup_parts.push_back(lookup_part); + lookup_chunk = 0; + lookup_part = 0; + } + // +1 because lookup input is multiplied by selector + lookup_chunk += max_constraint_degree + 1; + lookup_part++; + } + } + for (const auto& table : constraint_system.lookup_tables()) { + for( const auto &lookup_options: table.lookup_options ){ + // +3 because now any lookup option is lookup_column * lookup_selector * (1-q_last-q_blind) -- three polynomials degree rows_amount-1 + if( lookup_chunk + 3 >= max_quotient_chunks ){ + lookup_parts.push_back(lookup_part); + lookup_chunk = 0; + lookup_part = 0; + } + lookup_chunk += 3; + lookup_part++; + } + } + + lookup_parts.push_back(lookup_part); + return lookup_parts; + } + template class placeholder_lookup_argument_prover { using transcript_hash_type = typename ParamsType::transcript_hash_type; @@ -90,6 +144,7 @@ namespace nil { , basic_domain(preprocessed_data.common_data.basic_domain) , lookup_gates(constraint_system.lookup_gates()) , lookup_tables(constraint_system.lookup_tables()) + , lookup_chunks(0) { // $/theta = \challenge$ theta = transcript.template challenge(); @@ -131,7 +186,7 @@ namespace nil { } // Sort auto sorted = sort_polynomials(reduced_input, reduced_value, basic_domain->m, - preprocessed_data.common_data.usable_rows_amount); + preprocessed_data.common_data.desc.usable_rows_amount); // 4. Commit sorted polys for( std::size_t i = 0; i < sorted.size(); i++){ @@ -144,6 +199,12 @@ namespace nil { typename FieldType::value_type beta = transcript.template challenge(); typename FieldType::value_type gamma = transcript.template challenge(); + auto part_sizes = lookup_parts(constraint_system, preprocessed_data.common_data.max_quotient_chunks); + std::vector lookup_alphas; + for(std::size_t i = 0; i < part_sizes.size() - 1; i++){ + lookup_alphas.push_back(transcript.template challenge()); + } + math::polynomial_dfs V_L = compute_V_L( sorted, reduced_input, reduced_value, beta, gamma); @@ -153,13 +214,20 @@ namespace nil { commitment_scheme.append_to_batch(PERMUTATION_BATCH, V_L); - BOOST_CHECK(V_L[preprocessed_data.common_data.usable_rows_amount] == FieldType::value_type::one()); + BOOST_CHECK(V_L[preprocessed_data.common_data.desc.usable_rows_amount] == FieldType::value_type::one()); + + + BOOST_ASSERT(std::accumulate(part_sizes.begin(), part_sizes.end(), 0) == sorted.size()); - // After this call of compute_g lookup_input_ptr and lookup_value_ptr are deleted. - math::polynomial_dfs g = compute_g( - std::move(lookup_input_ptr), std::move(lookup_value_ptr), beta, gamma); + // Compute gs and hs products for each part + std::vector> gs = compute_gs( + std::move(lookup_input_ptr), std::move(lookup_value_ptr), beta, gamma, part_sizes + ); + + std::vector> hs = compute_hs( + sorted, beta, gamma, part_sizes + ); - math::polynomial_dfs h = compute_h(sorted, beta, gamma); math::polynomial_dfs V_L_shifted = math::polynomial_shift(V_L, 1, basic_domain->m); @@ -171,18 +239,48 @@ namespace nil { // Polynomial g is waaay too large, saving memory here, by making code very unreadable. //F_dfs[2] = (one_polynomial - (preprocessed_data.q_last + preprocessed_data.q_blind)) * // (V_L_shifted * h - V_L * g); - g *= V_L; - h *= V_L_shifted; - g -= h; - h = math::polynomial_dfs(); // just clean the memory of h. - g *= (preprocessed_data.q_last + preprocessed_data.q_blind) - one_polynomial; - F_dfs[2] = std::move(g); + F_dfs[2] = zero_polynomial; + if( part_sizes.size() == 1 ){ + auto &g = gs[0]; + auto &h = hs[0]; + g *= V_L; + h *= V_L_shifted; + g -= h; + h = math::polynomial_dfs(); // just clean the memory of h. + g *= (preprocessed_data.q_last + preprocessed_data.q_blind) - one_polynomial; + F_dfs[2] = std::move(g); + } else { + math::polynomial_dfs current_poly = V_L; + math::polynomial_dfs previous_poly = V_L; + std::vector> parts; + BOOST_ASSERT(part_sizes.size() == gs.size()); + BOOST_ASSERT(part_sizes.size() == hs.size()); + BOOST_ASSERT(part_sizes.size() == lookup_alphas.size() + 1); + for( std::size_t i = 0; i < lookup_alphas.size(); i ++ ){ + auto &g = gs[i]; + auto &h = hs[i]; + auto reduced_g = reduce_dfs_polynomial_domain(g, basic_domain->m); + auto reduced_h = reduce_dfs_polynomial_domain(h, basic_domain->m); + for( std::size_t j = 0; j < preprocessed_data.common_data.desc.usable_rows_amount; j++){ + current_poly[j] = (previous_poly[j] * reduced_g[j]) / reduced_h[j]; + } + commitment_scheme.append_to_batch(PERMUTATION_BATCH, current_poly); + auto par = lookup_alphas[i] * (previous_poly * g - current_poly * h); + F_dfs[2] += par; + previous_poly = current_poly; + } + std::size_t last = lookup_alphas.size(); + auto &g = gs[last]; + auto &h = hs[last]; + F_dfs[2] += (previous_poly * g - V_L_shifted * h); + F_dfs[2] *= (preprocessed_data.q_last + preprocessed_data.q_blind) - one_polynomial; + } F_dfs[3] = zero_polynomial; for (std::size_t i = 1; i < sorted.size(); i++) { typename FieldType::value_type alpha = transcript.template challenge(); - math::polynomial_dfs sorted_shifted = math::polynomial_shift(sorted[i-1], preprocessed_data.common_data.usable_rows_amount , basic_domain->m); + math::polynomial_dfs sorted_shifted = math::polynomial_shift(sorted[i-1], preprocessed_data.common_data.desc.usable_rows_amount , basic_domain->m); F_dfs[3] += alpha * preprocessed_data.common_data.lagrange_0 * (sorted[i] - sorted_shifted); } @@ -199,22 +297,31 @@ namespace nil { }; } - math::polynomial_dfs compute_g( + std::vector> compute_gs( std::unique_ptr>> lookup_input_ptr, std::unique_ptr>> lookup_value_ptr, const typename FieldType::value_type& beta, - const typename FieldType::value_type& gamma) { - + const typename FieldType::value_type& gamma, + std::vector lookup_part_sizes + ) { + std::vector> result; auto& lookup_value = *lookup_value_ptr; auto& lookup_input = *lookup_input_ptr; auto g = math::polynomial_dfs::one(); auto one = FieldType::value_type::one(); - g *= (one + beta).pow(lookup_input.size()); + std::size_t current_part = 0; std::vector> g_multipliers; for (std::size_t i = 0; i < lookup_input.size(); i++) { - g_multipliers.push_back(gamma + lookup_input[i]); + g_multipliers.push_back((one + beta) * (gamma + lookup_input[i])); + if( g_multipliers.size() == lookup_part_sizes[current_part] ){ + g *= math::polynomial_product(std::move(g_multipliers)); + result.push_back(g); + g_multipliers.clear(); + g = math::polynomial_dfs::one(); + current_part++; + } } // We don't use lookup_input after this line. @@ -224,28 +331,49 @@ namespace nil { for (std::size_t i = 0; i < lookup_value.size(); i++) { auto lookup_shifted = math::polynomial_shift(lookup_value[i], 1, basic_domain->m); g_multipliers.push_back( part1 + lookup_value[i] + beta * lookup_shifted); + if( g_multipliers.size() == lookup_part_sizes[current_part] ){ + g *= math::polynomial_product(std::move(g_multipliers)); + result.push_back(g); + g_multipliers.clear(); + g.clear(); + g = math::polynomial_dfs::one(); + current_part++; + } } + BOOST_ASSERT(g_multipliers.size() == 0); // We don't use lookup_value after this line. lookup_value_ptr.reset(nullptr); - - g *= math::polynomial_product(std::move(g_multipliers)); - return g; + return std::move(result); } - math::polynomial_dfs compute_h( + std::vector> compute_hs( const std::vector>& sorted, const typename FieldType::value_type& beta, - const typename FieldType::value_type& gamma + const typename FieldType::value_type& gamma, + const std::vector &lookup_part_sizes ) { auto one = FieldType::value_type::one(); + std::vector> result; std::vector> h_multipliers; + math::polynomial_dfs h = math::polynomial_dfs::one(); + + std::size_t current_part = 0; for (std::size_t i = 0; i < sorted.size(); i++) { auto sorted_shifted = math::polynomial_shift(sorted[i], 1, basic_domain->m); h_multipliers.push_back((one + beta) * gamma + sorted[i] + beta * sorted_shifted); + if( h_multipliers.size() == lookup_part_sizes[current_part] ){ + h = math::polynomial_product(h_multipliers); + result.push_back(h); + h_multipliers.clear(); + h.clear(); + h = math::polynomial_dfs::one(); + current_part++; + } } - return math::polynomial_product(h_multipliers); + BOOST_ASSERT(h_multipliers.size() == 0); + return std::move(result); } math::polynomial_dfs compute_V_L( @@ -260,7 +388,7 @@ namespace nil { V_L[0] = FieldType::value_type::one(); auto one = FieldType::value_type::one(); - for (std::size_t k = 1; k <= preprocessed_data.common_data.usable_rows_amount; k++) { + for (std::size_t k = 1; k <= preprocessed_data.common_data.desc.usable_rows_amount; k++) { V_L[k] = V_L[k-1]; typename FieldType::value_type g_tmp = (one + beta).pow(reduced_input.size()); @@ -514,7 +642,7 @@ namespace nil { const std::vector>>& lookup_gates; const std::vector>& lookup_tables; typename FieldType::value_type theta; - + std::size_t lookup_chunks; }; template @@ -533,9 +661,10 @@ namespace nil { public: std::array verify_eval( - const typename placeholder_public_preprocessor::preprocessed_data_type &preprocessed_data, - const std::vector>> &lookup_gates, - const std::vector> &lookup_tables, + const typename placeholder_public_preprocessor::preprocessed_data_type::common_data_type &common_data, + const std::vector &special_selector_values, + const std::vector &special_selector_values_shifted, + const plonk_constraint_system &constraint_system, // y const typename FieldType::value_type &challenge, typename policy_type::evaluation_map &evaluations, @@ -543,15 +672,17 @@ namespace nil { const std::vector> &sorted, // V_L(y), V_L(omega* Y) std::vector V_L_values, + // parts values + std::vector parts_values, // Commitment const typename CommitmentSchemeTypePermutation::commitment_type &lookup_commitment, transcript_type &transcript = transcript_type() ) { + const std::vector>> &lookup_gates = constraint_system.lookup_gates(); + const std::vector> &lookup_tables = constraint_system.lookup_tables(); std::array F; // 1. Get theta typename FieldType::value_type theta = transcript.template challenge(); - typename FieldType::value_type omega = preprocessed_data.common_data.basic_domain->get_domain_element(1); - // 2. Add commitments to transcript transcript(lookup_commitment); @@ -559,8 +690,8 @@ namespace nil { // 3. Calculate lookup_value compression typename FieldType::value_type one = FieldType::value_type::one(); - auto mask_value = (one - (preprocessed_data.q_last.evaluate(challenge) + preprocessed_data.q_blind.evaluate(challenge))); - auto shifted_mask_value = (one - (preprocessed_data.q_last.evaluate(challenge*omega) + preprocessed_data.q_blind.evaluate(challenge*omega))); + auto mask_value = (one - (special_selector_values[1] + special_selector_values[2])); + auto shifted_mask_value = (one - (special_selector_values_shifted[0] + special_selector_values_shifted[1])); typename FieldType::value_type theta_acc = FieldType::value_type::one(); @@ -613,30 +744,89 @@ namespace nil { typename FieldType::value_type beta = transcript.template challenge(); typename FieldType::value_type gamma = transcript.template challenge(); + std::vector lookup_alphas; + auto parts = lookup_parts(constraint_system, common_data.max_quotient_chunks); + for(std::size_t i = 0; i < parts.size() - 1; i++){ + lookup_alphas.push_back(transcript.template challenge()); + } + BOOST_ASSERT(lookup_alphas.size() == parts_values.size()); + + std::vector gs; + std::vector hs; + + std::size_t current_part = 0; + std::size_t current_size = 0; typename FieldType::value_type g(1); for( std::size_t i = 0; i < lookup_input.size(); i++){ g *= (one+beta)*(gamma + lookup_input[i]); + current_size++; + if( current_size == parts[current_part] ){ + gs.push_back(g); + g = FieldType::value_type::one(); + current_size = 0; + current_part++; + } } for( std::size_t i = 0; i < lookup_value.size(); i++ ){ g *= (one+beta) * gamma + lookup_value[i] + beta * shifted_lookup_value[i]; + current_size++; + if( current_size == parts[current_part] ){ + gs.push_back(g); + g = FieldType::value_type::one(); + current_size = 0; + current_part++; + } } + BOOST_ASSERT(current_size == 0); typename FieldType::value_type h(1); + current_part = 0; + current_size = 0; for( std::size_t i = 0; i < sorted.size(); i++){ h *= (one+beta) * gamma + sorted[i][0] + beta * sorted[i][1]; + current_size++; + if( current_size == parts[current_part] ){ + hs.push_back(h); + h = FieldType::value_type::one(); + current_size = 0; + current_part++; + } } + BOOST_ASSERT(current_size == 0); + BOOST_ASSERT(gs.size() == parts_values.size() + 1); + BOOST_ASSERT(hs.size() == parts_values.size() + 1); auto V_L_value = V_L_values[0]; auto V_L_shifted = V_L_values[1]; - F[0] = (one - V_L_value) * preprocessed_data.common_data.lagrange_0.evaluate(challenge); - F[1] = preprocessed_data.q_last.evaluate(challenge) * (V_L_value * V_L_value - V_L_value); - F[2] = (one - (preprocessed_data.q_last.evaluate(challenge) + preprocessed_data.q_blind.evaluate(challenge))) * + F[0] = (one - V_L_value) * special_selector_values[0]; + F[1] = special_selector_values[1] * (V_L_value * V_L_value - V_L_value); + if(parts.size() == 1){ + g = gs[0]; + h = hs[0]; + F[2] = (one - (special_selector_values[1] + special_selector_values[2])) * (V_L_shifted * h - V_L_value * g); + } else { + typename FieldType::value_type current_value; + typename FieldType::value_type previous_value = V_L_value; + for( std::size_t i = 0; i < lookup_alphas.size(); i ++ ){ + auto g = gs[i]; + auto h = hs[i]; + current_value = parts_values[i]; + auto part = lookup_alphas[i] * (previous_value * g - current_value * h); + F[2] += part; + previous_value = current_value; + } + std::size_t last = lookup_alphas.size(); + auto g = gs[last]; + auto h = hs[last]; + F[2] += (previous_value * g - V_L_shifted * h); + F[2] *= (special_selector_values[1] + special_selector_values[2]) - one; + } F[3] = 0; for( std::size_t i = 1; i < sorted.size(); i++ ){ typename FieldType::value_type alpha = transcript.template challenge(); - F[3] += (sorted[i][0] - sorted[i-1][2]) * alpha * preprocessed_data.common_data.lagrange_0.evaluate(challenge); + F[3] += (sorted[i][0] - sorted[i-1][2]) * alpha * special_selector_values[0]; } return F; } diff --git a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/permutation_argument.hpp b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/permutation_argument.hpp index 34e0cb3ac..110f38d08 100644 --- a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/permutation_argument.hpp +++ b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/permutation_argument.hpp @@ -77,8 +77,8 @@ namespace nil { const plonk_polynomial_dfs_table &column_polynomials, typename ParamsType::commitment_scheme_type& commitment_scheme, - transcript_type& transcript) { - + transcript_type& transcript + ) { PROFILE_PLACEHOLDER_SCOPE("permutation_argument_prove_eval_time"); const std::vector> &S_sigma = @@ -87,6 +87,13 @@ namespace nil { preprocessed_data.identity_polynomials; std::shared_ptr> basic_domain = preprocessed_data.common_data.basic_domain; + + auto permuted_columns = constraint_system.permuted_columns(); + std::vector global_indices; + for( auto it = permuted_columns.begin(); it != permuted_columns.end(); it++ ){ + global_indices.push_back(table_description.global_index(*it)); + } + // 1. $\beta_1, \gamma_1 = \challenge$ typename FieldType::value_type beta = transcript.template challenge(); typename FieldType::value_type gamma = transcript.template challenge(); @@ -98,20 +105,22 @@ namespace nil { std::vector> g_v = S_id; std::vector> h_v = S_sigma; + BOOST_ASSERT(global_indices.size() == S_id.size()); + BOOST_ASSERT(global_indices.size() == S_sigma.size()); for (std::size_t i = 0; i < S_id.size(); i++) { - BOOST_ASSERT(column_polynomials[i].size() == basic_domain->size()); + BOOST_ASSERT(column_polynomials[global_indices[i]].size() == basic_domain->size()); BOOST_ASSERT(S_id[i].size() == basic_domain->size()); BOOST_ASSERT(S_sigma[i].size() == basic_domain->size()); /* g_v.push_back(column_polynomials[i] + beta * S_id[i] + gamma); */ g_v[i] *= beta; g_v[i] += gamma; - g_v[i] += column_polynomials[i]; + g_v[i] += column_polynomials[global_indices[i]]; /* h_v.push_back(column_polynomials[i] + beta * S_sigma[i] + gamma); */ h_v[i] *= beta; h_v[i] += gamma; - h_v[i] += column_polynomials[i]; + h_v[i] += column_polynomials[global_indices[i]]; } V_P[0] = FieldType::value_type::one(); @@ -131,10 +140,28 @@ namespace nil { commitment_scheme.append_to_batch(PERMUTATION_BATCH, V_P); // 5. Calculate g_perm, h_perm - math::polynomial_dfs g = - math::polynomial_product(std::move(g_v)); - math::polynomial_dfs h = - math::polynomial_product(std::move(h_v)); + std::vector> gs; + std::vector> hs; + std::vector> g_factors; + std::vector> h_factors; + for(std::size_t i = 0; i < g_v.size(); i++){ + g_factors.push_back(g_v[i]); + h_factors.push_back(h_v[i]); + if( preprocessed_data.common_data.max_quotient_chunks != 0 && g_factors.size() == (preprocessed_data.common_data.max_quotient_chunks - 1)) { + gs.push_back(math::polynomial_product(g_factors)); + hs.push_back(math::polynomial_product(h_factors)); + g_factors.clear(); + h_factors.clear(); + } + } + if( g_factors.size() != 0 ){ + gs.push_back(math::polynomial_product(g_factors)); + hs.push_back(math::polynomial_product(h_factors)); + g_factors.clear(); + h_factors.clear(); + } + BOOST_ASSERT(gs.size() == preprocessed_data.common_data.permutation_parts); + BOOST_ASSERT(gs.size() == hs.size()); math::polynomial_dfs one_polynomial( 0, V_P.size(), FieldType::value_type::one()); @@ -147,17 +174,46 @@ namespace nil { F_dfs[0] = one_polynomial; F_dfs[0] -= V_P; F_dfs[0] *= preprocessed_data.common_data.lagrange_0; + std::vector permutation_alphas; + for( std::size_t i = 0; i < preprocessed_data.common_data.permutation_parts - 1; i++ ){ + permutation_alphas.push_back(transcript.template challenge()); + } /* F_dfs[1] = (one_polynomial - (preprocessed_data.q_last + preprocessed_data.q_blind)) * (V_P_shifted * h - V_P * g); */ - math::polynomial_dfs t1 = V_P; - t1 *= g; - V_P_shifted *= h; - V_P_shifted -= t1; - - F_dfs[1] = one_polynomial; - F_dfs[1] -= preprocessed_data.q_last; - F_dfs[1] -= preprocessed_data.q_blind; - F_dfs[1] *= V_P_shifted; + if ( preprocessed_data.common_data.permutation_parts == 1 ){ + auto &g = gs[0]; + auto &h = hs[0]; + math::polynomial_dfs t1 = V_P; + t1 *= g; + V_P_shifted *= h; + V_P_shifted -= t1; + + F_dfs[1] = one_polynomial; + F_dfs[1] -= preprocessed_data.q_last; + F_dfs[1] -= preprocessed_data.q_blind; + F_dfs[1] *= V_P_shifted; + } else { + math::polynomial_dfs previous_poly = V_P; + math::polynomial_dfs current_poly = V_P; + for( std::size_t i = 0; i < preprocessed_data.common_data.permutation_parts-1; i++ ){ + auto g = gs[i]; + auto h = hs[i]; + auto reduced_g = reduce_dfs_polynomial_domain(g, basic_domain->m); + auto reduced_h = reduce_dfs_polynomial_domain(h, basic_domain->m); + for(std::size_t j = 0; j < preprocessed_data.common_data.desc.usable_rows_amount; j++){ + current_poly[j] = (previous_poly[j] * reduced_g[j]) / reduced_h[j]; + } + commitment_scheme.append_to_batch(PERMUTATION_BATCH, current_poly); + auto part = permutation_alphas[i] * (previous_poly * g - current_poly * h); + F_dfs[1] += part; + previous_poly = current_poly; + } + std::size_t last = permutation_alphas.size(); + auto &g = gs[last]; + auto &h = hs[last]; + F_dfs[1] += (previous_poly * g - V_P_shifted * h); + F_dfs[1] *= (preprocessed_data.q_last + preprocessed_data.q_blind) - one_polynomial; + } /* F_dfs[2] = preprocessed_data.q_last * V_P * (V_P - one_polynomial); */ F_dfs[2] = V_P; @@ -171,8 +227,11 @@ namespace nil { } static inline std::array verify_eval( - const typename placeholder_public_preprocessor::preprocessed_data_type - &preprocessed_data, + const typename placeholder_public_preprocessor::preprocessed_data_type::common_data_type + &common_data, + const std::vector &S_id, + const std::vector &S_sigma, + const std::vector &special_selector_values, // y const typename FieldType::value_type &challenge, // f(y): @@ -181,59 +240,120 @@ namespace nil { const typename FieldType::value_type &perm_polynomial_value, // V_P(omega * y): const typename FieldType::value_type &perm_polynomial_shifted_value, - transcript_type &transcript) { - - const std::vector> &S_sigma = - preprocessed_data.permutation_polynomials; - const std::vector> &S_id = - preprocessed_data.identity_polynomials; - + const std::vector &perm_partitions, + transcript_type &transcript + ) { // 1. Get beta, gamma typename FieldType::value_type beta = transcript.template challenge(); typename FieldType::value_type gamma = transcript.template challenge(); // 2. Add commitment to V_P to transcript // 3. Calculate h_perm, g_perm at challenge point - math::polynomial_dfs one_polynomial( - 0, preprocessed_data.common_data.basic_domain->size(), FieldType::value_type::one()); - math::polynomial_dfs g_poly = one_polynomial; - math::polynomial_dfs h_poly = one_polynomial; + typename FieldType::value_type one = FieldType::value_type::one(); + typename FieldType::value_type g = one; + typename FieldType::value_type h = one; + + BOOST_ASSERT(column_polynomials_values.size() == S_id.size()); + BOOST_ASSERT(column_polynomials_values.size() == S_sigma.size()); + std::vector gs; + std::vector hs; + std::size_t current_size = 0; for (std::size_t i = 0; i < column_polynomials_values.size(); i++) { typename FieldType::value_type pp = column_polynomials_values[i] + gamma; - math::polynomial_dfs t_id = S_id[i]; - math::polynomial_dfs t_sigma = S_sigma[i]; + typename FieldType::value_type t_id = S_id[i]; + typename FieldType::value_type t_sigma = S_sigma[i]; // g_poly = g_poly * (S_id[i] * beta + pp); t_id *= beta; t_id += pp; - g_poly *= t_id; + g *= t_id; // h_poly = h_poly * (S_sigma[i] * beta + pp); t_sigma *= beta; t_sigma += pp; - h_poly *= t_sigma; + h *= t_sigma; + + current_size++; + if( common_data.max_quotient_chunks != 0 && current_size == (common_data.max_quotient_chunks - 1)){ + gs.push_back(std::move(g)); + hs.push_back(std::move(h)); + g = one; + h = one; + current_size = 0; + } + } + if( current_size != 0 ){ + gs.push_back(g); + hs.push_back(h); } std::array F; - typename FieldType::value_type one = FieldType::value_type::one(); - F[0] = preprocessed_data.common_data.lagrange_0.evaluate(challenge) * + F[0] = common_data.lagrange_0.evaluate(challenge) * (one - perm_polynomial_value); + std::vector permutation_alphas; + for( std::size_t i = 0; i < common_data.permutation_parts - 1; i++ ){ + permutation_alphas.push_back(transcript.template challenge()); + } + BOOST_ASSERT(permutation_alphas.size() == perm_partitions.size()); + + // F[1] = ((one - preprocessed_data.q_last - preprocessed_data.q_blind) * // (perm_polynomial_shifted_value * h_poly - perm_polynomial_value * g_poly)).evaluate(challenge); - h_poly *= perm_polynomial_shifted_value; - g_poly *= perm_polynomial_value; - h_poly -= g_poly; - h_poly *= one - preprocessed_data.q_last - preprocessed_data.q_blind; - F[1] = h_poly.evaluate(challenge); + if( common_data.permutation_parts == 1 ){ + auto &h = hs[0]; + auto &g = gs[0]; + h *= perm_polynomial_shifted_value; + g *= perm_polynomial_value; + h -= g; + h *= one - special_selector_values[1] - special_selector_values[2]; + F[1] = h; + } else { + typename FieldType::value_type current_value; + typename FieldType::value_type previous_value = perm_polynomial_value; + for(std::size_t i = 0; i < permutation_alphas.size(); i++){ + auto &h = hs[i]; + auto &g = gs[i]; + current_value = perm_partitions[i]; + auto part = permutation_alphas[i] * (previous_value * g - current_value * h); + F[1] += part; + previous_value = current_value; + } + std::size_t last = permutation_alphas.size(); + auto g = gs[last]; + auto h = hs[last]; + F[1] += (previous_value * g - perm_polynomial_shifted_value * h); + F[1] *= (special_selector_values[1] + special_selector_values[2]) - one; + } - F[2] = preprocessed_data.q_last.evaluate(challenge) * + F[2] = special_selector_values[1] * (perm_polynomial_value.squared() - perm_polynomial_value); return F; } + + static math::polynomial_dfs reduce_dfs_polynomial_domain( + const math::polynomial_dfs &polynomial, + const std::size_t &new_domain_size + ) { + math::polynomial_dfs reduced( + new_domain_size - 1, new_domain_size, FieldType::value_type::zero()); + + BOOST_ASSERT(new_domain_size <= polynomial.size()); + if (polynomial.size() == new_domain_size) { + reduced = polynomial; + } else { + BOOST_ASSERT(polynomial.size() % new_domain_size == 0); + + std::size_t step = polynomial.size() / new_domain_size; + for (std::size_t i = 0; i < new_domain_size; i++) { + reduced[i] = polynomial[i * step]; + } + } + return reduced; + }; }; } // namespace snark } // namespace zk diff --git a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp index b3070a268..d2118043e 100644 --- a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp +++ b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/preprocessor.hpp @@ -56,6 +56,11 @@ namespace nil { namespace crypto3 { namespace zk { namespace snark { + template + std::vector lookup_parts( + const plonk_constraint_system &constraint_system, + std::size_t max_quotient_chunks + ); template class placeholder_public_preprocessor { @@ -70,6 +75,17 @@ namespace nil { using transcript_hash_type = typename commitment_scheme_type::transcript_hash_type; public: + static std::size_t permutation_partitions_num( + std::size_t permutation_size, + std::size_t max_quotient_chunks + ){ + if( permutation_size == 0 ) return 0; + if( max_quotient_chunks == 0 ){ + return 1; + } + return (permutation_size % (max_quotient_chunks - 1) == 0)? permutation_size / (max_quotient_chunks - 1) : permutation_size / (max_quotient_chunks - 1) + 1; + } + struct preprocessed_data_type { struct public_commitments_type { commitment_type fixed_values; @@ -95,10 +111,13 @@ namespace nil { return !(rhs == *this); } + std::string to_string() const{ std::stringstream ss; - ss << constraint_system_with_params_hash << " " << fixed_values_commitment; + // TODO: KZG fixed_values_commitments are vector + // need operator<<(ostream,vector)? + ss << constraint_system_with_params_hash /*<< " " << fixed_values_commitment*/; return ss.str(); } }; @@ -113,17 +132,14 @@ namespace nil { using verification_key_type = verification_key; using transcript_hash_type = typename ParamsType::transcript_hash_type; using table_description_type = plonk_table_description; + using commitment_scheme_data_type = typename commitment_scheme_type::preprocessed_data_type; + using commitment_params_type = typename commitment_scheme_type::params_type; // marshalled public_commitments_type commitments; columns_rotations_type columns_rotations; - std::size_t rows_amount; - std::size_t usable_rows_amount; - std::size_t witness_columns; - std::size_t public_input_columns; - std::size_t constant_columns; - std::size_t selector_columns; + table_description_type desc; // not marshalled. They can be derived from other fields. polynomial_dfs_type lagrange_0; @@ -131,29 +147,41 @@ namespace nil { std::shared_ptr> basic_domain; std::uint32_t max_gates_degree; verification_key vk; - typename commitment_scheme_type::preprocessed_data_type commitment_scheme_data; + commitment_scheme_data_type commitment_scheme_data; + commitment_params_type commitment_params; + std::vector permuted_columns; + std::uint32_t max_quotient_chunks; + std::uint32_t permutation_parts; + std::uint32_t lookup_parts; // Constructor with pregenerated domain common_data_type( std::shared_ptr> D, public_commitments_type commts, std::vector> col_rotations, - std::size_t rows, - std::size_t usable_rows, - std::size_t witness_columns, - std::size_t public_input_columns, - std::size_t constant_columns, - std::size_t selector_columns, + const table_description_type &table_description, std::uint32_t max_gates_degree, - verification_key vk + std::uint32_t permutation_parts, + std::uint32_t lookup_parts, + verification_key vk, + const std::vector &_permuted_columns, + const commitment_params_type &_commitment_params, + const commitment_scheme_data_type &_commitment_scheme_data, + std::size_t max_quotient_chunks = 0 ): commitments(commts), - columns_rotations(col_rotations), rows_amount(rows), usable_rows_amount(usable_rows), + columns_rotations(col_rotations), + desc(table_description), lagrange_0(D->size() - 1, D->size(), FieldType::value_type::zero()), - Z(std::vector(rows + 1, FieldType::value_type::zero())), + Z(std::vector(table_description.rows_amount + 1, FieldType::value_type::zero())), basic_domain(D), - max_gates_degree(max_gates_degree), vk(vk), - witness_columns(witness_columns), public_input_columns(public_input_columns), - constant_columns(constant_columns), selector_columns(selector_columns) + max_gates_degree(max_gates_degree), + vk(vk), + commitment_scheme_data(_commitment_scheme_data), + commitment_params(_commitment_params), + permuted_columns(_permuted_columns), + max_quotient_chunks(max_quotient_chunks), + permutation_parts(permutation_parts), + lookup_parts(lookup_parts) { // Z is polynomial -1, 0,..., 0, 1 Z[0] = -FieldType::value_type::one(); @@ -167,21 +195,28 @@ namespace nil { common_data_type( public_commitments_type commts, std::vector> col_rotations, - std::size_t rows, - std::size_t usable_rows, - std::size_t witness_columns, - std::size_t public_input_columns, - std::size_t constant_columns, - std::size_t selector_columns, + const table_description_type &table_description, std::uint32_t max_gates_degree, - verification_key vk + std::uint32_t permutation_parts, + std::uint32_t lookup_parts, + verification_key vk, + const std::vector &_permuted_columns, + const commitment_params_type &_commitment_params, + const commitment_scheme_data_type &_commitment_scheme_data, + std::size_t max_quotient_chunks ): commitments(commts), - columns_rotations(col_rotations), rows_amount(rows), usable_rows_amount(usable_rows), - lagrange_0(rows - 1, rows, FieldType::value_type::zero()), - Z(std::vector(rows + 1, FieldType::value_type::zero())), - max_gates_degree(max_gates_degree), vk(vk), - witness_columns(witness_columns), public_input_columns(public_input_columns), - constant_columns(constant_columns), selector_columns(selector_columns) + columns_rotations(col_rotations), + desc(table_description), + lagrange_0(table_description.rows_amount - 1, table_description.rows_amount, FieldType::value_type::zero()), + Z(std::vector(table_description.rows_amount + 1, FieldType::value_type::zero())), + max_gates_degree(max_gates_degree), + vk(vk), + commitment_scheme_data(_commitment_scheme_data), + commitment_params(_commitment_params), + permuted_columns(_permuted_columns), + max_quotient_chunks(max_quotient_chunks), + permutation_parts(permutation_parts), + lookup_parts(lookup_parts) { // Z is polynomial -1, 0,..., 0, 1 Z[0] = -FieldType::value_type::one(); @@ -190,25 +225,27 @@ namespace nil { // lagrange_0: 1, 0,...,0 lagrange_0[0] = FieldType::value_type::one(); - basic_domain = math::make_evaluation_domain(rows); + basic_domain = math::make_evaluation_domain(table_description.rows_amount); } // These operators are useful for marshalling // They will be implemented with marshalling procedures implementation bool operator==(const common_data_type &rhs) const { - return rows_amount == rhs.rows_amount && - usable_rows_amount == rhs.usable_rows_amount && + return desc == rhs.desc && columns_rotations == rhs.columns_rotations && - witness_columns == rhs.witness_columns && - public_input_columns == rhs.public_input_columns && - constant_columns == rhs.constant_columns && - selector_columns == rhs.selector_columns && commitments == rhs.commitments && basic_domain->size() == rhs.basic_domain->size() && lagrange_0 == rhs.lagrange_0 && Z == rhs.Z && - max_gates_degree == rhs.max_gates_degree && - vk == rhs.vk; + max_gates_degree == rhs.max_gates_degree + && vk == rhs.vk + && permuted_columns == rhs.permuted_columns + && commitment_params == rhs.commitment_params + && commitment_scheme_data == rhs.commitment_scheme_data + && max_quotient_chunks == rhs.max_quotient_chunks + && permutation_parts == rhs.permutation_parts + && lookup_parts == rhs.lookup_parts + ; } bool operator!=(const common_data_type &rhs) const { return !(rhs == *this); @@ -379,7 +416,7 @@ namespace nil { } static inline std::vector identity_polynomials( - std::size_t permutation_size, + const std::size_t permutation_size, const typename FieldType::value_type &omega, const typename FieldType::value_type &delta, std::shared_ptr> domain @@ -400,20 +437,21 @@ namespace nil { } static inline std::vector permutation_polynomials( - std::size_t permutation_size, + const std::vector &global_indices, // ordered global indices const typename FieldType::value_type &omega, const typename FieldType::value_type &delta, cycle_representation &permutation, std::shared_ptr> domain ) { - std::vector S_perm(permutation_size); - for (std::size_t i = 0; i < permutation_size; i++) { + std::vector S_perm(global_indices.size()); + for (std::size_t i = 0; i < global_indices.size(); i++) { S_perm[i] = polynomial_dfs_type( domain->size() - 1, domain->size(), FieldType::value_type::zero()); for (std::size_t j = 0; j < domain->size(); j++) { - auto key = std::make_pair(i, j); - S_perm[i][j] = delta.pow(permutation[key].first) * omega.pow(permutation[key].second); + auto key = std::make_pair(global_indices[i], j); + auto permuted_index = find(global_indices.begin(), global_indices.end(), permutation[key].first) - global_indices.begin(); + S_perm[i][j] = delta.pow(permuted_index) * omega.pow(permutation[key].second); } } @@ -459,8 +497,11 @@ namespace nil { const plonk_table_description &table_description, typename ParamsType::commitment_scheme_type &commitment_scheme, - std::size_t columns_with_copy_constraints, // TODO(martun): move delta back to placeholder_params, once template arguments are reduced. + // To prevent work with too large polynomials during proof generation + // if 0 -- any degree + // else -- we have a bound for permutations and lookups F-s degree rows_amount * (2 ^ max_quotient_poly_expand) + const std::size_t max_quotient_poly_chunks = 0, const typename FieldType::value_type& delta=algebra::fields::arithmetic_params::multiplicative_generator ) { PROFILE_PLACEHOLDER_SCOPE("Placeholder public preprocessor"); @@ -480,12 +521,18 @@ namespace nil { // TODO: add std::vector columns_with_copy_constraints; cycle_representation permutation(constraint_system, table_description); + auto permuted_columns = constraint_system.permuted_columns(); + std::vector global_indices; + for( auto it = permuted_columns.begin(); it != permuted_columns.end(); it++ ){ + global_indices.push_back(table_description.global_index(*it)); + } + std::vector id_perm_polys = - identity_polynomials(columns_with_copy_constraints, basic_domain->get_domain_element(1), + identity_polynomials(permuted_columns.size(), basic_domain->get_domain_element(1), delta, basic_domain); std::vector sigma_perm_polys = - permutation_polynomials(columns_with_copy_constraints, basic_domain->get_domain_element(1), + permutation_polynomials(global_indices, basic_domain->get_domain_element(1), delta, permutation, basic_domain); polynomial_dfs_type lagrange_0 = lagrange_polynomial(basic_domain, 0); @@ -509,6 +556,10 @@ namespace nil { // precommitments(public_polynomial_table, id_perm_polys, sigma_perm_polys, q_last_q_blind, // commitment_params); + BOOST_ASSERT(max_quotient_poly_chunks == 0 || max_quotient_poly_chunks > max_gates_degree ); + std::size_t permutation_parts_num = permutation_partitions_num(permuted_columns.size(), max_quotient_poly_chunks); + std::size_t lookup_parts_num = lookup_parts(constraint_system, max_quotient_poly_chunks).size(); + typename preprocessed_data_type::public_commitments_type public_commitments = commitments( public_polynomial_table, id_perm_polys, sigma_perm_polys, q_last_q_blind, commitment_scheme @@ -528,22 +579,23 @@ namespace nil { delta); typename preprocessed_data_type::verification_key vk = {constraint_system_with_params_hash, public_commitments.fixed_values}; - typename preprocessed_data_type::common_data_type common_data ( - std::move(public_commitments), std::move(c_rotations), - table_description.rows_amount, - table_description.usable_rows_amount, - table_description.witness_columns, - table_description.public_input_columns, - table_description.constant_columns, - table_description.selector_columns, - max_gates_degree, vk - ); transcript_type transcript(std::vector({})); transcript(vk.constraint_system_with_params_hash); transcript(vk.fixed_values_commitment); - common_data.commitment_scheme_data = commitment_scheme.preprocess(transcript); + typename preprocessed_data_type::common_data_type common_data ( + std::move(public_commitments), std::move(c_rotations), + table_description, + max_gates_degree, + permutation_parts_num, + lookup_parts_num, + vk, + global_indices, + commitment_scheme.get_commitment_params(), + commitment_scheme.preprocess(transcript), + max_quotient_poly_chunks + ); // Push circuit description to transcript preprocessed_data_type preprocessed_data({ diff --git a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp index b9ff71281..8c57cb86f 100644 --- a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp +++ b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp @@ -28,6 +28,8 @@ #ifndef CRYPTO3_ZK_PLONK_PLACEHOLDER_PROOF_HPP #define CRYPTO3_ZK_PLONK_PLACEHOLDER_PROOF_HPP +#include + namespace nil { namespace crypto3 { namespace zk { @@ -67,7 +69,7 @@ namespace nil { typename commitment_scheme_type::proof_type eval_proof; bool operator==(const evaluation_proof &rhs) const { - return challenge == rhs.challenge && eval_proof == rhs.eval_proof; + return challenge == rhs.challenge && eval_proof == rhs.eval_proof; } bool operator!=(const evaluation_proof &rhs) const { return !(rhs == *this); diff --git a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp index 8331d867b..4f07262f2 100644 --- a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp +++ b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp @@ -98,7 +98,6 @@ namespace nil { const plonk_constraint_system &constraint_system, commitment_scheme_type commitment_scheme ) { - auto prover = placeholder_prover( preprocessed_public_data, std::move(preprocessed_private_data), table_description, constraint_system, commitment_scheme); @@ -144,7 +143,7 @@ namespace nil { transcript(_proof.commitments[VARIABLE_VALUES_BATCH]); // 4. permutation_argument - { + if( constraint_system.copy_constraints().size() > 0 ){ auto permutation_argument = placeholder_permutation_argument::prove_eval( constraint_system, preprocessed_public_data, @@ -167,8 +166,10 @@ namespace nil { _F_dfs[6] = std::move(lookup_argument_result.F_dfs[3]); } - _proof.commitments[PERMUTATION_BATCH] = _commitment_scheme.commit(PERMUTATION_BATCH); - transcript(_proof.commitments[PERMUTATION_BATCH]); + if( constraint_system.copy_constraints().size() > 0 || constraint_system.lookup_gates().size() > 0){ + _proof.commitments[PERMUTATION_BATCH] = _commitment_scheme.commit(PERMUTATION_BATCH); + transcript(_proof.commitments[PERMUTATION_BATCH]); + } // 6. circuit-satisfability @@ -190,7 +191,6 @@ namespace nil { #ifdef ZK_PLACEHOLDER_DEBUG_ENABLED placeholder_debug_output(); #endif - // _polynomial_table not needed, clean its memory _polynomial_table.reset(nullptr); @@ -226,16 +226,20 @@ namespace nil { PROFILE_PLACEHOLDER_SCOPE("split_polynomial_dfs_conversion_time"); std::size_t split_polynomial_size = std::max( - (preprocessed_public_data.identity_polynomials.size() + 2) * (preprocessed_public_data.common_data.rows_amount -1 ), - (constraint_system.lookup_poly_degree_bound() + 1) * (preprocessed_public_data.common_data.rows_amount -1 )//, + (preprocessed_public_data.identity_polynomials.size() + 2) * (preprocessed_public_data.common_data.desc.rows_amount -1 ), + (constraint_system.lookup_poly_degree_bound() + 1) * (preprocessed_public_data.common_data.desc.rows_amount -1 )//, ); split_polynomial_size = std::max( split_polynomial_size, - (preprocessed_public_data.common_data.max_gates_degree + 1) * (preprocessed_public_data.common_data.rows_amount -1) + (preprocessed_public_data.common_data.max_gates_degree + 1) * (preprocessed_public_data.common_data.desc.rows_amount -1) ); - split_polynomial_size = (split_polynomial_size % preprocessed_public_data.common_data.rows_amount != 0)? - (split_polynomial_size / preprocessed_public_data.common_data.rows_amount + 1): - (split_polynomial_size / preprocessed_public_data.common_data.rows_amount); + split_polynomial_size = (split_polynomial_size % preprocessed_public_data.common_data.desc.rows_amount != 0)? + (split_polynomial_size / preprocessed_public_data.common_data.desc.rows_amount + 1): + (split_polynomial_size / preprocessed_public_data.common_data.desc.rows_amount); + + if( preprocessed_public_data.common_data.max_quotient_chunks != 0 && split_polynomial_size > preprocessed_public_data.common_data.max_quotient_chunks){ + split_polynomial_size = preprocessed_public_data.common_data.max_quotient_chunks; + } // We need split_polynomial_size computation because proof size shouldn't depend on public input size. // we set this size as maximum of @@ -250,7 +254,6 @@ namespace nil { for (std::size_t k = 0; k < T_splitted.size(); k++) { T_splitted_dfs[k].from_coefficients(T_splitted[k]); } - return T_splitted_dfs; } @@ -365,14 +368,18 @@ namespace nil { } } - _commitment_scheme.append_eval_point(PERMUTATION_BATCH, _proof.eval_proof.challenge); - _commitment_scheme.append_eval_point(PERMUTATION_BATCH, _proof.eval_proof.challenge * _omega); + if(_is_lookup_enabled || constraint_system.copy_constraints().size() > 0){ + _commitment_scheme.append_eval_point(PERMUTATION_BATCH, _proof.eval_proof.challenge); + _commitment_scheme.append_eval_point(PERMUTATION_BATCH, 0, _proof.eval_proof.challenge * _omega); + } + if(_is_lookup_enabled){ + _commitment_scheme.append_eval_point(PERMUTATION_BATCH, preprocessed_public_data.common_data.permutation_parts , _proof.eval_proof.challenge * _omega); _commitment_scheme.append_eval_point(LOOKUP_BATCH, _proof.eval_proof.challenge); _commitment_scheme.append_eval_point(LOOKUP_BATCH, _proof.eval_proof.challenge * _omega); _commitment_scheme.append_eval_point(LOOKUP_BATCH, _proof.eval_proof.challenge * - _omega.pow(preprocessed_public_data.common_data.usable_rows_amount)); + _omega.pow(preprocessed_public_data.common_data.desc.usable_rows_amount)); } _commitment_scheme.append_eval_point(QUOTIENT_BATCH, _proof.eval_proof.challenge); diff --git a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/verifier.hpp b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/verifier.hpp index fada7b59c..462978425 100644 --- a/include/nil/crypto3/zk/snark/systems/plonk/placeholder/verifier.hpp +++ b/include/nil/crypto3/zk/snark/systems/plonk/placeholder/verifier.hpp @@ -61,7 +61,7 @@ namespace nil { public: static void generate_evaluation_points( commitment_scheme_type &_commitment_scheme, - const typename public_preprocessor_type::preprocessed_data_type &preprocessed_public_data, + const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, const plonk_constraint_system &constraint_system, const plonk_table_description &table_description, typename FieldType::value_type challenge, @@ -72,8 +72,9 @@ namespace nil { const std::size_t witness_columns = table_description.witness_columns; const std::size_t public_input_columns = table_description.public_input_columns; const std::size_t constant_columns = table_description.constant_columns; + const std::size_t selector_columns = table_description.selector_columns; - auto _omega = preprocessed_public_data.common_data.basic_domain->get_domain_element(1); + auto _omega = common_data.basic_domain->get_domain_element(1); // variable_values' rotations for (std::size_t variable_values_index = 0; @@ -81,7 +82,7 @@ namespace nil { variable_values_index++ ) { const std::set& variable_values_rotation = - preprocessed_public_data.common_data.columns_rotations[variable_values_index]; + common_data.columns_rotations[variable_values_index]; for (int rotation: variable_values_rotation) { _commitment_scheme.append_eval_point( @@ -92,13 +93,16 @@ namespace nil { } } - _commitment_scheme.append_eval_point(PERMUTATION_BATCH, challenge); - _commitment_scheme.append_eval_point(PERMUTATION_BATCH, challenge * _omega); + if( _is_lookup_enabled || constraint_system.copy_constraints().size() > 0){ + _commitment_scheme.append_eval_point(PERMUTATION_BATCH, challenge); + _commitment_scheme.append_eval_point(PERMUTATION_BATCH, 0, challenge * _omega); + } if (_is_lookup_enabled) { + _commitment_scheme.append_eval_point(PERMUTATION_BATCH, common_data.permutation_parts , challenge * _omega); _commitment_scheme.append_eval_point(LOOKUP_BATCH, challenge); _commitment_scheme.append_eval_point(LOOKUP_BATCH, challenge * _omega); - _commitment_scheme.append_eval_point(LOOKUP_BATCH, challenge * _omega.pow(preprocessed_public_data.common_data.usable_rows_amount)); + _commitment_scheme.append_eval_point(LOOKUP_BATCH, challenge * _omega.pow(common_data.desc.usable_rows_amount)); } _commitment_scheme.append_eval_point(QUOTIENT_BATCH, challenge); @@ -106,22 +110,22 @@ namespace nil { // fixed values' rotations (table columns) std::size_t i = 0; - std::size_t start_index = preprocessed_public_data.identity_polynomials.size() + - preprocessed_public_data.permutation_polynomials.size() + 2; + std::size_t start_index = common_data.permuted_columns.size() * 2 + 2; for( i = 0; i < start_index; i++){ _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, i, challenge); } + // for special selectors _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, start_index - 2, challenge * _omega); _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, start_index - 1, challenge * _omega); for (std::size_t ind = 0; - ind < constant_columns + preprocessed_public_data.public_polynomial_table.selectors().size(); + ind < constant_columns + selector_columns; ind++, i++ ) { const std::set& fixed_values_rotation = - preprocessed_public_data.common_data.columns_rotations[witness_columns + public_input_columns + ind]; + common_data.columns_rotations[witness_columns + public_input_columns + ind]; for (int rotation: fixed_values_rotation) { _commitment_scheme.append_eval_point( @@ -134,7 +138,7 @@ namespace nil { } static inline bool process( - const typename public_preprocessor_type::preprocessed_data_type &preprocessed_public_data, + const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, const placeholder_proof &proof, const plonk_table_description &table_description, const plonk_constraint_system &constraint_system, @@ -142,10 +146,10 @@ namespace nil { const std::vector> &public_input ){ // TODO: process rotations for public input. - auto omega = preprocessed_public_data.common_data.basic_domain->get_domain_element(1); + auto omega = common_data.basic_domain->get_domain_element(1); auto challenge = proof.eval_proof.challenge; - auto numerator = challenge.pow(preprocessed_public_data.common_data.rows_amount) - FieldType::value_type::one(); - numerator /= typename FieldType::value_type(preprocessed_public_data.common_data.rows_amount); + auto numerator = challenge.pow(table_description.rows_amount) - FieldType::value_type::one(); + numerator /= typename FieldType::value_type(table_description.rows_amount); // If public input sizes are set, all of them should be set. if(constraint_system.public_input_sizes_num() != 0 && constraint_system.public_input_sizes_num() != table_description.public_input_columns){ @@ -168,11 +172,11 @@ namespace nil { return false; } } - return process(preprocessed_public_data, proof, table_description, constraint_system, commitment_scheme); + return process(common_data, proof, table_description, constraint_system, commitment_scheme); } static inline bool process( - const typename public_preprocessor_type::preprocessed_data_type &preprocessed_public_data, + const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, const placeholder_proof &proof, const plonk_table_description &table_description, const plonk_constraint_system &constraint_system, @@ -185,49 +189,75 @@ namespace nil { transcript::fiat_shamir_heuristic_sequential transcript(std::vector({})); - transcript(preprocessed_public_data.common_data.vk.constraint_system_with_params_hash); - transcript(preprocessed_public_data.common_data.vk.fixed_values_commitment); + transcript(common_data.vk.constraint_system_with_params_hash); + transcript(common_data.vk.fixed_values_commitment); // Setup commitment scheme. LPC adds an additional point here. - commitment_scheme.setup(transcript, preprocessed_public_data.common_data.commitment_scheme_data); + commitment_scheme.setup(transcript, common_data.commitment_scheme_data); // 3. append witness commitments to transcript transcript(proof.commitments.at(VARIABLE_VALUES_BATCH)); + std::vector special_selector_values(3); + special_selector_values[0] = common_data.lagrange_0.evaluate(proof.eval_proof.challenge); + special_selector_values[1] = proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH, 2*common_data.permuted_columns.size(), 0); + special_selector_values[2] = proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH, 2*common_data.permuted_columns.size() + 1, 0); + // 4. prepare evaluaitons of the polynomials that are copy-constrained + std::array F; std::size_t permutation_size = (proof.eval_proof.eval_proof.z.get_batch_size(FIXED_VALUES_BATCH) - 2 - constant_columns - selector_columns) / 2; - - std::vector f(permutation_size); - for (std::size_t i = 0; i < permutation_size; i++) { - std::size_t zero_index = 0; - for (int v: preprocessed_public_data.common_data.columns_rotations[i]) { - if (v == 0){ - break; + if( constraint_system.copy_constraints().size() > 0 ){ + // Permutation polys + std::vector permuted_polys_global_indices = common_data.permuted_columns; + std::vector f(permutation_size); + std::vector S_id; + std::vector S_sigma; + + for (std::size_t perm_i = 0; perm_i < permutation_size; perm_i++) { + S_id.push_back(proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH, perm_i, 0)); + S_sigma.push_back(proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH, permutation_size + perm_i, 0)); + + std::size_t i = permuted_polys_global_indices[perm_i]; + std::size_t zero_index = 0; + for (int v: common_data.columns_rotations[i]) { + if (v == 0){ + break; + } + zero_index++; + } + if (i < witness_columns + public_input_columns) { + f[perm_i] = proof.eval_proof.eval_proof.z.get(VARIABLE_VALUES_BATCH,i,zero_index); + } else if (i >= witness_columns + public_input_columns ) { + std::size_t idx = i - witness_columns - public_input_columns + permutation_size*2 + 2; + f[perm_i] = proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH,idx,zero_index); } - zero_index++; } - if (i < witness_columns + public_input_columns) { - f[i] = proof.eval_proof.eval_proof.z.get(VARIABLE_VALUES_BATCH,i,zero_index); - } else if (i < witness_columns + public_input_columns + constant_columns) { - std::size_t idx = i - witness_columns - public_input_columns + permutation_size*2 + 2; - f[i] = proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH,idx,zero_index); + + // 5. permutation argument + std::vector perm_partitions; + for( std::size_t i = 1; i < common_data.permutation_parts; i++ ){ + perm_partitions.push_back(proof.eval_proof.eval_proof.z.get(PERMUTATION_BATCH, i, 0)); } + std::array permutation_argument = + placeholder_permutation_argument::verify_eval( + common_data, + S_id, S_sigma, special_selector_values, + proof.eval_proof.challenge, f, + proof.eval_proof.eval_proof.z.get(PERMUTATION_BATCH, 0, 0), + proof.eval_proof.eval_proof.z.get(PERMUTATION_BATCH, 0, 1), + perm_partitions, + transcript + ); + F[0] = permutation_argument[0]; + F[1] = permutation_argument[1]; + F[2] = permutation_argument[2]; } - // 5. permutation argument - std::array permutation_argument = - placeholder_permutation_argument::verify_eval( - preprocessed_public_data, proof.eval_proof.challenge, f, - proof.eval_proof.eval_proof.z.get(PERMUTATION_BATCH, 0, 0), - proof.eval_proof.eval_proof.z.get(PERMUTATION_BATCH, 0, 1), - transcript - ); - typename policy_type::evaluation_map columns_at_y; for (std::size_t i = 0; i < witness_columns; i++) { std::size_t i_global_index = i; std::size_t j = 0; - for (int rotation: preprocessed_public_data.common_data.columns_rotations[i_global_index]) { + for (int rotation: common_data.columns_rotations[i_global_index]) { auto key = std::make_tuple( i, rotation, @@ -241,7 +271,7 @@ namespace nil { std::size_t i_global_index = witness_columns + i; std::size_t j = 0; - for (int rotation: preprocessed_public_data.common_data.columns_rotations[i_global_index]) { + for (int rotation: common_data.columns_rotations[i_global_index]) { auto key = std::make_tuple( i, rotation, @@ -254,7 +284,7 @@ namespace nil { for (std::size_t i = 0; i < 0 + constant_columns; i++) { std::size_t i_global_index = witness_columns + public_input_columns + i; std::size_t j = 0; - for (int rotation: preprocessed_public_data.common_data.columns_rotations[i_global_index]) { + for (int rotation: common_data.columns_rotations[i_global_index]) { auto key = std::make_tuple( i, rotation, @@ -267,7 +297,7 @@ namespace nil { for (std::size_t i = 0; i < selector_columns; i++) { std::size_t i_global_index = witness_columns + constant_columns + public_input_columns + i; std::size_t j = 0; - for (int rotation: preprocessed_public_data.common_data.columns_rotations[i_global_index]) { + for (int rotation: common_data.columns_rotations[i_global_index]) { auto key = std::make_tuple( i, rotation, @@ -281,27 +311,40 @@ namespace nil { bool is_lookup_enabled = (constraint_system.lookup_gates().size() > 0); std::array lookup_argument; if (is_lookup_enabled) { + std::vector special_selector_values_shifted(2); + special_selector_values_shifted[0] = proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH, 2*common_data.permuted_columns.size(), 1); + special_selector_values_shifted[1] = proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH, 2*common_data.permuted_columns.size() + 1, 1); + + std::vector lookup_parts_values; + for( std::size_t i = common_data.permutation_parts + 1; + i < common_data.permutation_parts + common_data.lookup_parts; + i++ + ) lookup_parts_values.push_back(proof.eval_proof.eval_proof.z.get(PERMUTATION_BATCH, i, 0)); + placeholder_lookup_argument_verifier lookup_argument_verifier; lookup_argument = lookup_argument_verifier.verify_eval( - preprocessed_public_data, - constraint_system.lookup_gates(), - constraint_system.lookup_tables(), + common_data, + special_selector_values, special_selector_values_shifted, + constraint_system, proof.eval_proof.challenge, columns_at_y, proof.eval_proof.eval_proof.z.get(LOOKUP_BATCH), - proof.eval_proof.eval_proof.z.get(PERMUTATION_BATCH, 1), + proof.eval_proof.eval_proof.z.get(PERMUTATION_BATCH, common_data.permutation_parts), + lookup_parts_values, proof.commitments.at(LOOKUP_BATCH), transcript ); } - transcript(proof.commitments.at(PERMUTATION_BATCH)); + if( constraint_system.copy_constraints().size() > 0 || constraint_system.lookup_gates().size() > 0){ + transcript(proof.commitments.at(PERMUTATION_BATCH)); + } // 7. gate argument std::array gate_argument = - placeholder_gates_argument::verify_eval( - constraint_system.gates(), columns_at_y, proof.eval_proof.challenge, - FieldType::value_type::one() - - preprocessed_public_data.q_last.evaluate(proof.eval_proof.challenge) - - preprocessed_public_data.q_blind.evaluate(proof.eval_proof.challenge), - transcript + placeholder_gates_argument::verify_eval( + constraint_system.gates(), columns_at_y, proof.eval_proof.challenge, + FieldType::value_type::one() - + proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH, common_data.permuted_columns.size() * 2, 0) - + proof.eval_proof.eval_proof.z.get(FIXED_VALUES_BATCH, common_data.permuted_columns.size() * 2 + 1, 0), + transcript ); std::array alphas = @@ -314,24 +357,21 @@ namespace nil { BOOST_ASSERT(challenge == proof.eval_proof.challenge); commitment_scheme.set_batch_size(VARIABLE_VALUES_BATCH, proof.eval_proof.eval_proof.z.get_batch_size(VARIABLE_VALUES_BATCH)); - commitment_scheme.set_batch_size(PERMUTATION_BATCH, proof.eval_proof.eval_proof.z.get_batch_size(PERMUTATION_BATCH)); + if( is_lookup_enabled || constraint_system.copy_constraints().size()) + commitment_scheme.set_batch_size(PERMUTATION_BATCH, proof.eval_proof.eval_proof.z.get_batch_size(PERMUTATION_BATCH)); commitment_scheme.set_batch_size(QUOTIENT_BATCH, proof.eval_proof.eval_proof.z.get_batch_size(QUOTIENT_BATCH)); if (is_lookup_enabled) commitment_scheme.set_batch_size(LOOKUP_BATCH, proof.eval_proof.eval_proof.z.get_batch_size(LOOKUP_BATCH)); - generate_evaluation_points(commitment_scheme, preprocessed_public_data, constraint_system, + generate_evaluation_points(commitment_scheme, common_data, constraint_system, table_description, challenge, is_lookup_enabled); std::map commitments = proof.commitments; - commitments[FIXED_VALUES_BATCH] = preprocessed_public_data.common_data.commitments.fixed_values; + commitments[FIXED_VALUES_BATCH] = common_data.commitments.fixed_values; if (!commitment_scheme.verify_eval( proof.eval_proof.eval_proof, commitments, transcript )) { return false; } // 10. final check - std::array F; - F[0] = permutation_argument[0]; - F[1] = permutation_argument[1]; - F[2] = permutation_argument[2]; F[3] = lookup_argument[0]; F[4] = lookup_argument[1]; F[5] = lookup_argument[2]; @@ -346,11 +386,11 @@ namespace nil { typename FieldType::value_type T_consolidated = FieldType::value_type::zero(); for (std::size_t i = 0; i < proof.eval_proof.eval_proof.z.get_batch_size(QUOTIENT_BATCH); i++) { T_consolidated += proof.eval_proof.eval_proof.z.get(QUOTIENT_BATCH, i, 0) * - challenge.pow((preprocessed_public_data.common_data.rows_amount) * i); + challenge.pow((common_data.desc.rows_amount) * i); } // Z is polynomial -1, 0 ...., 0, 1 - typename FieldType::value_type Z_at_challenge = preprocessed_public_data.common_data.Z.evaluate(challenge); + typename FieldType::value_type Z_at_challenge = common_data.Z.evaluate(challenge); if (F_consolidated != Z_at_challenge * T_consolidated) { return false; } diff --git a/test/commitment/fri.cpp b/test/commitment/fri.cpp index 4fce9ae8e..87597d63c 100644 --- a/test/commitment/fri.cpp +++ b/test/commitment/fri.cpp @@ -95,7 +95,7 @@ BOOST_AUTO_TEST_CASE(fri_basic_test) { constexpr static const std::size_t m = 2; constexpr static const std::size_t lambda = 40; - typedef zk::commitments::fri fri_type; + typedef zk::commitments::fri fri_type; static_assert(zk::is_commitment::value); static_assert(!zk::is_commitment::value); @@ -113,7 +113,10 @@ BOOST_AUTO_TEST_CASE(fri_basic_test) { d - 1, // max_degree D, generate_random_step_list(r, 1), - 2 //expand_factor + 2, //expand_factor + lambda, + true, + 0xFFFFF ); BOOST_CHECK(D[1]->m == D[0]->m / 2); diff --git a/test/commitment/kzg.cpp b/test/commitment/kzg.cpp index 5c97a0d2c..55dd90661 100644 --- a/test/commitment/kzg.cpp +++ b/test/commitment/kzg.cpp @@ -57,6 +57,7 @@ #include #include +#include using namespace nil::crypto3; using namespace nil::crypto3::math; @@ -947,7 +948,7 @@ struct placeholder_class_test_initializer { using kzg_scheme_type = typename zk::commitments::kzg_commitment_scheme_v2; scalar_value_type alpha = 7; - auto params = typename kzg_type::params_type(8, 8, alpha); + auto params = kzg_scheme_type::create_params(8, alpha); kzg_scheme_type kzg(params); typename kzg_type::batch_of_polynomials_type polys(4); diff --git a/test/commitment/lpc.cpp b/test/commitment/lpc.cpp index 4cf806d26..2935789c1 100644 --- a/test/commitment/lpc.cpp +++ b/test/commitment/lpc.cpp @@ -180,10 +180,10 @@ BOOST_FIXTURE_TEST_CASE(lpc_basic_test, test_fixture) { constexpr static const std::size_t m = 2; - typedef zk::commitments::fri fri_type; + typedef zk::commitments::fri fri_type; typedef zk::commitments:: - list_polynomial_commitment_params + list_polynomial_commitment_params lpc_params_type; typedef zk::commitments::list_polynomial_commitment lpc_type; @@ -204,7 +204,10 @@ BOOST_FIXTURE_TEST_CASE(lpc_basic_test, test_fixture) { d - 1, // max_degree D, generate_random_step_list(r, 1, test_global_rnd_engine), - 2 //expand_factor + 2, //expand_factor + lambda, + true, + 0xFFF ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; @@ -277,10 +280,10 @@ BOOST_FIXTURE_TEST_CASE(lpc_basic_skipping_layers_test, test_fixture) { constexpr static const std::size_t r = boost::static_log2<(d - k)>::value; constexpr static const std::size_t m = 2; - typedef zk::commitments::fri fri_type; + typedef zk::commitments::fri fri_type; typedef zk::commitments:: - list_polynomial_commitment_params + list_polynomial_commitment_params lpc_params_type; typedef zk::commitments::list_polynomial_commitment lpc_type; @@ -295,14 +298,15 @@ BOOST_FIXTURE_TEST_CASE(lpc_basic_skipping_layers_test, test_fixture) { std::vector>> D = math::calculate_domain_set(extended_log, r); - typedef zk::commitments::fri fri_type; + typedef zk::commitments::fri fri_type; // Setup params typename fri_type::params_type fri_params( d - 1, // max_degree D, generate_random_step_list(r, 5, test_global_rnd_engine), - 2 //expand_factor + 2, //expand_factor + lambda ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; @@ -371,10 +375,10 @@ BOOST_FIXTURE_TEST_CASE(lpc_dfs_basic_test, test_fixture) { constexpr static const std::size_t r = boost::static_log2<(d - k)>::value; constexpr static const std::size_t m = 2; - typedef zk::commitments::fri fri_type; + typedef zk::commitments::fri fri_type; typedef zk::commitments:: - list_polynomial_commitment_params + list_polynomial_commitment_params lpc_params_type; typedef zk::commitments::list_polynomial_commitment lpc_type; @@ -395,7 +399,9 @@ BOOST_FIXTURE_TEST_CASE(lpc_dfs_basic_test, test_fixture) { d - 1, // max_degree D, generate_random_step_list(r, 1, test_global_rnd_engine), - 2 //expand_factor + 2, //expand_factor + lambda, + true ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme; @@ -466,10 +472,10 @@ BOOST_FIXTURE_TEST_CASE(lpc_batches_num_3_test, test_fixture){ constexpr static const std::size_t r = boost::static_log2<(d - k)>::value; constexpr static const std::size_t m = 2; - typedef zk::commitments::fri fri_type; + typedef zk::commitments::fri fri_type; typedef zk::commitments:: - list_polynomial_commitment_params + list_polynomial_commitment_params lpc_params_type; typedef zk::commitments::list_polynomial_commitment lpc_type; @@ -488,7 +494,10 @@ BOOST_FIXTURE_TEST_CASE(lpc_batches_num_3_test, test_fixture){ d - 1, // max_degree D, generate_random_step_list(r, 1, test_global_rnd_engine), - 2 //expand_factor + 2, //expand_factor + lambda, + true, + 0xFF ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; @@ -555,10 +564,10 @@ BOOST_FIXTURE_TEST_CASE(lpc_different_hash_types_test, test_fixture) { constexpr static const std::size_t m = 2; - typedef zk::commitments::fri fri_type; + typedef zk::commitments::fri fri_type; typedef zk::commitments:: - list_polynomial_commitment_params + list_polynomial_commitment_params lpc_params_type; typedef zk::commitments::list_polynomial_commitment lpc_type; @@ -577,7 +586,8 @@ BOOST_FIXTURE_TEST_CASE(lpc_different_hash_types_test, test_fixture) { d - 1, // max_degree D, generate_random_step_list(r, 1, test_global_rnd_engine), - 2 //expand_factor + 2, //expand_factor + lambda ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; diff --git a/test/commitment/lpc_performance.cpp b/test/commitment/lpc_performance.cpp index ce5f24971..cb524025a 100644 --- a/test/commitment/lpc_performance.cpp +++ b/test/commitment/lpc_performance.cpp @@ -138,8 +138,8 @@ BOOST_AUTO_TEST_CASE(step_list_1) { constexpr static const std::size_t m = 2; - typedef zk::commitments::fri fri_type; - typedef zk::commitments::list_polynomial_commitment_params lpc_params_type; + typedef zk::commitments::fri fri_type; + typedef zk::commitments::list_polynomial_commitment_params lpc_params_type; typedef zk::commitments::list_polynomial_commitment lpc_type; constexpr static const std::size_t d_extended = d; @@ -151,7 +151,8 @@ BOOST_AUTO_TEST_CASE(step_list_1) { d - 1, D, generate_random_step_list(r, 1), - r + r, + lambda ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; @@ -225,8 +226,8 @@ BOOST_AUTO_TEST_CASE(step_list_3) { constexpr static const std::size_t r = boost::static_log2<(d - k)>::value; constexpr static const std::size_t m = 2; - typedef zk::commitments::fri fri_type; - typedef zk::commitments::list_polynomial_commitment_params lpc_params_type; + typedef zk::commitments::fri fri_type; + typedef zk::commitments::list_polynomial_commitment_params lpc_params_type; typedef zk::commitments::list_polynomial_commitment lpc_type; constexpr static const std::size_t d_extended = d; @@ -238,7 +239,8 @@ BOOST_AUTO_TEST_CASE(step_list_3) { d - 1, D, generate_random_step_list(r, 3), - r + r, + lambda ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; @@ -311,8 +313,8 @@ BOOST_AUTO_TEST_CASE(step_list_5) { constexpr static const std::size_t m = 2; constexpr static const std::size_t r = boost::static_log2<(d - k)>::value; - typedef zk::commitments::fri fri_type; - typedef zk::commitments::list_polynomial_commitment_params lpc_params_type; + typedef zk::commitments::fri fri_type; + typedef zk::commitments::list_polynomial_commitment_params lpc_params_type; typedef zk::commitments::list_polynomial_commitment lpc_type; constexpr static const std::size_t d_extended = d; @@ -324,7 +326,8 @@ BOOST_AUTO_TEST_CASE(step_list_5) { d - 1, D, generate_random_step_list(r, 5), - r + r, + lambda ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; diff --git a/test/commitment/proof_of_work.cpp b/test/commitment/proof_of_work.cpp index b514f9698..b9efa0b16 100644 --- a/test/commitment/proof_of_work.cpp +++ b/test/commitment/proof_of_work.cpp @@ -49,36 +49,35 @@ BOOST_AUTO_TEST_CASE(pow_poseidon_basic_test) { using integral_type = typename field_type::integral_type; using policy = nil::crypto3::hashes::detail::mina_poseidon_policy; using poseidon = nil::crypto3::hashes::poseidon; - using pow_type = nil::crypto3::zk::commitments::field_proof_of_work; + using pow_type = nil::crypto3::zk::commitments::field_proof_of_work; const integral_type expected_mask = integral_type(0xFF80000000000000) << (field_type::modulus_bits - 64); nil::crypto3::zk::transcript::fiat_shamir_heuristic_sequential transcript; auto old_transcript_1 = transcript, old_transcript_2 = transcript; - auto result = pow_type::generate(transcript); - BOOST_ASSERT(expected_mask == pow_type::mask); - BOOST_ASSERT(pow_type::verify(old_transcript_1, result)); + auto result = pow_type::generate(transcript, 9); + BOOST_ASSERT(pow_type::verify(old_transcript_1, result, 9)); // manually reimplement verify to ensure that changes in implementation didn't break it old_transcript_2(result); auto chal = old_transcript_2.template challenge(); BOOST_ASSERT((integral_type(chal.data) & expected_mask) == 0); - using hard_pow_type = nil::crypto3::zk::commitments::field_proof_of_work; + using hard_pow_type = nil::crypto3::zk::commitments::field_proof_of_work; // check that random stuff doesn't pass verify - BOOST_ASSERT(!hard_pow_type::verify(old_transcript_1, result)); + BOOST_ASSERT(!hard_pow_type::verify(old_transcript_1, result, 9)); } BOOST_AUTO_TEST_CASE(pow_basic_test) { using keccak = nil::crypto3::hashes::keccak_1600<512>; const std::uint32_t mask = 0xFFFFF000; - using pow_type = nil::crypto3::zk::commitments::proof_of_work; + using pow_type = nil::crypto3::zk::commitments::proof_of_work; nil::crypto3::zk::transcript::fiat_shamir_heuristic_sequential transcript; auto old_transcript_1 = transcript, old_transcript_2 = transcript; - auto result = pow_type::generate(transcript); - BOOST_ASSERT(pow_type::verify(old_transcript_1, result)); + auto result = pow_type::generate(transcript, mask); + BOOST_ASSERT(pow_type::verify(old_transcript_1, result, mask)); // manually reimplement verify to ensure that changes in implementation didn't break it std::array bytes; @@ -91,8 +90,8 @@ BOOST_AUTO_TEST_CASE(pow_basic_test) { BOOST_ASSERT((chal & mask) == 0); // check that random stuff doesn't pass verify - using hard_pow_type = nil::crypto3::zk::commitments::proof_of_work; - BOOST_ASSERT(!hard_pow_type::verify(old_transcript_1, result)); + using hard_pow_type = nil::crypto3::zk::commitments::proof_of_work; + BOOST_ASSERT(!hard_pow_type::verify(old_transcript_1, result, mask)); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/systems/plonk/placeholder/circuits.hpp b/test/systems/plonk/placeholder/circuits.hpp index 77832ba57..fa6471299 100644 --- a/test/systems/plonk/placeholder/circuits.hpp +++ b/test/systems/plonk/placeholder/circuits.hpp @@ -54,7 +54,7 @@ namespace nil { namespace crypto3 { namespace zk { namespace snark { - template + template class circuit_description { typedef zk::snark::detail::placeholder_policy policy_type; @@ -96,14 +96,13 @@ namespace nil { const std::size_t rows_amount_1 = 13; template - circuit_description, rows_amount_1, 4> circuit_test_1( + circuit_description, rows_amount_1> circuit_test_1( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; constexpr static const std::size_t usable_rows = rows_amount_1; - constexpr static const std::size_t permutation = 4; constexpr static const std::size_t witness_columns = witness_columns_1; constexpr static const std::size_t public_columns = public_columns_1; @@ -113,7 +112,7 @@ namespace nil { witness_columns + public_columns + constant_columns; typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::vector> table(table_columns); std::vector q_add(test_circuit.usable_rows); @@ -228,10 +227,9 @@ namespace nil { constexpr static const std::size_t constant_columns_t = 0; constexpr static const std::size_t selector_columns_t = 2; constexpr static const std::size_t usable_rows_t = 5; - constexpr static const std::size_t permutation_t = 4; template - circuit_description, usable_rows_t, permutation_t> + circuit_description, usable_rows_t> circuit_test_t( typename FieldType::value_type pi0 = 0, typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), @@ -239,7 +237,6 @@ namespace nil { ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t permutation = permutation_t; constexpr static const std::size_t usable_rows = usable_rows_t; constexpr static const std::size_t witness_columns = witness_columns_t; constexpr static const std::size_t public_columns = public_columns_t; @@ -250,7 +247,7 @@ namespace nil { typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; test_circuit.public_input_sizes = {3}; std::vector> table(table_columns); @@ -363,16 +360,14 @@ namespace nil { constexpr static const std::size_t constant_columns_3 = 3; constexpr static const std::size_t selector_columns_3 = 2; constexpr static const std::size_t usable_rows_3 = 4; - constexpr static const std::size_t permutation_size_3 = 3; template - circuit_description, usable_rows_3, permutation_size_3> circuit_test_3( + circuit_description, usable_rows_3> circuit_test_3( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t permutation = permutation_size_3; constexpr static const std::size_t witness_columns = witness_columns_3; constexpr static const std::size_t public_columns = public_columns_3; constexpr static const std::size_t constant_columns = constant_columns_3; @@ -383,7 +378,7 @@ namespace nil { typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::vector> table(table_columns); for (std::size_t j = 0; j < table_columns; j++) { @@ -472,14 +467,13 @@ namespace nil { constexpr static const std::size_t selector_columns_4 = 3; template - circuit_description, 5, 3> circuit_test_4( + circuit_description, 5> circuit_test_4( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; constexpr static const std::size_t rows_log = 3; - constexpr static const std::size_t permutation = 3; constexpr static const std::size_t witness_columns = witness_columns_4; constexpr static const std::size_t public_columns = public_columns_4; @@ -490,7 +484,7 @@ namespace nil { typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; test_circuit.table_rows = 1 << rows_log; std::vector> table(table_columns); @@ -568,6 +562,80 @@ namespace nil { return test_circuit; } + //---------------------------------------------------------------------------// + // Test circuit 5 (wide table) + // i | GATE | w_0 | w_1 | w_2 | ... | w135 | public | q_mul | + // 0 | -- | p_0 | p_1 | p_2 | | p135 | p0 | 0 | + // 1 | | q0 | q1 | q2 | | q135 | p1 | 1 | + // 2 | | r0 | r1 | r2 | | r135 | ... | 0 | + // ...| ... | | | | | 0 | p135 | 0 | + // + // MUL: w_{i-1} - w_{i} * w_{i+1} = 0 + //---------------------------------------------------------------------------// + constexpr static const std::size_t witness_columns_5 = 30; + constexpr static const std::size_t public_columns_5 = 1; + constexpr static const std::size_t constant_columns_5 = 0; + constexpr static const std::size_t selector_columns_5 = 1; + constexpr static const std::size_t usable_rows_5 = 30; + + template + circuit_description, usable_rows_5> + circuit_test_5( + typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), + boost::random::mt11213b rnd = boost::random::mt11213b() + ) { + using assignment_type = typename FieldType::value_type; + + constexpr static const std::size_t usable_rows = usable_rows_5; + constexpr static const std::size_t witness_columns = witness_columns_5; + constexpr static const std::size_t public_input_columns = public_columns_5; + constexpr static const std::size_t constant_columns = constant_columns_5; + constexpr static const std::size_t selector_columns = selector_columns_5; + constexpr static const std::size_t table_columns = + witness_columns + public_input_columns + constant_columns; + + typedef placeholder_circuit_params circuit_params; + + circuit_description test_circuit; + test_circuit.public_input_sizes = {witness_columns}; + + std::vector> private_assignment(witness_columns); + std::vector> public_input_assignment(public_input_columns); + std::vector> constant_assignment(constant_columns); + std::vector> selectors_assignment(selector_columns); + + public_input_assignment[0].resize(test_circuit.usable_rows); + selectors_assignment[0].resize(test_circuit.usable_rows); + for(std::size_t i = 0; i < witness_columns; i++) { + private_assignment[i].resize(test_circuit.usable_rows); + private_assignment[i][0] = private_assignment[i][2] = public_input_assignment[0][i] = typename FieldType::value_type(rnd() % witness_columns); + private_assignment[i][1] = 1; + plonk_variable pi(0, i, false, plonk_variable::column_type::public_input); + plonk_variable wi(i, 0, false, plonk_variable::column_type::witness); + test_circuit.copy_constraints.push_back(plonk_copy_constraint({pi, wi})); + } + selectors_assignment[0][1] = 1; + + test_circuit.table = plonk_assignment_table( + plonk_private_assignment_table(private_assignment), + plonk_public_assignment_table( + public_input_assignment, constant_assignment, selectors_assignment)); + test_circuit.table_rows = zk_padding>(test_circuit.table, alg_rnd); + + std::vector> mul_gate_constraints; + for( std::size_t i = 0; i < witness_columns; i++){ + plonk_variable w0(i, -1, true, plonk_variable::column_type::witness); + plonk_variable w1(i, 0, true, plonk_variable::column_type::witness); + plonk_variable w2(i, 1, true, plonk_variable::column_type::witness); + mul_gate_constraints.push_back(w0 - w1 * w2); + } + + plonk_gate> mul_gate(0, mul_gate_constraints); + test_circuit.gates.push_back(mul_gate); + + return test_circuit; + } + //---------------------------------------------------------------------------// // Test fibonacci circuit // i | GATE | w_0 | public | q_add | @@ -586,14 +654,12 @@ namespace nil { constexpr static const std::size_t selector_columns_fib = 1; template - circuit_description, usable_rows, 2> + circuit_description, usable_rows> circuit_test_fib( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine() ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t permutation = 2; - constexpr static const std::size_t witness_columns = witness_columns_fib; constexpr static const std::size_t public_columns = public_columns_fib; constexpr static const std::size_t constant_columns = constant_columns_fib; @@ -603,7 +669,7 @@ namespace nil { typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::vector> table(table_columns); std::vector q_add(test_circuit.usable_rows); @@ -705,14 +771,12 @@ namespace nil { constexpr static const std::size_t usable_rows_6 = 6; template - circuit_description, usable_rows_6, 3> circuit_test_6( + circuit_description, usable_rows_6> circuit_test_6( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t permutation = 3; - constexpr static const std::size_t witness_columns = witness_columns_6; constexpr static const std::size_t public_columns = public_columns_6; constexpr static const std::size_t constant_columns = constant_columns_6; @@ -722,7 +786,7 @@ namespace nil { typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::vector> table(table_columns); for (std::size_t j = 0; j < table_columns; j++) { @@ -848,14 +912,12 @@ namespace nil { constexpr static const std::size_t usable_rows_7 = 14; template - circuit_description, usable_rows_7, 3> circuit_test_7( + circuit_description, usable_rows_7> circuit_test_7( typename nil::crypto3::random::algebraic_engine alg_rnd = nil::crypto3::random::algebraic_engine(), boost::random::mt11213b rnd = boost::random::mt11213b() ) { using assignment_type = typename FieldType::value_type; - constexpr static const std::size_t permutation = 3; - constexpr static const std::size_t witness_columns = witness_columns_7; constexpr static const std::size_t public_columns = public_columns_7; constexpr static const std::size_t constant_columns = constant_columns_7; @@ -865,7 +927,7 @@ namespace nil { typedef placeholder_circuit_params circuit_params; - circuit_description test_circuit; + circuit_description test_circuit; std::vector> table(table_columns); for (std::size_t j = 0; j < table_columns; j++) { diff --git a/test/systems/plonk/placeholder/performance.cpp b/test/systems/plonk/placeholder/performance.cpp index 048c329d6..006e2d0e6 100644 --- a/test/systems/plonk/placeholder/performance.cpp +++ b/test/systems/plonk/placeholder/performance.cpp @@ -112,20 +112,6 @@ class placeholder_performance_test_base { } return step_list; } - - template - typename fri_type::params_type create_fri_params( - std::size_t degree_log, const int max_step = 1, std::size_t expand_factor = 7) { - std::size_t r = degree_log - 1; - - return typename fri_type::params_type( - (1 << degree_log) - 1, // max_degree - math::calculate_domain_set(degree_log + expand_factor, r), - generate_random_step_list(r, max_step), - expand_factor - ); -} - }; template @@ -147,7 +133,7 @@ class placeholder_performance_test : public placeholder_performance_test_base { static constexpr std::size_t TotalColumns = WitnessColumns + PublicInputColumns + ConstantColumns + SelectorColumns; using lpc_params_type = commitments::list_polynomial_commitment_params< - hash_type, hash_type, lambda, m, true /* use grinding */>; + hash_type, hash_type, m>; using lpc_type = commitments::list_polynomial_commitment; using lpc_scheme_type = typename commitments::lpc_commitment_scheme; @@ -182,8 +168,9 @@ class placeholder_performance_test : public placeholder_performance_test_base { std::cout << "rows_amount = " << table_description.rows_amount << std::endl; std::size_t table_rows_log = std::ceil(std::log2(table_description.rows_amount)); - typename lpc_type::fri_type::params_type fri_params = - create_fri_params(table_rows_log); + typename lpc_type::fri_type::params_type fri_params( + 1, table_rows_log, lambda, 7, true + ); std::size_t permutation_size = table_description.witness_columns + table_description.public_input_columns + table_description.constant_columns; @@ -372,7 +359,6 @@ using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; @@ -397,8 +383,9 @@ BOOST_FIXTURE_TEST_CASE(placeholder_large_fibonacci_test, placeholder_performanc desc.usable_rows_amount = circuit.usable_rows; std::size_t table_rows_log = std::log2(desc.rows_amount); - typename lpc_type::fri_type::params_type fri_params = - create_fri_params(table_rows_log); + typename lpc_type::fri_type::params_type fri_params( + 1, table_rows_log, placeholder_fibonacci_params::lambda, 7, true + ); typename policy_type::constraint_system_type constraint_system( circuit.gates, circuit.copy_constraints, circuit.lookup_gates); diff --git a/test/systems/plonk/placeholder/placeholder.cpp b/test/systems/plonk/placeholder/placeholder.cpp index f02ac9b2d..ae6b648de 100644 --- a/test/systems/plonk/placeholder/placeholder.cpp +++ b/test/systems/plonk/placeholder/placeholder.cpp @@ -45,13 +45,11 @@ #include #include #include - /* #include #include #include */ - #include #include #include @@ -89,6 +87,7 @@ #include #include #include +#include #include #include "circuits.hpp" @@ -173,26 +172,23 @@ inline std::vector generate_random_step_list(const std::size_t r, c return step_list; } -template -typename fri_type::params_type create_fri_params( - std::size_t degree_log, const int max_step = 1, std::size_t expand_factor = 4) { - std::size_t r = degree_log - 1; +template +typename kzg_type::params_type create_kzg_params(std::size_t degree_log) { + // TODO: what cases t != d? + typename kzg_type::field_type::value_type alpha (7); + std::size_t d = 1 << degree_log; - return typename fri_type::params_type( - (1 << degree_log) - 1, // max_degree - math::calculate_domain_set(degree_log + expand_factor, r), - generate_random_step_list(r, max_step), - expand_factor - ); + typename kzg_type::params_type params(d, d, alpha); + return params; } template -typename kzg_type::params_type create_kzg_params(std::size_t degree_log) { +typename kzg_type::params_type create_kzg_v2_params(std::size_t degree_log) { // TODO: what cases t != d? typename kzg_type::field_type::value_type alpha (7); std::size_t d = 1 << degree_log; - typename kzg_type::params_type params(d, d, alpha); + typename kzg_type::params_type params(d, 1, alpha); return params; } @@ -247,7 +243,7 @@ struct test_initializer { template + std::size_t usable_rows_amount, bool UseGrinding = false, std::size_t max_quotient_poly_chunks = 0> struct placeholder_test_fixture : public test_initializer { using field_type = FieldType; @@ -269,16 +265,14 @@ struct placeholder_test_fixture : public test_initializer { using lpc_params_type = commitments::list_polynomial_commitment_params< merkle_hash_type, transcript_hash_type, - placeholder_test_params::lambda, - placeholder_test_params::m, - UseGrinding + placeholder_test_params::m >; using lpc_type = commitments::list_polynomial_commitment; using lpc_scheme_type = typename commitments::lpc_commitment_scheme; using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; using policy_type = zk::snark::detail::placeholder_policy; - using circuit_type = circuit_description, usable_rows_amount, permutation>; + using circuit_type = circuit_description, usable_rows_amount>; placeholder_test_fixture(const circuit_type& circuit_in, std::size_t usable_rows, std::size_t table_rows) : circuit(circuit_in) @@ -286,7 +280,7 @@ struct placeholder_test_fixture : public test_initializer { , constraint_system(circuit.gates, circuit.copy_constraints, circuit.lookup_gates, circuit.lookup_tables) , assignments(circuit.table) , table_rows_log(std::log2(table_rows)) - , fri_params(create_fri_params(table_rows_log)) + , fri_params(1,table_rows_log, placeholder_test_params::lambda, 4) { desc.rows_amount = table_rows; desc.usable_rows_amount = usable_rows; @@ -296,11 +290,9 @@ struct placeholder_test_fixture : public test_initializer { test_initializer::setup(); lpc_scheme_type lpc_scheme(fri_params); - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; - typename placeholder_public_preprocessor::preprocessed_data_type lpc_preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.move_public_table(), desc, lpc_scheme, columns_with_copy_constraints.size() + constraint_system, assignments.move_public_table(), desc, lpc_scheme, max_quotient_poly_chunks ); typename placeholder_private_preprocessor::preprocessed_data_type @@ -313,7 +305,7 @@ struct placeholder_test_fixture : public test_initializer { ); bool verifier_res = placeholder_verifier::process( - lpc_preprocessed_public_data, lpc_proof, desc, constraint_system, lpc_scheme + lpc_preprocessed_public_data.common_data, lpc_proof, desc, constraint_system, lpc_scheme ); test_initializer::teardown(); return verifier_res; @@ -342,7 +334,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2) constexpr static const std::size_t constant_columns = 0; constexpr static const std::size_t selector_columns = 2; - constexpr static const std::size_t lambda = 1; + constexpr static const std::size_t lambda = 10; constexpr static const std::size_t m = 2; }; using circuit_t_params = placeholder_circuit_params; @@ -357,7 +349,6 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2) using lpc_params_type = commitments::list_polynomial_commitment_params< typename placeholder_test_params::merkle_hash_type, typename placeholder_test_params::transcript_hash_type, - placeholder_test_params::lambda, placeholder_test_params::m >; @@ -390,8 +381,6 @@ BOOST_FIXTURE_TEST_CASE(prover_test, test_initializer){ ); typename policy_type::variable_assignment_type assignments = circuit.table; - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; - bool verifier_res; // Dummy commitment scheme @@ -399,7 +388,7 @@ BOOST_FIXTURE_TEST_CASE(prover_test, test_initializer){ typename placeholder_public_preprocessor::preprocessed_data_type preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.public_table(), desc, commitment_scheme, columns_with_copy_constraints.size() + constraint_system, assignments.public_table(), desc, commitment_scheme ); typename placeholder_private_preprocessor::preprocessed_data_type @@ -412,7 +401,7 @@ BOOST_FIXTURE_TEST_CASE(prover_test, test_initializer){ ); verifier_res = placeholder_verifier::process( - preprocessed_public_data, proof, desc, constraint_system, commitment_scheme + preprocessed_public_data.common_data, proof, desc, constraint_system, commitment_scheme ); BOOST_CHECK(verifier_res); @@ -421,33 +410,35 @@ BOOST_FIXTURE_TEST_CASE(prover_test, test_initializer){ typename placeholder_params_type::public_input_type public_input(1); public_input[0] = {pi0, 0, 1}; verifier_res = placeholder_verifier::process( - preprocessed_public_data, proof, desc, constraint_system, commitment_scheme, public_input + preprocessed_public_data.common_data, proof, desc, constraint_system, commitment_scheme, public_input ); BOOST_CHECK(verifier_res); // Completely correct zeroes after it are not important public_input[0] = {pi0, 0, 1, 0}; verifier_res = placeholder_verifier::process( - preprocessed_public_data, proof, desc, constraint_system, commitment_scheme, public_input + preprocessed_public_data.common_data, proof, desc, constraint_system, commitment_scheme, public_input ); BOOST_CHECK(verifier_res); // Incorrect public input public_input[0] = {pi0, 1}; verifier_res = placeholder_verifier::process( - preprocessed_public_data, proof, desc, constraint_system, commitment_scheme, public_input + preprocessed_public_data.common_data, proof, desc, constraint_system, commitment_scheme, public_input ); BOOST_CHECK(!verifier_res); // LPC commitment scheme - typename lpc_type::fri_type::params_type fri_params = create_fri_params(table_rows_log); + typename lpc_type::fri_type::params_type fri_params( + 1, table_rows_log, placeholder_test_params::lambda, 4 + ); lpc_scheme_type lpc_scheme(fri_params); transcript_type lpc_transcript; // Normally we would use "assignments.move_public_table()" here, but assignments are reused in this test. typename placeholder_public_preprocessor::preprocessed_data_type lpc_preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size() + constraint_system, assignments.public_table(), desc, lpc_scheme ); // Normally we would use "assignments.move_private_table()" here, but assignments are reused in this test. @@ -461,7 +452,7 @@ BOOST_FIXTURE_TEST_CASE(prover_test, test_initializer){ ); verifier_res = placeholder_verifier::process( - lpc_preprocessed_public_data, lpc_proof, desc, constraint_system, lpc_scheme + lpc_preprocessed_public_data.common_data, lpc_proof, desc, constraint_system, lpc_scheme ); BOOST_CHECK(verifier_res); @@ -471,7 +462,7 @@ BOOST_FIXTURE_TEST_CASE(prover_test, test_initializer){ typename placeholder_public_preprocessor::preprocessed_data_type kzg_preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.public_table(), desc, kzg_scheme, columns_with_copy_constraints.size() + constraint_system, assignments.public_table(), desc, kzg_scheme ); typename placeholder_private_preprocessor::preprocessed_data_type @@ -484,7 +475,7 @@ BOOST_FIXTURE_TEST_CASE(prover_test, test_initializer){ ); verifier_res = placeholder_verifier::process( - kzg_preprocessed_public_data, kzg_proof, desc, constraint_system, kzg_scheme + kzg_preprocessed_public_data.common_data, kzg_proof, desc, constraint_system, kzg_scheme ); BOOST_CHECK(verifier_res); } @@ -507,15 +498,13 @@ BOOST_AUTO_TEST_CASE(permutation_polynomials_test) { circuit.lookup_gates); typename policy_type::variable_assignment_type assignments = circuit.table; - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; - - typename lpc_type::fri_type::params_type fri_params = create_fri_params(table_rows_log); + typename lpc_type::fri_type::params_type fri_params(1,table_rows_log, placeholder_test_params::lambda, 4); lpc_scheme_type lpc_scheme(fri_params); transcript_type lpc_transcript; typename placeholder_public_preprocessor::preprocessed_data_type lpc_preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.move_public_table(), desc, lpc_scheme, columns_with_copy_constraints.size() + constraint_system, assignments.move_public_table(), desc, lpc_scheme ); typename placeholder_private_preprocessor::preprocessed_data_type @@ -546,11 +535,12 @@ BOOST_AUTO_TEST_CASE(permutation_polynomials_test) { id_res = field_type::value_type::one(); sigma_res = field_type::value_type::one(); + const auto &permuted_columns = lpc_preprocessed_public_data.common_data.permuted_columns; for (std::size_t i = 0; i < desc.rows_amount; i++) { for (std::size_t j = 0; j < lpc_preprocessed_public_data.identity_polynomials.size(); j++) { id_res = id_res * - (polynomial_table[j].evaluate(domain->get_domain_element(i)) + + (polynomial_table[permuted_columns[j]].evaluate(domain->get_domain_element(i)) + beta * lpc_preprocessed_public_data.identity_polynomials[j].evaluate(domain->get_domain_element(i)) + gamma); } @@ -558,7 +548,7 @@ BOOST_AUTO_TEST_CASE(permutation_polynomials_test) { for (std::size_t j = 0; j < lpc_preprocessed_public_data.permutation_polynomials.size(); j++) { sigma_res = sigma_res * - (polynomial_table[j].evaluate(domain->get_domain_element(i)) + + (polynomial_table[permuted_columns[j]].evaluate(domain->get_domain_element(i)) + beta * lpc_preprocessed_public_data.permutation_polynomials[j].evaluate(domain->get_domain_element(i)) + gamma); } @@ -601,22 +591,19 @@ BOOST_AUTO_TEST_CASE(permutation_argument_test) { std::size_t table_rows_log = std::log2(desc.rows_amount); const std::size_t argument_size = 3; - const std::size_t permutation_size = 4; - auto fri_params = create_fri_params(table_rows_log); + typename lpc_type::fri_type::params_type fri_params(1, table_rows_log, placeholder_test_params::lambda, 4); lpc_scheme_type lpc_scheme(fri_params); typename policy_type::constraint_system_type constraint_system(circuit.gates, circuit.copy_constraints, circuit.lookup_gates); typename policy_type::variable_assignment_type assignments = circuit.table; - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; - transcript_type transcript; typename placeholder_public_preprocessor::preprocessed_data_type preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.move_public_table(), desc, lpc_scheme, permutation_size + constraint_system, assignments.move_public_table(), desc, lpc_scheme ); typename placeholder_private_preprocessor::preprocessed_data_type @@ -637,10 +624,16 @@ BOOST_AUTO_TEST_CASE(permutation_argument_test) { constraint_system, preprocessed_public_data, desc, polynomial_table, lpc_scheme, prover_transcript); // Challenge phase + const auto &permuted_columns = preprocessed_public_data.common_data.permuted_columns; + typename field_type::value_type y = algebra::random_element(); - std::vector f_at_y(permutation_size); - for (std::size_t i = 0; i < permutation_size; i++) { - f_at_y[i] = polynomial_table[i].evaluate(y); + std::vector f_at_y(permuted_columns.size()); + std::vector S_id(permuted_columns.size()); + std::vector S_sigma(permuted_columns.size()); + for (std::size_t i = 0; i < permuted_columns.size(); i++) { + f_at_y[i] = polynomial_table[permuted_columns[i]].evaluate(y); + S_id[i] = preprocessed_public_data.identity_polynomials[i].evaluate(y); + S_sigma[i] = preprocessed_public_data.permutation_polynomials[i].evaluate(y); } auto omega = preprocessed_public_data.common_data.basic_domain->get_domain_element(1); @@ -648,10 +641,19 @@ BOOST_AUTO_TEST_CASE(permutation_argument_test) { typename field_type::value_type v_p_at_y = prover_res.permutation_polynomial_dfs.evaluate(y); typename field_type::value_type v_p_at_y_shifted = prover_res.permutation_polynomial_dfs.evaluate(omega * y); + std::vector special_selector_values(3); + special_selector_values[0] = preprocessed_public_data.common_data.lagrange_0.evaluate(y); + special_selector_values[1] = preprocessed_public_data.q_last.evaluate(y); + special_selector_values[2] = preprocessed_public_data.q_blind.evaluate(y); + + auto permutation_commitment = lpc_scheme.commit(PERMUTATION_BATCH); std::array verifier_res = placeholder_permutation_argument::verify_eval( - preprocessed_public_data, y, f_at_y, v_p_at_y, v_p_at_y_shifted, verifier_transcript + preprocessed_public_data.common_data, + S_id, S_sigma, + special_selector_values, + y, f_at_y, v_p_at_y, v_p_at_y_shifted, {}, verifier_transcript ); typename field_type::value_type verifier_next_challenge = verifier_transcript.template challenge(); @@ -682,15 +684,11 @@ BOOST_AUTO_TEST_CASE(placeholder_gate_argument_test) { desc.usable_rows_amount = circuit.usable_rows; std::size_t table_rows_log = std::log2(desc.rows_amount); - const std::size_t permutation_size = 4; - typename policy_type::constraint_system_type constraint_system( circuit.gates, circuit.copy_constraints, circuit.lookup_gates); typename policy_type::variable_assignment_type assignments = circuit.table; - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; - - auto fri_params = create_fri_params(table_rows_log); + typename lpc_type::fri_type::params_type fri_params(1, table_rows_log, placeholder_test_params::lambda, 4); lpc_scheme_type lpc_scheme(fri_params); std::vector init_blob {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; @@ -698,7 +696,7 @@ BOOST_AUTO_TEST_CASE(placeholder_gate_argument_test) { typename placeholder_public_preprocessor::preprocessed_data_type preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.public_table(), desc, lpc_scheme, permutation_size + constraint_system, assignments.public_table(), desc, lpc_scheme ); typename placeholder_private_preprocessor::preprocessed_data_type @@ -815,9 +813,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit3_lookup_test) using lpc_params_type = commitments::list_polynomial_commitment_params< typename placeholder_test_params::merkle_hash_type, typename placeholder_test_params::transcript_hash_type, - placeholder_test_params::lambda, - placeholder_test_params::m, - true + placeholder_test_params::m >; using lpc_type = commitments::list_polynomial_commitment; @@ -847,14 +843,12 @@ BOOST_AUTO_TEST_CASE(lookup_test) { ); typename policy_type::variable_assignment_type assignments = circuit.table; - auto fri_params = create_fri_params(table_rows_log); + typename lpc_type::fri_type::params_type fri_params(1, table_rows_log, placeholder_test_params::lambda, 4, true); lpc_scheme_type lpc_scheme(fri_params); - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; - typename placeholder_public_preprocessor::preprocessed_data_type preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size()); + constraint_system, assignments.public_table(), desc, lpc_scheme ); typename placeholder_private_preprocessor::preprocessed_data_type preprocessed_private_data = placeholder_private_preprocessor::process( @@ -918,23 +912,29 @@ BOOST_AUTO_TEST_CASE(lookup_test) { lpc_scheme.commit(PERMUTATION_BATCH); lpc_scheme.append_eval_point(PERMUTATION_BATCH, y); - lpc_scheme.append_eval_point(PERMUTATION_BATCH, y * omega); + lpc_scheme.append_eval_point(PERMUTATION_BATCH, preprocessed_public_data.common_data.permutation_parts, y * omega); transcript_type transcript; + lpc_scheme.setup(transcript, preprocessed_public_data.common_data.commitment_scheme_data); auto lpc_proof = lpc_scheme.proof_eval(transcript); // Prepare sorted and V_L values -/* - auto special_selectors = (field_type::value_type::one() - (preprocessed_public_data.q_last.evaluate(y) + - preprocessed_public_data.q_blind.evaluate(y))); - auto half = prover_res.F_dfs[2].evaluate(y) * special_selectors.inversed(); -*/ + std::vector special_selector_values(3); + special_selector_values[0] = preprocessed_public_data.common_data.lagrange_0.evaluate(y); + special_selector_values[1] = preprocessed_public_data.q_last.evaluate(y); + special_selector_values[2] = preprocessed_public_data.q_blind.evaluate(y); + + std::vector special_selector_values_shifted(2); + special_selector_values_shifted[0] = preprocessed_public_data.q_last.evaluate(y * omega); + special_selector_values_shifted[1] = preprocessed_public_data.q_blind.evaluate(y * omega); + placeholder_lookup_argument_verifier lookup_verifier; std::array verifier_res = lookup_verifier.verify_eval( - preprocessed_public_data, - constraint_system.lookup_gates(), - constraint_system.lookup_tables(), + preprocessed_public_data.common_data, + special_selector_values, special_selector_values_shifted, + constraint_system, y, columns_at_y, lpc_proof.z.get(LOOKUP_BATCH), - lpc_proof.z.get(PERMUTATION_BATCH, 0), + lpc_proof.z.get(PERMUTATION_BATCH, preprocessed_public_data.common_data.permutation_parts), + {}, prover_res.lookup_commitment, verifier_transcript ); @@ -945,6 +945,9 @@ BOOST_AUTO_TEST_CASE(lookup_test) { for (int i = 0; i < argument_size; i++) { BOOST_CHECK(prover_res.F_dfs[i].evaluate(y) == verifier_res[i]); + if( prover_res.F_dfs[i].evaluate(y) != verifier_res[i] ){ + std::cout << prover_res.F_dfs[i].evaluate(y) << "!=" << verifier_res[i] << std::endl; + } for (std::size_t j = 0; j < desc.rows_amount; j++) { if(prover_res.F_dfs[i].evaluate(preprocessed_public_data.common_data.basic_domain->get_domain_element(j)) != field_type::value_type::zero()){ std::cout << "!["<< i << "][" << j << "]" << std::endl; @@ -982,9 +985,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit4_lookup_test) using lpc_params_type = commitments::list_polynomial_commitment_params< typename placeholder_test_params::merkle_hash_type, typename placeholder_test_params::transcript_hash_type, - placeholder_test_params::lambda, - placeholder_test_params::m, - true + placeholder_test_params::m >; using lpc_type = commitments::list_polynomial_commitment; @@ -1014,19 +1015,19 @@ BOOST_AUTO_TEST_CASE(lookup_test) { ); typename policy_type::variable_assignment_type assignments = circuit.table; - auto fri_params = create_fri_params(table_rows_log); + typename lpc_type::fri_type::params_type fri_params(1, table_rows_log, placeholder_test_params::lambda, 4); lpc_scheme_type lpc_scheme(fri_params); - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; transcript_type transcript; typename placeholder_public_preprocessor::preprocessed_data_type preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.public_table(), desc, lpc_scheme, columns_with_copy_constraints.size()); + constraint_system, assignments.public_table(), desc, lpc_scheme); typename placeholder_private_preprocessor::preprocessed_data_type preprocessed_private_data = placeholder_private_preprocessor::process( constraint_system, assignments.private_table(), desc); + lpc_scheme.setup(transcript, preprocessed_public_data.common_data.commitment_scheme_data); auto polynomial_table = plonk_polynomial_dfs_table( @@ -1095,13 +1096,23 @@ BOOST_AUTO_TEST_CASE(lookup_test) { preprocessed_public_data.q_blind.evaluate(y))); auto half = prover_res.F_dfs[2].evaluate(y) * special_selectors.inversed(); + std::vector special_selector_values(3); + special_selector_values[0] = preprocessed_public_data.common_data.lagrange_0.evaluate(y); + special_selector_values[1] = preprocessed_public_data.q_last.evaluate(y); + special_selector_values[2] = preprocessed_public_data.q_blind.evaluate(y); + + std::vector special_selector_values_shifted(2); + special_selector_values_shifted[0] = preprocessed_public_data.q_last.evaluate(y * omega); + special_selector_values_shifted[1] = preprocessed_public_data.q_blind.evaluate(y * omega); + placeholder_lookup_argument_verifier verifier; std::array verifier_res = verifier.verify_eval( - preprocessed_public_data, - constraint_system.lookup_gates(), - constraint_system.lookup_tables(), + preprocessed_public_data.common_data, + special_selector_values, special_selector_values_shifted, + constraint_system, y, columns_at_y, lpc_proof.z.get(LOOKUP_BATCH), lpc_proof.z.get(PERMUTATION_BATCH, 0), + {}, prover_res.lookup_commitment, verifier_transcript ); @@ -1132,8 +1143,8 @@ using field_type = typename curve_type::base_field_type; using poseidon_type = hashes::poseidon>; using TestFixtures = boost::mpl::list< - placeholder_test_fixture, - placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_1, public_columns_1, constant_columns_1, selector_columns_1, rows_amount_1, 4> + placeholder_test_fixture, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_1, public_columns_1, constant_columns_1, selector_columns_1, rows_amount_1> >; BOOST_AUTO_TEST_CASE_TEMPLATE(prover_test, F, TestFixtures) { auto circuit = circuit_test_1(test_global_alg_rnd_engine); @@ -1148,7 +1159,7 @@ using field_type = typename algebra::fields::goldilocks64; using poseidon_type = hashes::poseidon>; using TestFixtures = boost::mpl::list< - placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_1, public_columns_1, constant_columns_1, selector_columns_1, rows_amount_1, 4> + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_1, public_columns_1, constant_columns_1, selector_columns_1, rows_amount_1> >; BOOST_AUTO_TEST_CASE_TEMPLATE(prover_test, F, TestFixtures) { auto circuit = circuit_test_1(test_global_alg_rnd_engine); @@ -1163,11 +1174,10 @@ using curve_type = algebra::curves::pallas; using field_type = typename curve_type::base_field_type; using poseidon_type = hashes::poseidon>; const size_t usable_rows_3 = 4; -const size_t permutation_size = 3; using TestFixtures = boost::mpl::list< - placeholder_test_fixture, - placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_3, public_columns_3, constant_columns_3, selector_columns_3, usable_rows_3, permutation_size> + placeholder_test_fixture, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_3, public_columns_3, constant_columns_3, selector_columns_3, usable_rows_3> >; BOOST_AUTO_TEST_CASE_TEMPLATE(prover_test, F, TestFixtures) { auto circuit = circuit_test_3(test_global_alg_rnd_engine); @@ -1182,11 +1192,10 @@ using curve_type = algebra::curves::pallas; using field_type = typename curve_type::base_field_type; using poseidon_type = hashes::poseidon>; const size_t usable_rows_4 = 5; -const size_t permutation_size = 3; using TestFixtures = boost::mpl::list< - placeholder_test_fixture, - placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_4, public_columns_4, constant_columns_4, selector_columns_4, usable_rows_4, permutation_size> + placeholder_test_fixture, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_4, public_columns_4, constant_columns_4, selector_columns_4, usable_rows_4> >; BOOST_AUTO_TEST_CASE_TEMPLATE(prover_test, F, TestFixtures) { auto circuit = circuit_test_4(test_global_alg_rnd_engine); @@ -1195,6 +1204,22 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(prover_test, F, TestFixtures) { } BOOST_AUTO_TEST_SUITE_END() +BOOST_AUTO_TEST_SUITE(placeholder_circuit5) +using curve_type = algebra::curves::pallas; +using field_type = typename curve_type::base_field_type; +using poseidon_type = hashes::poseidon>; + +using TestFixtures = boost::mpl::list< + placeholder_test_fixture, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_5, public_columns_5, constant_columns_5, selector_columns_5, usable_rows_5, false, 10> +>; +BOOST_AUTO_TEST_CASE_TEMPLATE(prover_test, F, TestFixtures) { + auto circuit = circuit_test_5(test_global_alg_rnd_engine); + F fixture(circuit, circuit.usable_rows, circuit.table_rows); + BOOST_CHECK(fixture.run_test()); +} +BOOST_AUTO_TEST_SUITE_END() + BOOST_AUTO_TEST_SUITE(placeholder_circuit6) using curve_type = algebra::curves::pallas; @@ -1202,8 +1227,8 @@ using field_type = typename curve_type::base_field_type; using poseidon_type = hashes::poseidon>; using TestFixtures = boost::mpl::list< - placeholder_test_fixture, - placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_6, public_columns_6, constant_columns_6, selector_columns_6, usable_rows_6, 3, true> + placeholder_test_fixture, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_6, public_columns_6, constant_columns_6, selector_columns_6, usable_rows_6, true> >; BOOST_AUTO_TEST_CASE_TEMPLATE(prover_test, F, TestFixtures) { auto circuit = circuit_test_6(test_global_alg_rnd_engine); @@ -1219,8 +1244,11 @@ using field_type = typename curve_type::base_field_type; using poseidon_type = hashes::poseidon>; using TestFixtures = boost::mpl::list< - placeholder_test_fixture, - placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_7, public_columns_7, constant_columns_7, selector_columns_7, usable_rows_7, 3, true> + placeholder_test_fixture, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_7, public_columns_7, constant_columns_7, selector_columns_7, usable_rows_7, true, 8>, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_7, public_columns_7, constant_columns_7, selector_columns_7, usable_rows_7, true, 10>, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_7, public_columns_7, constant_columns_7, selector_columns_7, usable_rows_7, true, 30>, + placeholder_test_fixture, hashes::keccak_1600<512>, witness_columns_7, public_columns_7, constant_columns_7, selector_columns_7, usable_rows_7, true, 50> >; BOOST_AUTO_TEST_CASE_TEMPLATE(prover_test, F, TestFixtures) { auto circuit = circuit_test_7(test_global_alg_rnd_engine); @@ -1239,7 +1267,7 @@ template< std::size_t ConstantColumns, std::size_t SelectorColumns, std::size_t usable_rows_amount, - std::size_t permutation, + std::size_t permutation, bool UseGrinding = false> struct placeholder_kzg_test_fixture : public test_initializer { using field_type = typename curve_type::scalar_field_type; @@ -1251,9 +1279,6 @@ struct placeholder_kzg_test_fixture : public test_initializer { constexpr static const std::size_t public_input_columns = PublicInputColumns; constexpr static const std::size_t constant_columns = ConstantColumns; constexpr static const std::size_t selector_columns = SelectorColumns; - - constexpr static const std::size_t lambda = 40; - constexpr static const std::size_t m = 2; }; using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; @@ -1269,7 +1294,7 @@ struct placeholder_kzg_test_fixture : public test_initializer { using circuit_type = circuit_description, - usable_rows_amount, permutation>; + usable_rows_amount>; placeholder_kzg_test_fixture() : desc(WitnessColumns, PublicInputColumns, ConstantColumns, SelectorColumns) @@ -1287,8 +1312,6 @@ struct placeholder_kzg_test_fixture : public test_initializer { typename policy_type::constraint_system_type constraint_system(circuit.gates, circuit.copy_constraints, circuit.lookup_gates); typename policy_type::variable_assignment_type assignments = circuit.table; - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; - bool verifier_res; // KZG commitment scheme @@ -1298,21 +1321,21 @@ struct placeholder_kzg_test_fixture : public test_initializer { typename placeholder_public_preprocessor::preprocessed_data_type kzg_preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.public_table(), desc, kzg_scheme, columns_with_copy_constraints.size() - ); + constraint_system, assignments.public_table(), desc, kzg_scheme + ); typename placeholder_private_preprocessor::preprocessed_data_type kzg_preprocessed_private_data = placeholder_private_preprocessor::process( - constraint_system, assignments.private_table(), desc - ); + constraint_system, assignments.private_table(), desc + ); auto kzg_proof = placeholder_prover::process( - kzg_preprocessed_public_data, std::move(kzg_preprocessed_private_data), desc, constraint_system, kzg_scheme - ); + kzg_preprocessed_public_data, std::move(kzg_preprocessed_private_data), desc, constraint_system, kzg_scheme + ); verifier_res = placeholder_verifier::process( - kzg_preprocessed_public_data, kzg_proof, desc, constraint_system, kzg_scheme - ); + kzg_preprocessed_public_data.common_data, kzg_proof, desc, constraint_system, kzg_scheme + ); test_initializer::teardown(); return verifier_res; } @@ -1333,7 +1356,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2_kzg) constant_columns_t, selector_columns_t, usable_rows_t, - permutation_t, true> + true> /* , placeholder_kzg_test_fixture< algebra::curves::alt_bn128_254, @@ -1354,7 +1377,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2_kzg) constant_columns_t, selector_columns_t, usable_rows_t, - permutation_t, true> + true> , placeholder_kzg_test_fixture< algebra::curves::mnt6_298, hashes::keccak_1600<256>, @@ -1364,7 +1387,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2_kzg) constant_columns_t, selector_columns_t, usable_rows_t, - permutation_t, true> + true> /*, -- Not yet implemented placeholder_kzg_test_fixture< algebra::curves::mnt6_298, @@ -1408,9 +1431,6 @@ struct placeholder_kzg_test_fixture_v2 : public test_initializer { constexpr static const std::size_t public_input_columns = PublicInputColumns; constexpr static const std::size_t constant_columns = ConstantColumns; constexpr static const std::size_t selector_columns = SelectorColumns; - - constexpr static const std::size_t lambda = 40; - constexpr static const std::size_t m = 2; }; using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; @@ -1423,10 +1443,10 @@ struct placeholder_kzg_test_fixture_v2 : public test_initializer { using policy_type = zk::snark::detail::placeholder_policy; - using circuit_type = + using circuit_type = circuit_description, - usable_rows_amount, permutation>; + usable_rows_amount>; placeholder_kzg_test_fixture_v2() : desc(WitnessColumns, PublicInputColumns, ConstantColumns, SelectorColumns) @@ -1444,19 +1464,17 @@ struct placeholder_kzg_test_fixture_v2 : public test_initializer { typename policy_type::constraint_system_type constraint_system(circuit.gates, circuit.copy_constraints, circuit.lookup_gates); typename policy_type::variable_assignment_type assignments = circuit.table; - std::vector columns_with_copy_constraints = {0, 1, 2, 3}; - bool verifier_res; // KZG commitment scheme - auto kzg_params = create_kzg_params(table_rows_log); + auto kzg_params = create_kzg_v2_params(table_rows_log); kzg_scheme_type kzg_scheme(kzg_params); typename placeholder_public_preprocessor::preprocessed_data_type kzg_preprocessed_public_data = placeholder_public_preprocessor::process( - constraint_system, assignments.public_table(), desc, kzg_scheme, columns_with_copy_constraints.size() - ); + constraint_system, assignments.public_table(), desc, kzg_scheme + ); typename placeholder_private_preprocessor::preprocessed_data_type kzg_preprocessed_private_data = placeholder_private_preprocessor::process( @@ -1468,7 +1486,7 @@ struct placeholder_kzg_test_fixture_v2 : public test_initializer { ); verifier_res = placeholder_verifier::process( - kzg_preprocessed_public_data, kzg_proof, desc, constraint_system, kzg_scheme + kzg_preprocessed_public_data.common_data, kzg_proof, desc, constraint_system, kzg_scheme ); test_initializer::teardown(); return verifier_res; @@ -1490,9 +1508,8 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2_kzg_v2) constant_columns_t, selector_columns_t, usable_rows_t, - permutation_t, true> - /* - , placeholder_kzg_test_fixture< + true> +/* , placeholder_kzg_test_fixture< algebra::curves::alt_bn128_254, hashes::keccak_1600<256>, hashes::keccak_1600<256>, @@ -1511,7 +1528,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2_kzg_v2) constant_columns_t, selector_columns_t, usable_rows_t, - permutation_t, true> + true> , placeholder_kzg_test_fixture_v2< algebra::curves::mnt6_298, hashes::keccak_1600<256>, @@ -1521,7 +1538,7 @@ BOOST_AUTO_TEST_SUITE(placeholder_circuit2_kzg_v2) constant_columns_t, selector_columns_t, usable_rows_t, - permutation_t, true> + true> /*, -- Not yet implemented placeholder_kzg_test_fixture< algebra::curves::mnt6_298, diff --git a/test/systems/plonk/plonk_constraint.cpp b/test/systems/plonk/plonk_constraint.cpp index 7c9a06620..1e97ee78e 100644 --- a/test/systems/plonk/plonk_constraint.cpp +++ b/test/systems/plonk/plonk_constraint.cpp @@ -41,6 +41,7 @@ #include #include +#include #include #include #include @@ -48,9 +49,6 @@ using namespace nil::crypto3; BOOST_AUTO_TEST_SUITE(plonk_constraint_test_suite) - -BOOST_AUTO_TEST_CASE(plonk_constraint_basic_test) { - // setup using curve_type = algebra::curves::pallas; using FieldType = typename curve_type::base_field_type; @@ -58,7 +56,9 @@ BOOST_AUTO_TEST_CASE(plonk_constraint_basic_test) { using var = zk::snark::plonk_variable; using constraint_type = zk::snark::plonk_constraint; + using copy_constraint_type = zk::snark::plonk_copy_constraint; +BOOST_AUTO_TEST_CASE(plonk_constraint_basic_test) { constraint_type constraint = var(0, 0) + var(1, 0) - var(2, 0); constraint_type constraint1 = var(0, 0) + var(1, 0) - 2; constraint_type constraint2 = 2 - (var(0, 0) + var(1, 0)); @@ -111,4 +111,36 @@ BOOST_AUTO_TEST_CASE(plonk_constraint_basic_test) { BOOST_CHECK((witness_columns[0][0] - witness_columns[0][0]) == constraint9.evaluate(0, assignment)); } +BOOST_AUTO_TEST_CASE(plonk_copy_constraint_constructor_test) { + var w0(0, 0, false, var::column_type::witness); + var w0_1(0, 1, false, var::column_type::witness); + var w1(1, 0, false, var::column_type::witness); + var w1_1(1, 0, false, var::column_type::witness); + var p0(0,0, false, var::column_type::public_input); + var c0(0,0, false, var::column_type::constant); + var s0(0,0, false, var::column_type::selector); + var w(0, 0, true); + +// copy_constraint_type copy_constraint(w0, w0); // Fails with assersion + copy_constraint_type cp0({w0, w0_1}); BOOST_ASSERT(cp0.first == w0 && cp0.second == w0_1); + copy_constraint_type cp1({w0_1, w0}); BOOST_ASSERT(cp1.first == w0 && cp1.second == w0_1); + copy_constraint_type cp2({w0, w1}); BOOST_ASSERT(cp2.first == w0 && cp2.second == w1); + copy_constraint_type cp3({w1, w0}); BOOST_ASSERT(cp3.first == w0 && cp3.second == w1); + copy_constraint_type cp4({w0_1, w1}); BOOST_ASSERT(cp4.first == w0_1 && cp4.second == w1); + copy_constraint_type cp5({w1, w0_1}); BOOST_ASSERT(cp5.first == w0_1 && cp5.second == w1); + copy_constraint_type cp6({w0, p0}); BOOST_ASSERT(cp6.first == w0 && cp6.second == p0); + copy_constraint_type cp7({p0, w0}); BOOST_ASSERT(cp7.first == w0 && cp7.second == p0); + copy_constraint_type cp8({w0, c0}); BOOST_ASSERT(cp8.first == w0 && cp8.second == c0); + copy_constraint_type cp9({c0, w0}); BOOST_ASSERT(cp9.first == w0 && cp9.second == c0); + copy_constraint_type cp10({w0, s0}); BOOST_ASSERT(cp10.first == w0 && cp10.second == s0); + copy_constraint_type cp11({s0, w0}); BOOST_ASSERT(cp11.first == w0 && cp11.second == s0); + copy_constraint_type cp12({p0, c0}); BOOST_ASSERT(cp12.first == p0 && cp12.second == c0); + copy_constraint_type cp13({c0, p0}); BOOST_ASSERT(cp13.first == p0 && cp13.second == c0); + copy_constraint_type cp14({p0, s0}); BOOST_ASSERT(cp14.first == p0 && cp14.second == s0); + copy_constraint_type cp15({s0, p0}); BOOST_ASSERT(cp15.first == p0 && cp15.second == s0); + copy_constraint_type cp16({c0, s0}); BOOST_ASSERT(cp16.first == c0 && cp16.second == s0); + copy_constraint_type cp17({s0, c0}); BOOST_ASSERT(cp17.first == c0 && cp17.second == s0); +// copy_constraint_type cp18({w0, w}); // Fails with assertion +} + BOOST_AUTO_TEST_SUITE_END()