From 6299d18e0f5a5f0e39dbccf195bf737b269eaf7d Mon Sep 17 00:00:00 2001 From: Martun Karapetyan Date: Tue, 25 Feb 2025 18:27:12 +0400 Subject: [PATCH] Implemented dFRI verification. --- .../detail/polynomial/basic_fri.hpp | 556 +++++++++++------- .../crypto3/zk/commitments/polynomial/lpc.hpp | 93 +-- .../plonk/placeholder/dFRI_verifier.hpp | 272 +++++++++ .../plonk/placeholder/gates_argument.hpp | 9 + .../plonk/placeholder/lookup_argument.hpp | 34 +- .../placeholder/permutation_argument.hpp | 16 + .../snark/systems/plonk/placeholder/proof.hpp | 2 +- .../systems/plonk/placeholder/prover.hpp | 76 +-- .../systems/plonk/placeholder/verifier.hpp | 279 ++++++--- crypto3/libs/zk/test/CMakeLists.txt | 1 + .../placeholder/placeholder_circuits_dFRI.cpp | 147 +++++ .../placeholder_dFRI_test_runner.hpp | 233 ++++++++ .../commands/aggregated_fri_proof_command.hpp | 8 +- .../commands/detail/proof_gen.hpp | 16 +- .../gen_consistency_check_command.hpp | 15 +- .../commands/merge_proofs_command.hpp | 1 + 16 files changed, 1348 insertions(+), 410 deletions(-) create mode 100644 crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/dFRI_verifier.hpp create mode 100644 crypto3/libs/zk/test/systems/plonk/placeholder/placeholder_circuits_dFRI.cpp create mode 100644 crypto3/libs/zk/test/systems/plonk/placeholder/placeholder_dFRI_test_runner.hpp diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp index 3439d2397f..0e3de4debe 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp @@ -707,7 +707,7 @@ namespace nil { if (found_it != std::cend(input_s_indices)) { correct_order_idx[i].first = std::distance(std::cbegin(input_s_indices), found_it); } else { - BOOST_ASSERT(false); + throw std::logic_error("Unable to establish the correct order in FRI."); } } @@ -742,6 +742,7 @@ namespace nil { transcript(commit(precommitment)); for (std::size_t step_i = 0; step_i < fri_params.step_list[i]; ++step_i, ++t) { typename FRI::field_type::value_type alpha = transcript.template challenge(); +std::cout << "FRI Proof eval alpha = " << alpha << std::endl; // Calculate next f if constexpr (std::is_same, PolynomialType>::value) { @@ -985,6 +986,7 @@ namespace nil { for (std::size_t query_id = 0; query_id < fri_params.lambda; query_id++) { std::size_t domain_size = fri_params.D[0]->size(); typename FRI::field_type::value_type x = challenges[query_id]; +std::cout << "Prover: challenge x is " << x << std::endl; x = x.pow((FRI::field_type::modulus - 1) / domain_size); std::uint64_t x_index = 0; @@ -1032,10 +1034,10 @@ namespace nil { ++x_index; } - std::map - initial_proof = build_initial_proof( - precommitments, - fri_params, g, g_coeffs, x_index); + std::map initial_proof = + build_initial_proof( + precommitments, + fri_params, g, g_coeffs, x_index); proof.initial_proofs.emplace_back(std::move(initial_proof)); } @@ -1163,232 +1165,386 @@ namespace nil { } template - static bool verify_eval( - const typename FRI::proof_type &proof, - const typename FRI::params_type &fri_params, - const std::map &commitments, - const typename FRI::field_type::value_type theta, - const std::vector>> &poly_ids, - const std::vector &combined_U, - const std::vector> &denominators, + static std::vector generate_alphas( + const std::vector& fri_roots, + const typename FRI::params_type &fri_params, typename FRI::transcript_type &transcript + ) { + std::vector alphas; + std::size_t t = 0; + for (std::size_t i = 0; i < fri_params.step_list.size(); i++) { + transcript(fri_roots[i]); + for (std::size_t step_i = 0; step_i < fri_params.step_list[i]; step_i++, t++) { + auto alpha = transcript.template challenge(); + alphas.push_back(alpha); + } + } + return alphas; + } + + template + static bool verify_initial_proof( + const std::map& initial_proof, + const std::map& commitments, + const std::vector>& correct_order_idx, + std::size_t coset_size + ) { + for (auto const &it: initial_proof) { + auto k = it.first; + if (initial_proof.at(k).p.root() != commitments.at(k)) { + BOOST_LOG_TRIVIAL(info) << "FRI verification failed: Wrong initial proof, commitment does not match."; + return false; + } + + detail::fri_field_element_consumer leaf_data( + coset_size * initial_proof.at(k).values.size()); + + for (std::size_t i = 0; i < initial_proof.at(k).values.size(); i++) { + for (auto [idx, pair_idx] : correct_order_idx) { + leaf_data.consume(initial_proof.at(k).values[i][idx][0]); + leaf_data.consume(initial_proof.at(k).values[i][idx][1]); + } + } + if (!initial_proof.at(k).p.validate(leaf_data)) { + BOOST_LOG_TRIVIAL(info) << "FRI verification failed: Wrong initial proof."; + return false; + } + } + return true; + } + + template + static typename FRI::polynomial_values_type calculate_combined_Q_values( + const std::vector& combined_U, + const std::map& initial_proof, + const std::vector>>& poly_ids, + const std::vector>& s_indices, + const std::vector>& denominators, + const std::vector>& s, + const typename FRI::field_type::value_type& theta, + std::size_t coset_size, + size_t starting_index + ) { + typename FRI::field_type::value_type theta_acc = theta.pow(starting_index); + typename FRI::polynomial_values_type y; + y.resize(coset_size / FRI::m); + + for (size_t j = 0; j < coset_size / FRI::m; j++) { + y[j][0] = FRI::field_type::value_type::zero(); + y[j][1] = FRI::field_type::value_type::zero(); + } + for (std::size_t p = 0; p < poly_ids.size(); p++) { + typename FRI::polynomial_values_type Q; + Q.resize(coset_size / FRI::m); + for (auto const &poly_id: poly_ids[p]) { + for (size_t j = 0; j < coset_size / FRI::m; j++) { + Q[j][0] += initial_proof.at(std::get<0>(poly_id)).values[std::get<1>(poly_id)][j][0] * theta_acc; + Q[j][1] += initial_proof.at(std::get<0>(poly_id)).values[std::get<1>(poly_id)][j][1] * theta_acc; + } + 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][id0]).inversed(); + Q[j][1] *= denominators[p].evaluate(s[j][id1]).inversed(); + y[j][0] += Q[j][0]; + y[j][1] += Q[j][1]; + } + } + return y; + } + + template + static bool check_argument_sizes( + const typename FRI::proof_type& proof, + const typename FRI::params_type &fri_params, + const std::vector& combined_U, + const std::vector>>& poly_ids, + const std::vector>& denominators ) { BOOST_ASSERT(check_step_list(fri_params)); BOOST_ASSERT(combined_U.size() == denominators.size()); BOOST_ASSERT(combined_U.size() == poly_ids.size()); - // TODO: Add size correcness checks. + // TODO: Add size correctness checks. if (proof.final_polynomial.degree() > std::pow(2, std::log2(fri_params.max_degree + 1) - fri_params.r + 1) - 1) { + BOOST_LOG_TRIVIAL(info) << "FRI verification failed: Wrong argument sizes."; return false; } + return true; + } - std::vector alphas; - std::size_t t = 0; - for (std::size_t i = 0; i < fri_params.step_list.size(); i++) { - transcript(proof.fri_roots[i]); - for (std::size_t step_i = 0; step_i < fri_params.step_list[i]; step_i++, t++) { - auto alpha = transcript.template challenge(); - alphas.push_back(alpha); - } + /** + * param[in/out] y - The value of 'y' is modified by this function. Initally it contains the evaluation values of polynomial combined Q. + */ + template + static bool verify_round_proof( + const typename FRI::round_proof_type& round_proof, + typename FRI::polynomial_values_type& y, + const typename FRI::params_type& fri_params, + const std::vector& alphas, + const typename FRI::commitment_type& fri_root, + size_t i, + std::uint64_t& x_index, + std::size_t& domain_size, + std::size_t& t + ) { + size_t coset_size = 1 << fri_params.step_list[i]; + if (round_proof.p.root() != fri_root) { + BOOST_LOG_TRIVIAL(info) << "FRI verification failed: wrong FRI root on round proof " << i << "."; + return false; } - if (fri_params.use_grinding && !FRI::grinding_type::verify( - transcript, proof.proof_of_work, fri_params.grinding_parameter)){ + std::vector> s; + std::vector> s_indices; + std::tie(s, s_indices) = calculate_s(x_index, fri_params.step_list[i], + fri_params.D[t]); + + detail::fri_field_element_consumer leaf_data(coset_size); + 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) { + leaf_data.consume(y[idx][0]); + leaf_data.consume(y[idx][1]); + } + if (!round_proof.p.validate(leaf_data)) { + BOOST_LOG_TRIVIAL(info) << "Wrong round merkle proof on " << i << "-th round"; return false; } - 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]; - 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; - } - } + typename FRI::polynomial_values_type y_next; - std::vector> s; - std::vector> s_indices; - std::tie(s, s_indices) = calculate_s(x_index, fri_params.step_list[0], fri_params.D[0]); - auto correct_order_idx = get_correct_order(x_index, domain_size, fri_params.step_list[0], - s_indices); - - // Check initial proof. - for( auto const &it: query_proof.initial_proof ){ - auto k = it.first; - if (query_proof.initial_proof.at(k).p.root() != commitments.at(k) ) { - return false; - } + // colinear check + for (std::size_t step_i = 0; step_i < fri_params.step_list[i] - 1; step_i++, t++) { + y_next.resize(y.size() / FRI::m); - detail::fri_field_element_consumer leaf_data( - coset_size * query_proof.initial_proof.at(k).values.size()); + domain_size = fri_params.D[t]->size(); + x_index %= domain_size; + typename FRI::field_type::value_type x = fri_params.D[t]->get_domain_element(x_index); - for (std::size_t i = 0; i < query_proof.initial_proof.at(k).values.size(); i++) { - for (auto [idx, pair_idx] : correct_order_idx) { - leaf_data.consume(query_proof.initial_proof.at(k).values[i][idx][0]); - leaf_data.consume(query_proof.initial_proof.at(k).values[i][idx][1]); - } - } - if (!query_proof.initial_proof.at(k).p.validate(leaf_data)) { - BOOST_LOG_TRIVIAL(info) << "Wrong initial proof"; - return false; - } - } + auto [s_next, s_indices_next] = calculate_s( + x_index % fri_params.D[t+1]->size(), + fri_params.step_list[i], fri_params.D[t+1] + ); - // Calculate combinedQ values - typename FRI::field_type::value_type theta_acc = FRI::field_type::value_type::one(); - typename FRI::polynomial_values_type y; - typename FRI::polynomial_values_type combined_eval_values; - y.resize(coset_size / FRI::m); - combined_eval_values.resize(coset_size / FRI::m); - for (size_t j = 0; j < coset_size / FRI::m; j++) { - y[j][0] = FRI::field_type::value_type::zero(); - y[j][1] = FRI::field_type::value_type::zero(); - } - for( std::size_t p = 0; p < poly_ids.size(); p++){ - typename FRI::polynomial_values_type Q; - Q.resize(coset_size / FRI::m); - for( auto const &poly_id: poly_ids[p] ){ - for (size_t j = 0; j < coset_size / FRI::m; j++) { - Q[j][0] += query_proof.initial_proof.at(std::get<0>(poly_id)).values[std::get<1>(poly_id)][j][0] * theta_acc; - Q[j][1] += query_proof.initial_proof.at(std::get<0>(poly_id)).values[std::get<1>(poly_id)][j][1] * theta_acc; - } - 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][id0]).inversed(); - Q[j][1] *= denominators[p].evaluate(s[j][id1]).inversed(); - 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; - for (std::size_t i = 0; i < fri_params.step_list.size(); i++) { - coset_size = 1 << fri_params.step_list[i]; - if (query_proof.round_proofs[i].p.root() != proof.fri_roots[i]) - return false; - - std::tie(s, s_indices) = calculate_s(x_index, fri_params.step_list[i], - fri_params.D[t]); - detail::fri_field_element_consumer leaf_data(coset_size); - 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) { - leaf_data.consume(y[idx][0]); - leaf_data.consume(y[idx][1]); - } - if (!query_proof.round_proofs[i].p.validate(leaf_data)) { - BOOST_LOG_TRIVIAL(info) << "Wrong round merkle proof on " << i << "-th round"; - return false; - } + std::tie(s, s_indices) = calculate_s( + x_index, fri_params.step_list[i], fri_params.D[t]); - // colinear check - for (std::size_t step_i = 0; step_i < fri_params.step_list[i] - 1; step_i++, t++) { - y_next.resize(y.size() / FRI::m); - - 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_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_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_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); - - 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_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); - - 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_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_ch, y[0][0]), - std::make_pair(-s_ch, y[0][1]), + 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_ch, y[2 * y_ind][0]), + std::make_pair(-s_ch, y[2 * y_ind][1]), }; - math::polynomial interpolant_poly = - math::lagrange_interpolation(interpolation_points); - auto interpolant = interpolant_poly.evaluate(alphas[t]); + math::polynomial interpolant_l = + math::lagrange_interpolation(interpolation_points_l); + + 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_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); - 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; - } + new_domain_size /= FRI::m; - // For the last round we check final polynomial nor colinear_check - 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); + 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; + typename FRI::field_type::value_type x = fri_params.D[t]->get_domain_element(x_index); + std::tie(s, s_indices) = calculate_s( + 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_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]); - // Final polynomial check - x_index %= fri_params.D[t]->size(); + std::size_t ind = s_indices[0][ind0] % (fri_params.D[t]->size()/2) < fri_params.D[t]->size() / 4 ? 0 : 1; + if (interpolant != round_proof.y[0][ind]) { + BOOST_LOG_TRIVIAL(info) << "FRI verification failed: interpolant does not match for round proof " << i << "."; + return false; + } + + // For the last round we check final polynomial not colinear_check + y = round_proof.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); - x = x * 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; + } + return true; + } + + template + static bool verify_initial_proof_and_return_combined_Q_values( + const std::map& initial_proof, + const std::vector& combined_U, + const std::vector>>& poly_ids, + const std::vector>& denominators, + const typename FRI::params_type& fri_params, + const std::map& commitments, + const typename FRI::field_type::value_type& theta, + const std::size_t coset_size, + std::size_t domain_size, + size_t starting_index, + typename FRI::transcript_type &transcript, + typename FRI::polynomial_values_type& combined_Q_y_out, + typename FRI::field_type::value_type& x_out, + std::uint64_t& x_index_out + ) { + typename FRI::field_type::value_type x_challenge = transcript.template challenge(); +std::cout << "Verifier: in FRI initial proofs challenge X = " << x_challenge << std::endl; + x_out = x_challenge.pow((FRI::field_type::modulus - 1) / domain_size); + + x_index_out = 0; + for (x_index_out = 0; x_index_out < domain_size; x_index_out++) { + if (fri_params.D[0]->get_domain_element(x_index_out) == x_out) { + break; } - if (y[0][1-ind] != proof.final_polynomial.evaluate(-x)) { + } + + std::vector> s; + std::vector> s_indices; + std::tie(s, s_indices) = calculate_s(x_index_out, fri_params.step_list[0], fri_params.D[0]); + auto correct_order_idx = get_correct_order(x_index_out, domain_size, fri_params.step_list[0], s_indices); + + // Check initial proof. + if (!verify_initial_proof(initial_proof, commitments, correct_order_idx, coset_size)) { + BOOST_LOG_TRIVIAL(info) << "Initial FRI proof/consistency check verification failed."; + return false; + } + + // Calculate combinedQ values + combined_Q_y_out = calculate_combined_Q_values( + combined_U, initial_proof, poly_ids, s_indices, denominators, s, theta, coset_size, starting_index); + + return true; + } + + template + static bool check_final_polynomial( + const math::polynomial& final_polynomial, + typename FRI::polynomial_values_type& y, + const typename FRI::params_type& fri_params, + uint64_t x_index, + size_t t + ) { + x_index %= fri_params.D[t]->size(); + typename FRI::field_type::value_type x = fri_params.D[t]->get_domain_element(x_index); + x = x * 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] != final_polynomial.evaluate(x)) { + BOOST_LOG_TRIVIAL(info) << "FRI verification failed: final polynomial check failed."; + return false; + } + if (y[0][1-ind] != final_polynomial.evaluate(-x)) { + BOOST_LOG_TRIVIAL(info) << "FRI verification failed: final polynomial check failed."; + return false; + } + return true; + } + + template + static bool verify_query_proof( + const typename FRI::query_proof_type &query_proof, + const std::vector& combined_U, + const std::vector>>& poly_ids, + const std::vector>& denominators, + const typename FRI::params_type& fri_params, + const std::map& commitments, + const typename FRI::field_type::value_type& theta, + const std::vector& alphas, + const std::vector& fri_roots, + const math::polynomial& final_polynomial, + const std::size_t coset_size, + std::size_t domain_size, + typename FRI::transcript_type &transcript + ) { + typename FRI::field_type::value_type x; + std::uint64_t x_index; + // Combined Q values + typename FRI::polynomial_values_type y; + + size_t starting_index = 0; + if (!verify_initial_proof_and_return_combined_Q_values( + query_proof.initial_proof, combined_U, poly_ids, denominators, fri_params, commitments, theta, coset_size, domain_size, + starting_index, transcript, y, x, x_index)) { + return false; + } + + // Check round proofs + std::size_t t = 0; + for (std::size_t i = 0; i < fri_params.step_list.size(); i++) { + if (!verify_round_proof(query_proof.round_proofs[i], y, fri_params, + alphas, fri_roots[i], i, x_index, domain_size, t)) + return false; + } + + // Final polynomial check + if (!check_final_polynomial(final_polynomial, y, fri_params, x_index, t)) + return false; + return true; + } + + template + static bool verify_eval( + const typename FRI::proof_type& proof, + const typename FRI::params_type& fri_params, + const std::map& commitments, + const typename FRI::field_type::value_type& theta, + const std::vector>>& poly_ids, + const std::vector& combined_U, + const std::vector>& denominators, + typename FRI::transcript_type &transcript + ) { + if (!check_argument_sizes(proof, fri_params, combined_U, poly_ids, denominators)) + return false; + + std::vector alphas = generate_alphas(proof.fri_roots, fri_params, transcript); +std::cout << "FRI verify_eval generated alpha values " << alphas[0] << std::endl; + + if (fri_params.use_grinding && !FRI::grinding_type::verify( + transcript, proof.proof_of_work, fri_params.grinding_parameter)) { + return false; + } + + std::size_t domain_size = fri_params.D[0]->size(); + std::size_t coset_size = 1 << fri_params.step_list[0]; + + for (std::size_t query_id = 0; query_id < fri_params.lambda; query_id++) { + if (!verify_query_proof(proof.query_proofs[query_id], combined_U, poly_ids, denominators, fri_params, commitments, + theta, alphas, proof.fri_roots, proof.final_polynomial, coset_size, domain_size, transcript)) return false; - } } return true; diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp index 6a2b4a5924..433657c9b0 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp @@ -30,6 +30,8 @@ #ifndef CRYPTO3_ZK_LIST_POLYNOMIAL_COMMITMENT_SCHEME_HPP #define CRYPTO3_ZK_LIST_POLYNOMIAL_COMMITMENT_SCHEME_HPP +#include + #include #include @@ -135,6 +137,11 @@ namespace nil { _fixed_polys_values = preprocessed_data; } + void fill_challenge_queue_for_setup(transcript_type& transcript, std::queue& queue) { + // The value of _etha. + queue.push(transcript.template challenge()); + } + commitment_type commit(std::size_t index) { this->state_commited(index); @@ -194,8 +201,13 @@ namespace nil { challenges from all the other provers. * \returns A pair containing the FRI proof and the vector of size 'lambda' containing the challenges used. */ - std::pair> - proof_eval_FRI_proof(polynomial_type& sum_poly, transcript_type &transcript) { + void proof_eval_FRI_proof( + polynomial_type& sum_poly, + fri_proof_type& fri_proof_out, + std::vector& challenges_out, + typename params_type::grinding_type::output_type& proof_of_work_out, + transcript_type &transcript + ) { // TODO(martun): this function belongs to FRI, not here, probably will move later. // Precommit to sum_poly. @@ -223,22 +235,24 @@ namespace nil { sum_poly_precommitment, _fri_params, transcript); - std::vector challenges = - transcript.template challenges(this->_fri_params.lambda); + // First grinding, then query phase. + proof_of_work_out = nil::crypto3::zk::algorithms::run_grinding( + _fri_params, transcript); - fri_proof_type fri_proof; + challenges_out = transcript.template challenges( + this->_fri_params.lambda); + +std::cout << "LPC Proof eval challenges[0] = " << challenges_out[0] << std::endl; - fri_proof.fri_round_proof = nil::crypto3::zk::algorithms::query_phase_round_proofs< + fri_proof_out.fri_round_proof = nil::crypto3::zk::algorithms::query_phase_round_proofs< fri_type, polynomial_type>( _fri_params, fri_trees, fs, commitments_proof.final_polynomial, - challenges); + challenges_out); - fri_proof.fri_commitments_proof_part = std::move(commitments_proof); - - return {fri_proof, challenges}; + fri_proof_out.fri_commitments_proof_part = std::move(commitments_proof); } typename fri_type::proof_type commit_and_fri_proof( @@ -374,36 +388,37 @@ namespace nil { return theta_power; } - std::size_t get_total_points() { + size_t get_total_points() { auto points = this->get_unique_points(); // List of unique eval points set. [id=>points] - std::size_t total_points = points.size(); + size_t total_points = points.size(); if (std::any_of(_batch_fixed.begin(), _batch_fixed.end(), [](auto i){return i.second != false;})) total_points++; return total_points; } void generate_U_V_polymap( - typename std::vector U, - typename std::vector> V, - typename std::vector>> poly_map, - eval_storage_type z, - value_type theta, - value_type &theta_acc, - size_t starting_index; - ) { + typename std::vector& U, + typename std::vector>& V, + typename std::vector>>& poly_map, + const eval_storage_type& z, + const value_type& theta, + value_type& theta_acc, + size_t total_points) { auto points = this->get_unique_points(); - for (std::size_t p = 0; p < points.size(); p++){ + for (std::size_t p = 0; p < points.size(); p++) { auto &point = points[p]; - V[p+starting_index] = {-point, 1u}; - for(std::size_t i:z.get_batches()){ - for(std::size_t j = 0; j < z.get_batch_size(i); j++){ + V[p] = {-point, 1u}; + for (std::size_t i:z.get_batches()) { + for (std::size_t j = 0; j < z.get_batch_size(i); j++) { auto it = std::find(this->_points[i][j].begin(), this->_points[i][j].end(), point); - if( it == this->_points[i][j].end()) continue; - U[p+starting_index] += this->_z.geat(i, j, it - this->_points[i][j].begin()) * theta_acc; - poly_map[p+starting_index].push_back(std::make_tuple(i, j)); + if (it == this->_points[i][j].end()) + continue; + + U[p] += this->_z.get(i, j, it - this->_points[i][j].begin()) * theta_acc; + poly_map[p].push_back(std::make_tuple(i, j)); theta_acc *= theta; } } @@ -416,8 +431,8 @@ namespace nil { if (!_batch_fixed[i]) continue; for (std::size_t j = 0; j < z.get_batch_size(i); j++) { - U[p+starting_index] += _fixed_polys_values[i][j] * theta_acc; - poly_map[p+starting_index].push_back(std::make_tuple(i, j)); + U[p] += _fixed_polys_values[i][j] * theta_acc; + poly_map[p].push_back(std::make_tuple(i, j)); theta_acc *= theta; } } @@ -429,19 +444,28 @@ namespace nil { const std::map &commitments, transcript_type &transcript ) { + this->_z = proof.z; for (auto const &it: commitments) { transcript(commitments.at(it.first)); } - auto total_points = get_total_points(); + + size_t total_points = get_total_points(); typename std::vector U(total_points); + // V is product of (x - eval_point) polynomial for each eval_point 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(total_points); + value_type theta = transcript.template challenge(); +std::cout << "Theta - first challenge in prover from agg transcript is " << theta << std::endl; + value_type theta_acc = value_type::one(); - generate_U_V_polymap(U, V, poly_map, proof.z, theta, *theta_acc, 0); - if (!nil::crypto3::zk::algorithms::verify_eval( + + generate_U_V_polymap(U, V, poly_map, proof.z, theta, theta_acc, total_points); + + return nil::crypto3::zk::algorithms::verify_eval( proof.fri_proof, _fri_params, commitments, @@ -450,10 +474,7 @@ namespace nil { U, V, transcript - )) { - return false; - } - return true; + ); } // Params for LPC are actually FRI params. We can return some LPC params from here in the future if needed. diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/dFRI_verifier.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/dFRI_verifier.hpp new file mode 100644 index 0000000000..ea15e69db8 --- /dev/null +++ b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/dFRI_verifier.hpp @@ -0,0 +1,272 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2025 Martun Karapetyan +// +// 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_PLONK_PLACEHOLDER_DFRI_VERIFIER_HPP +#define CRYPTO3_ZK_PLONK_PLACEHOLDER_DFRI_VERIFIER_HPP + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace nil { + namespace crypto3 { + namespace zk { + namespace snark { + // Verifier for Distributed FRI aggregated proofs. Will use normal verifier to check parts of proofs. + template + class placeholder_DFRI_verifier { + using value_type = typename FieldType::value_type; + using verifier_type = placeholder_verifier; + using public_input_type = std::vector>; + using transcript_hash_type = typename ParamsType::transcript_hash_type; + using policy_type = detail::placeholder_policy; + using public_preprocessor_type = placeholder_public_preprocessor; + using common_data_type = typename public_preprocessor_type::preprocessed_data_type::common_data_type; + using commitment_scheme_type = typename ParamsType::commitment_scheme_type; + using commitment_type = typename commitment_scheme_type::commitment_type; + using transcript_type = typename commitment_scheme_type::transcript_type; + using fri_type = typename commitment_scheme_type::fri_type; + + public: + + static inline bool process( + const std::vector &common_datas, + const placeholder_aggregated_proof &agg_proof, + const std::vector> &table_descriptions, + const std::vector> &constraint_systems, + std::vector& commitment_schemes, + const std::vector &public_inputs + ) { + const size_t N = agg_proof.partial_proofs.size(); + + // fri params must be the same for all provers. + // TODO: add a check that they are the same!! + auto fri_params = commitment_schemes[0].get_fri_params(); + std::size_t domain_size = fri_params.D[0]->size(); + std::size_t coset_size = 1 << fri_params.step_list[0]; + + std::vector> transcripts(N, std::vector({})); + + std::vector> proofs; + std::vector F_consolidated(N); + // Verify partial proofs. + for (size_t i = 0; i < N; i++) { + // Create a proof from aggregated_proof. + typename placeholder_proof::evaluation_proof eval_proof; + eval_proof.eval_proof.z = agg_proof.aggregated_proof.initial_proofs_per_prover[i].z; + + const auto& initial_fri_proofs = agg_proof.aggregated_proof.initial_proofs_per_prover[i].initial_fri_proofs.initial_proofs; + eval_proof.eval_proof.fri_proof.query_proofs.resize(initial_fri_proofs.size()); + for (size_t j = 0; j < initial_fri_proofs.size(); ++j) { + eval_proof.eval_proof.fri_proof.query_proofs[j].initial_proof = initial_fri_proofs[j]; + } + + proofs.push_back(placeholder_proof(agg_proof.partial_proofs[i], eval_proof)); + + auto transcript_copy = transcripts[i]; + + value_type evaluation_challenge; + std::queue queue; + verifier_type::fill_challenge_queue( + common_datas[i], proofs[i], constraint_systems[i], commitment_schemes[i], transcript_copy, queue, evaluation_challenge); + + // F_consolidated[i] is an out parameter here. + if (!verifier_type::verify_partial_proof( + common_datas[i], proofs[i], table_descriptions[i], constraint_systems[i], commitment_schemes[i], + public_inputs[i], transcripts[i], F_consolidated[i], evaluation_challenge)) + { + BOOST_LOG_TRIVIAL(info) << "dFRI Verification failed: partial proof #" << i << " failed."; + return false; + } + } + + + // Create the commitments for each prover. + std::vector> commitments(N); + for (size_t i = 0; i < N; i++) { + commitments[i] = agg_proof.partial_proofs[i].commitments; + commitments[i][FIXED_VALUES_BATCH] = common_datas[i].commitments.fixed_values; + } + + for (size_t i = 0; i < N; i++) { + commitment_schemes[i]._z = proofs[i].eval_proof.eval_proof.z; + // This is similar to 'eval_polys_and_add_roots_to_transcipt' call in partial proof from prover. + for (auto const &it: commitments[i]) { + transcripts[i](commitments[i].at(it.first)); + } + } + + std::vector starting_indexes(N); + for (size_t i = 1; i < N; i++) { + starting_indexes[i] = starting_indexes[i-1] + commitment_schemes[i-1].compute_theta_power_for_combined_Q(); +std::cout << "starting_index " << i << " = " << starting_indexes[i] << std::endl; + } + + // Create the aggregated challenge point. + transcript_type transcript_for_aggregation; + + for (size_t i = 0; i < N; i++) { + transcript_for_aggregation(transcripts[i].template challenge()); + } + + // produce the aggregated challenge + auto aggregated_challenge = transcript_for_aggregation.template challenge(); +std::cout << "Verifier aggregated_challenge = " << aggregated_challenge << std::endl; + + // This the transcript that our provers will use, it's not the same as 'transcript_for_aggregation', it's the transcript that + // you get after injesting the aggregated challenge. + transcript_type aggregated_transcript; + aggregated_transcript(aggregated_challenge); + + value_type theta = aggregated_transcript.template challenge(); +std::cout << "Theta - first challenge in verifier from agg transcript is " << theta << std::endl; + + const auto& fri_roots = agg_proof.aggregated_proof.fri_proof.fri_commitments_proof_part.fri_roots; + std::vector alphas = nil::crypto3::zk::algorithms::generate_alphas( + fri_roots, fri_params, aggregated_transcript); + + if (fri_params.use_grinding && fri_type::grinding_type::verify( + aggregated_transcript, agg_proof.aggregated_proof.proof_of_work, fri_params.grinding_parameter)) { + BOOST_LOG_TRIVIAL(info) << "dFRI Verification failed: wrong grinding."; + return false; + } + + std::vector> Us(N); + // V is product of (x - eval_point) polynomial for each eval_point + std::vector>> Vs(N); + + // List of involved polynomials for each eval point [batch_id, poly_id, point_id] + std::vector>>> poly_maps(N); + + for (size_t i = 0; i < N; i++) { + size_t total_points = commitment_schemes[i].get_total_points(); + Us[i].resize(total_points); + Vs[i].resize(total_points); + poly_maps[i].resize(total_points); + + value_type theta_acc = theta.pow(starting_indexes[i]); + commitment_schemes[i].generate_U_V_polymap( + Us[i], Vs[i], poly_maps[i], proofs[i].eval_proof.eval_proof.z, theta, theta_acc, total_points); + } + + // Make a separate copy of the aggregated transcript for each prover. + std::vector aggregated_transcripts(N, aggregated_transcript); + + std::vector xs; + std::vector x_indexs; + // Combined Q values + std::vector ys; + + // Verify initial proofs for each prover. This checks the consistency. + // This checks the proofs generated by 'proof_eval_lpc_proof' in prover. + for (size_t i = 0; i < N; i++) { + for (size_t query_id = 0; query_id < fri_params.lambda; query_id++) { + value_type x; + std::uint64_t x_index; + // Combined Q values + typename fri_type::polynomial_values_type y; + +std::cout << "Verifier starting index for " << i << " is " << starting_indexes[i] << std::endl; + + if (!nil::crypto3::zk::algorithms::verify_initial_proof_and_return_combined_Q_values( + agg_proof.aggregated_proof.initial_proofs_per_prover[i].initial_fri_proofs.initial_proofs[query_id], Us[i], poly_maps[i], Vs[i], + fri_params, commitments[i], theta, coset_size, domain_size, starting_indexes[i], aggregated_transcripts[i], y, x, x_index + )) { + BOOST_LOG_TRIVIAL(info) << "dFRI Verification failed: initial FRI proof/consistency check verification failed for prover #" << i << "."; + return false; + } + // for all the provers the values of x and x_index must match, since we're using the same transcript for each prover. + if (i == 0) { + xs.push_back(x); + x_indexs.push_back(x_index); + ys.push_back(y); + } else { + if (x != xs[query_id]) { + BOOST_LOG_TRIVIAL(info) << "dFRI Verification failed: initial FRI proof/consistency check verification failed for prover #" << i + << " with challenge x mismatch."; + return false; + } + if (x_index != x_indexs[query_id]) { + BOOST_LOG_TRIVIAL(info) << "dFRI Verification failed: initial FRI proof/consistency check verification failed for prover #" << i + << " with challenge x_index mismatch."; + return false; + } + if (y.size() != ys[query_id].size()) { + BOOST_LOG_TRIVIAL(info) << "dFRI Verification failed: initial FRI proof/consistency check verification failed for prover #" << i + << " with mismatch in size of Y."; + return false; + } + // for y we need to sum up, since FRI was ran on the sum of polynomials combined Q. + for (size_t j = 0; j < y.size(); ++j) { + for (size_t k = 0; k < y[j].size(); ++k) + ys[query_id][j][k] += y[j][k]; + } + } + } + } + +std::cout << "dFRI verifier: alphas[0] = " << alphas[0] << std::endl; + + // Now run the round proofs once for the summed polynomial combined_Q. + for (size_t query_id = 0; query_id < fri_params.lambda; query_id++) { + size_t t = 0; + // Domain size changes during checks of 'verify_round_proof'. + size_t domain_size_for_rounds = domain_size; + for (size_t i = 0; i < fri_params.step_list.size(); i++) { + if (!nil::crypto3::zk::algorithms::verify_round_proof( + agg_proof.aggregated_proof.fri_proof.fri_round_proof.round_proofs[query_id][i], ys[query_id], fri_params, + alphas, fri_roots[i], i, x_indexs[query_id], domain_size_for_rounds, t)) { + BOOST_LOG_TRIVIAL(info) << "dFRI Verification failed: final FRI proof round proof failed for query " + << query_id << " and step " << i << "."; + return false; + } + } + + if (!nil::crypto3::zk::algorithms::check_final_polynomial( + agg_proof.aggregated_proof.fri_proof.fri_commitments_proof_part.final_polynomial, ys[query_id], fri_params, + x_indexs[query_id], t)) { + BOOST_LOG_TRIVIAL(info) << "dFRI Verification failed: final polynomial check failed."; + return false; + } + } + + return true; + } + }; + } // namespace snark + } // namespace zk + } // namespace crypto3 +} // namespace nil + +#endif // CRYPTO3_ZK_PLONK_PLACEHOLDER_DFRI_VERIFIER_HPP diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/gates_argument.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/gates_argument.hpp index a9b3eae39b..096d3dc85c 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/gates_argument.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/gates_argument.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -245,6 +246,14 @@ namespace nil { return F; } + + static inline void fill_challenge_queue( + transcript_type &transcript, + std::queue& queue) { + // Theta + queue.push(transcript.template challenge()); + } + }; } // namespace snark } // namespace zk diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/lookup_argument.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/lookup_argument.hpp index f54e6c23c2..96b77cc325 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/lookup_argument.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/lookup_argument.hpp @@ -32,6 +32,7 @@ #define CRYPTO3_ZK_PLONK_PLACEHOLDER_LOOKUP_ARGUMENT_HPP #include +#include #include #include @@ -504,14 +505,43 @@ namespace nil { typedef detail::placeholder_policy policy_type; public: + + void fill_challenge_queue( + const typename placeholder_public_preprocessor::preprocessed_data_type::common_data_type &common_data, + const plonk_constraint_system &constraint_system, + // sorted_batch_values. Pair value/shifted_value + const std::vector> &sorted, + // Commitment + const typename CommitmentSchemeTypePermutation::commitment_type &lookup_commitment, + transcript_type &transcript, + std::queue& queue + ) { + // Theta. + queue.push(transcript.template challenge()); + + transcript(lookup_commitment); + + // Beta and Gamma. + queue.push(transcript.template challenge()); + queue.push(transcript.template challenge()); + + auto parts = constraint_system.lookup_parts(common_data.max_quotient_chunks); + for (size_t i = 0; i < parts.size() - 1; i++) { + queue.push(transcript.template challenge()); + } + for (size_t i = 1; i < sorted.size(); i++) { + // alpha + queue.push(transcript.template challenge()); + } + } + /** * \param[in] challenge - The value of random challenge point 'Y'. * \param[in] evaluations - A map containing evaluations of all the required variables and rotations, I.E. values of all the columns at points 'Y' and 'Y*omega' and other points depending on the rotations used. * \param[in] counts - A vector containing the evaluation of polynomails "counts" at point 'T' for each lookup value. Each polynomial 'counts' shows the number of times each value appears in the lookup inputs. - * \returns Nullopt if the verification has failed, or a list of lookup argument values that are used as a part of - * the final zero-check pprotocol. + * \returns A list of lookup argument values that are used as a part of the final zero-check pprotocol. */ std::array verify_eval( const typename placeholder_public_preprocessor::preprocessed_data_type::common_data_type &common_data, diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/permutation_argument.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/permutation_argument.hpp index a5b8a33163..18c270d428 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/permutation_argument.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/permutation_argument.hpp @@ -28,6 +28,7 @@ #define CRYPTO3_ZK_PLONK_PLACEHOLDER_PERMUTATION_ARGUMENT_HPP #include +#include #include #include @@ -230,6 +231,21 @@ namespace nil { return res; } + static inline void fill_challenge_queue( + const typename placeholder_public_preprocessor::preprocessed_data_type::common_data_type + &common_data, + transcript_type &transcript, + std::queue& queue + ) { + // Beta and Gamma + queue.push(transcript.template challenge()); + queue.push(transcript.template challenge()); + + for (std::size_t i = 0; i < common_data.permutation_parts - 1; i++) { + queue.push(transcript.template challenge()); + } + } + static inline std::array verify_eval( const typename placeholder_public_preprocessor::preprocessed_data_type::common_data_type &common_data, diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp index 96ad8f1fa3..b12023755d 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp @@ -92,7 +92,7 @@ namespace nil { using partial_proof_type = placeholder_partial_proof; struct evaluation_proof { - // TODO: remove it! + // TODO: We don't use this any more, remove it! It's not being set, just delete it, and remove from marshalling. typename FieldType::value_type challenge; typename commitment_scheme_type::proof_type eval_proof; diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp index b557824aaa..0d6cb61300 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp @@ -209,8 +209,9 @@ namespace nil { transcript(_proof.commitments[QUOTIENT_BATCH]); // 8. Run evaluation proofs - _proof.eval_proof.challenge = transcript.template challenge(); - generate_evaluation_points(); + typename FieldType::value_type evaluation_challenge = transcript.template challenge(); +std::cout << "Evaluation challenge in prover is " << evaluation_challenge << std::endl; + generate_evaluation_points(evaluation_challenge); if (!_skip_commitment_scheme_eval_proofs) { _proof.eval_proof.eval_proof = _commitment_scheme.proof_eval(transcript); @@ -360,7 +361,7 @@ namespace nil { } } - void generate_evaluation_points() { + void generate_evaluation_points(const typename FieldType::value_type& evaluation_challenge) { PROFILE_SCOPE("evaluation_points_generated_time"); _omega = preprocessed_public_data.common_data->basic_domain->get_domain_element(1); @@ -382,26 +383,26 @@ namespace nil { _commitment_scheme.append_eval_point( VARIABLE_VALUES_BATCH, variable_values_index, - _proof.eval_proof.challenge * _omega.pow(rotation) + evaluation_challenge * _omega.pow(rotation) ); } } 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, evaluation_challenge); } if (constraint_system.copy_constraints().size() > 0) - _commitment_scheme.append_eval_point(PERMUTATION_BATCH, 0, _proof.eval_proof.challenge * _omega); + _commitment_scheme.append_eval_point(PERMUTATION_BATCH, 0, evaluation_challenge * _omega); if (_is_lookup_enabled) { // For polynomail U, we need the shifted value as well. _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); + evaluation_challenge * _omega); + _commitment_scheme.append_eval_point(LOOKUP_BATCH, evaluation_challenge); } - _commitment_scheme.append_eval_point(QUOTIENT_BATCH, _proof.eval_proof.challenge); + _commitment_scheme.append_eval_point(QUOTIENT_BATCH, evaluation_challenge); // fixed values' rotations (table columns) std::size_t i = 0; @@ -409,12 +410,12 @@ namespace nil { preprocessed_public_data.permutation_polynomials.size() + 2; for (i = 0; i < start_index; i++) { - _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, i, _proof.eval_proof.challenge); + _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, i, evaluation_challenge); } // For special selectors - _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, start_index - 2, _proof.eval_proof.challenge * _omega); - _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, start_index - 1, _proof.eval_proof.challenge * _omega); + _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, start_index - 2, evaluation_challenge * _omega); + _commitment_scheme.append_eval_point(FIXED_VALUES_BATCH, start_index - 1, evaluation_challenge * _omega); for (std::size_t ind = 0; ind < constant_columns + preprocessed_public_data.public_polynomial_table->selectors().size(); @@ -427,57 +428,15 @@ namespace nil { _commitment_scheme.append_eval_point( FIXED_VALUES_BATCH, start_index + ind, - _proof.eval_proof.challenge * _omega.pow(rotation) + evaluation_challenge * _omega.pow(rotation) ); } } } - std::vector> compute_evaluation_points_public() { - std::vector> evaluation_points_public( - preprocessed_public_data.identity_polynomials.size() + - preprocessed_public_data.permutation_polynomials.size(), - _challenge_point); - - 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; - - for (std::size_t k = 0, rotation_index = witness_columns + public_input_columns; - k < constant_columns; k++, rotation_index++) { - - const std::set& rotations = - preprocessed_public_data.common_data->columns_rotations[rotation_index]; - std::vector point; - point.reserve(rotations.size()); - - for (int rotation: rotations) { - // TODO: Maybe precompute values of _omega.pow(rotation)??? Rotation can be -1, causing computation - // of inverse element multiple times. - point.push_back( _proof.eval_proof.challenge * _omega.pow(rotation)); - } - evaluation_points_public.push_back(std::move(point)); - } - - for (std::size_t k = 0, rotation_index = witness_columns + public_input_columns + constant_columns; - k < preprocessed_public_data.public_polynomial_table.selectors().size(); - k++, rotation_index++) { - - const std::set& rotations = - preprocessed_public_data.common_data->columns_rotations[rotation_index]; - std::vector point; - point.reserve(rotations.size()); - - for (int rotation: rotations) { - point.push_back( _proof.eval_proof.challenge * _omega.pow(rotation)); - } - evaluation_points_public.push_back(std::move(point)); - } - - evaluation_points_public.push_back(_challenge_point); - - return evaluation_points_public; - } + public: + // Transcript is used from the outside to generate an aggregated challenge for dFRI. + transcript::fiat_shamir_heuristic_sequential transcript; private: // Structures passed from outside by reference. @@ -489,7 +448,6 @@ namespace nil { std::unique_ptr> _polynomial_table; placeholder_proof _proof; std::array _F_dfs; - transcript::fiat_shamir_heuristic_sequential transcript; bool _is_lookup_enabled; typename FieldType::value_type _omega; std::vector _challenge_point; diff --git a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/verifier.hpp b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/verifier.hpp index 996e43a963..42af59eebc 100644 --- a/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/verifier.hpp +++ b/crypto3/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/verifier.hpp @@ -29,6 +29,7 @@ #define CRYPTO3_ZK_PLONK_PLACEHOLDER_VERIFIER_HPP #include +#include #include @@ -54,6 +55,7 @@ namespace nil { using policy_type = detail::placeholder_policy; using public_preprocessor_type = placeholder_public_preprocessor; + using proof_type = placeholder_proof; using commitment_scheme_type = typename ParamsType::commitment_scheme_type; using commitment_type = typename commitment_scheme_type::commitment_type; using eval_storage_type = commitments::eval_storage; @@ -72,7 +74,7 @@ namespace nil { 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, + const typename FieldType::value_type& challenge, bool _is_lookup_enabled ) { PROFILE_SCOPE("evaluation_points_generated_time"); @@ -147,43 +149,35 @@ namespace nil { static inline bool process( const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, - const placeholder_proof &proof, + const proof_type &proof, const plonk_table_description &table_description, const plonk_constraint_system &constraint_system, commitment_scheme_type& commitment_scheme, const std::vector> &public_input - ){ - // TODO: process rotations for public input. - auto omega = common_data.basic_domain->get_domain_element(1); - auto challenge = proof.eval_proof.challenge; - auto numerator = challenge.pow(table_description.rows_amount) - FieldType::value_type::one(); - numerator *= typename FieldType::value_type(table_description.rows_amount).inversed(); + ) { + transcript::fiat_shamir_heuristic_sequential transcript(std::vector({})); + typename FieldType::value_type F_consolidated; - // 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) { - BOOST_LOG_TRIVIAL(info) << "Verification failed because: If public input sizes are set, all of them should be set."; + typename FieldType::value_type evaluation_challenge; + std::queue queue; + fill_challenge_queue(common_data, proof, constraint_system, commitment_scheme, transcript, queue, evaluation_challenge); + + if (!verify_partial_proof( + common_data, proof, table_description, constraint_system, + commitment_scheme, public_input, transcript, F_consolidated, evaluation_challenge)) + { + BOOST_LOG_TRIVIAL(info) << "Verification failed: partial proof failed."; return false; } - for (std::size_t i = 0; i < public_input.size(); ++i) { - typename FieldType::value_type value = FieldType::value_type::zero(); - std::size_t max_size = public_input[i].size(); - if (constraint_system.public_input_sizes_num() != 0) - max_size = std::min(max_size, constraint_system.public_input_size(i)); - auto omega_pow = FieldType::value_type::one(); - for( std::size_t j = 0; j < max_size; ++j ){ - value += (public_input[i][j] * omega_pow) * (challenge - omega_pow).inversed(); - omega_pow = omega_pow * omega; - } - value *= numerator; - if (value != proof.eval_proof.eval_proof.z.get(VARIABLE_VALUES_BATCH, table_description.witness_columns + i, 0) ) - { - BOOST_LOG_TRIVIAL(info) << "Verification failed because: evaluation proof failed."; - return false; - } + std::map commitments = proof.commitments; + commitments[FIXED_VALUES_BATCH] = common_data.commitments.fixed_values; + + if (!commitment_scheme.verify_eval(proof.eval_proof.eval_proof, commitments, transcript)) { + BOOST_LOG_TRIVIAL(info) << "Verification failed: LPC proof failed."; + return false; } - return process(common_data, proof, table_description, constraint_system, commitment_scheme); + return true; } // Takes out values of different polynomials at challenge point 'Y' from the evaluation proofs. @@ -235,27 +229,37 @@ namespace nil { static inline bool process( const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, - const placeholder_proof &proof, + const proof_type &proof, const plonk_table_description &table_description, const plonk_constraint_system &constraint_system, commitment_scheme_type& commitment_scheme ) { auto& Z = proof.eval_proof.eval_proof.z; transcript::fiat_shamir_heuristic_sequential transcript(std::vector({})); - if (!verify_partial_proof(*common_data, *proof, *table_description, *constraint_system, *commitment_scheme, *public_input, *transcript)) + typename FieldType::value_type F_consolidated; + + auto transcript_copy = transcript; + + typename FieldType::value_type evaluation_challenge; + std::queue queue; + fill_challenge_queue(common_data, proof, constraint_system, commitment_scheme, transcript_copy, queue, evaluation_challenge); + + // TODO(martun): remove all usage of transcript from the verification code. We already have all the challenges in a queue. + // Not doing it now to have a smaller PR. + if (!verify_partial_proof( + common_data, proof, table_description, constraint_system, + commitment_scheme, transcript, F_consolidated, evaluation_challenge)) { - BOOST_LOG_TRIVIAL(info) << "Verification failed because: partial proof failed."; + BOOST_LOG_TRIVIAL(info) << "Verification failed: partial proof failed."; return false; } - _prepare_polynomials( - *proof, - *common_data, - *constraint_system, - *commitment_scheme); - if (!verify_lpc_proof(proof, commitment_scheme, transcript)) - { - BOOST_LOG_TRIVIAL(info) << "Verification failed because: LPC proof failed."; - return false; + + std::map commitments = proof.commitments; + commitments[FIXED_VALUES_BATCH] = common_data.commitments.fixed_values; + + if (!commitment_scheme.verify_eval(proof.eval_proof.eval_proof, commitments, transcript)) { + BOOST_LOG_TRIVIAL(info) << "Verification failed: LPC proof failed."; + return false; } return true; } @@ -263,44 +267,127 @@ namespace nil { static inline bool verify_partial_proof( const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, - const placeholder_proof &proof, + const proof_type &proof, const plonk_table_description &table_description, const plonk_constraint_system &constraint_system, commitment_scheme_type& commitment_scheme, - const std::vector> &public_input - transcript_type &transcript + const std::vector> &public_input, + transcript_type &transcript, + typename FieldType::value_type& F_consolidated_out, + const typename FieldType::value_type& evaluation_challenge ) { // TODO: process rotations for public input. - auto omega = common_data.basic_domain->get_domain_element(1); - auto challenge = proof.eval_proof.challenge; - auto numerator = challenge.pow(table_description.rows_amount) - FieldType::value_type::one(); - numerator *= typename FieldType::value_type(table_description.rows_amount).inversed(); - // 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) { - BOOST_LOG_TRIVIAL(info) << "Verification failed because: If public input sizes are set, all of them should be set."; + BOOST_LOG_TRIVIAL(info) << "Verification failed: If public input sizes are set, all of them should be set."; return false; } - for (std::size_t i = 0; i < public_input.size(); ++i) { + if (!verify_partial_proof( + common_data, proof, table_description, constraint_system, + commitment_scheme, transcript, F_consolidated_out, evaluation_challenge)) + return false; + + auto omega = common_data.basic_domain->get_domain_element(1); + auto numerator = evaluation_challenge.pow(table_description.rows_amount) - FieldType::value_type::one(); + numerator *= typename FieldType::value_type(table_description.rows_amount).inversed(); + + for (size_t i = 0; i < public_input.size(); ++i) { typename FieldType::value_type value = FieldType::value_type::zero(); std::size_t max_size = public_input[i].size(); if (constraint_system.public_input_sizes_num() != 0) max_size = std::min(max_size, constraint_system.public_input_size(i)); auto omega_pow = FieldType::value_type::one(); - for( std::size_t j = 0; j < max_size; ++j ){ - value += (public_input[i][j] * omega_pow) * (challenge - omega_pow).inversed(); - omega_pow = omega_pow * omega; + for (size_t j = 0; j < max_size; ++j) { + value += (public_input[i][j] * omega_pow) * (evaluation_challenge - omega_pow).inversed(); + omega_pow *= omega; } value *= numerator; - if (value != proof.eval_proof.eval_proof.z.get(VARIABLE_VALUES_BATCH, table_description.witness_columns + i, 0) ) + if (value != proof.eval_proof.eval_proof.z.get(VARIABLE_VALUES_BATCH, table_description.witness_columns + i, 0)) { - BOOST_LOG_TRIVIAL(info) << "Verification failed because: evaluation proof failed."; + BOOST_LOG_TRIVIAL(info) << "Verification failed: evaluation proof failed."; return false; } } + return true; + } + + /** Generates the queue containing all the challenges which will be required for evaluation. Separately returns evaluation + * point challenge for convenience. + */ + static inline void fill_challenge_queue( + const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, + const proof_type &proof, + const plonk_constraint_system &constraint_system, + commitment_scheme_type& commitment_scheme, + transcript_type &transcript, + std::queue& queue, + typename FieldType::value_type& evaluation_challenge_out + ) { + 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.fill_challenge_queue_for_setup(transcript, queue); + + // 3. append witness commitments to transcript + transcript(proof.commitments.at(VARIABLE_VALUES_BATCH)); + + if (constraint_system.copy_constraints().size() > 0) { + placeholder_permutation_argument::fill_challenge_queue(common_data, transcript, queue); + } + // 6. lookup argument + bool is_lookup_enabled = (constraint_system.lookup_gates().size() > 0); + if (is_lookup_enabled) { + placeholder_lookup_argument_verifier lookup_argument_verifier; + lookup_argument_verifier.fill_challenge_queue( + common_data, + constraint_system, + proof.eval_proof.eval_proof.z.get(LOOKUP_BATCH), + proof.commitments.at(LOOKUP_BATCH), + transcript, queue); + } + if (constraint_system.copy_constraints().size() > 0 || constraint_system.lookup_gates().size() > 0) { + transcript(proof.commitments.at(PERMUTATION_BATCH)); + } + + // 7. gate argument + placeholder_gates_argument::fill_challenge_queue( + transcript, queue + ); + + std::array alphas = + transcript.template challenges(); + for (auto& a: alphas) { + queue.push(a); + } + + // 9. IOP checks + transcript(proof.commitments.at(QUOTIENT_BATCH)); + + evaluation_challenge_out = transcript.template challenge(); + queue.push(evaluation_challenge_out); + } + + /** Even though this function accepts the full proof, it does only partial verifications. + * FRI proof and evaluation proofs will be checked separately. + * \param[out] F_consolidated_out - F Consolidated polynomial output argument, will be used to check + * evaluation proofs in a given challenge point later. + * \param[in] evaluation_challenge - The last challenge used by partial proof, the evaluation point challenge. + * \returns true if partial proof passes, false otherwise. + */ + static inline bool verify_partial_proof( + const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, + const proof_type &proof, + const plonk_table_description &table_description, + const plonk_constraint_system &constraint_system, + commitment_scheme_type& commitment_scheme, + transcript_type &transcript, + typename FieldType::value_type& F_consolidated_out, + const typename FieldType::value_type& evaluation_challenge + ) { // We cannot add eval points unless everything is committed, so when verifying assume it's committed. commitment_scheme.state_commited(FIXED_VALUES_BATCH); commitment_scheme.state_commited(VARIABLE_VALUES_BATCH); @@ -326,7 +413,7 @@ namespace nil { 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[0] = common_data.lagrange_0.evaluate(evaluation_challenge); special_selector_values[1] = Z.get( FIXED_VALUES_BATCH, 2*common_data.permuted_columns.size(), 0); special_selector_values[2] = Z.get( @@ -371,7 +458,7 @@ namespace nil { placeholder_permutation_argument::verify_eval( common_data, S_id, S_sigma, special_selector_values, - proof.eval_proof.challenge, f, + evaluation_challenge, f, Z.get(PERMUTATION_BATCH, 0, 0), Z.get(PERMUTATION_BATCH, 0, 1), perm_partitions, @@ -464,14 +551,15 @@ namespace nil { PLONK_SPECIAL_SELECTOR_ALL_NON_FIRST_USABLE_ROWS_SELECTED, 0, plonk_variable::column_type::selector ); - columns_at_y[key] = mask_value - common_data.lagrange_0.evaluate(proof.eval_proof.challenge); + columns_at_y[key] = mask_value - common_data.lagrange_0.evaluate(evaluation_challenge); } { auto key = std::make_tuple( PLONK_SPECIAL_SELECTOR_ALL_NON_FIRST_USABLE_ROWS_SELECTED, 1, plonk_variable::column_type::selector ); - columns_at_y[key] = shifted_mask_value - common_data.lagrange_0.evaluate(proof.eval_proof.challenge * common_data.basic_domain->get_domain_element(1)); + columns_at_y[key] = shifted_mask_value - common_data.lagrange_0.evaluate( + evaluation_challenge * common_data.basic_domain->get_domain_element(1)); } // 6. lookup argument @@ -492,7 +580,7 @@ namespace nil { common_data, special_selector_values, constraint_system, - proof.eval_proof.challenge, + evaluation_challenge, columns_at_y, counts, U_value, @@ -510,7 +598,7 @@ namespace nil { // 7. gate argument std::array gate_argument = placeholder_gates_argument::verify_eval( - constraint_system.gates(), columns_at_y, proof.eval_proof.challenge, + constraint_system.gates(), columns_at_y, evaluation_challenge, mask_value, transcript ); @@ -521,9 +609,10 @@ namespace nil { // 9. IOP checks transcript(proof.commitments.at(QUOTIENT_BATCH)); - auto challenge = transcript.template challenge(); - BOOST_ASSERT(challenge == proof.eval_proof.challenge); + if (evaluation_challenge != transcript.template challenge()) + return false; +<<<<<<< HEAD commitment_scheme.set_batch_size(VARIABLE_VALUES_BATCH, Z.get_batch_size(VARIABLE_VALUES_BATCH)); commitment_scheme.set_batch_size(FIXED_VALUES_BATCH, @@ -551,17 +640,35 @@ namespace nil { } // 10. final check +======= +std::cout << "Evaluation challenge in verifier is " << evaluation_challenge << std::endl; +>>>>>>> 168226f4e (Implemented dFRI verification.) F[3] = lookup_argument[0]; F[4] = lookup_argument[1]; F[5] = lookup_argument[2]; F[6] = lookup_argument[3]; F[7] = gate_argument[0]; - typename FieldType::value_type F_consolidated = FieldType::value_type::zero(); + F_consolidated_out = FieldType::value_type::zero(); for (std::size_t i = 0; i < f_parts; i++) { - F_consolidated += alphas[i] * F[i]; + F_consolidated_out += alphas[i] * F[i]; } + prepare_polynomials(proof.eval_proof, common_data, table_description, constraint_system, commitment_scheme, evaluation_challenge); + + if (!verify_consolidated_polynomial(common_data, proof, F_consolidated_out, evaluation_challenge)) + return false; + + return true; + } + + static inline bool verify_consolidated_polynomial( + const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, + const proof_type &proof, + const typename FieldType::value_type& F_consolidated, + const typename FieldType::value_type& challenge) + { + typename FieldType::value_type T_consolidated = FieldType::value_type::zero(); for (std::size_t i = 0; i < Z.get_batch_size(QUOTIENT_BATCH); i++) { T_consolidated += Z.get(QUOTIENT_BATCH, i, 0) * @@ -571,52 +678,42 @@ namespace nil { // Z is polynomial -1, 0 ...., 0, 1 typename FieldType::value_type Z_at_challenge = common_data.Z.evaluate(challenge); if (F_consolidated != Z_at_challenge * T_consolidated) { - BOOST_LOG_TRIVIAL(info) << "Verification failed because: F consolidated polynomial does not match."; + BOOST_LOG_TRIVIAL(info) << "Verification failed: F consolidated polynomial mismatch."; return false; } - return true; + return true; } + // maybe rename this to something like prepare_batches_and_eval_points? static inline void prepare_polynomials( - const placeholder_proof &proof, - const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, - const plonk_constraint_system &constraint_system, - commitment_scheme_type &commitment_scheme) { + const typename proof_type::evaluation_proof &eval_proof, + const typename public_preprocessor_type::preprocessed_data_type::common_data_type &common_data, + const plonk_table_description &table_description, + const plonk_constraint_system &constraint_system, + commitment_scheme_type &commitment_scheme, + const typename FieldType::value_type& evaluation_challenge) { commitment_scheme.set_batch_size(VARIABLE_VALUES_BATCH, - proof.eval_proof.eval_proof.z.get_batch_size(VARIABLE_VALUES_BATCH)); + eval_proof.eval_proof.z.get_batch_size(VARIABLE_VALUES_BATCH)); commitment_scheme.set_batch_size(FIXED_VALUES_BATCH, - proof.eval_proof.eval_proof.z.get_batch_size(FIXED_VALUES_BATCH)); + eval_proof.eval_proof.z.get_batch_size(FIXED_VALUES_BATCH)); bool is_lookup_enabled = (constraint_system.lookup_gates().size() > 0); 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)); + 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)); + 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)); + eval_proof.eval_proof.z.get_batch_size(LOOKUP_BATCH)); generate_evaluation_points(commitment_scheme, common_data, constraint_system, - table_description, proof.eval_proof.challenge, is_lookup_enabled); + table_description, evaluation_challenge, is_lookup_enabled); - proof.commitments[FIXED_VALUES_BATCH] = common_data.commitments.fixed_values; - } - - static inline bool verify_lpc_proof( - const placeholder_proof &proof, - commitment_scheme_type& commitment_scheme, - transcript_type &transcript - ) { - if (!commitment_scheme.verify_eval( proof.eval_proof.eval_proof, proof.commitments, transcript )) { - BOOST_LOG_TRIVIAL(info) << "Verification failed because: commitment scheme verification failed."; - return false; - } - return true; } }; } // namespace snark diff --git a/crypto3/libs/zk/test/CMakeLists.txt b/crypto3/libs/zk/test/CMakeLists.txt index c69986f391..9e4eb75204 100644 --- a/crypto3/libs/zk/test/CMakeLists.txt +++ b/crypto3/libs/zk/test/CMakeLists.txt @@ -60,6 +60,7 @@ set(TESTS_NAMES "systems/plonk/type_traits" "systems/plonk/placeholder/placeholder_circuits" + "systems/plonk/placeholder/placeholder_circuits_dFRI" "systems/plonk/placeholder/placeholder_goldilocks" # TODO(ioxid): fails with "std::invalid_argument: expected logn <= arithmetic_params::two_adicity" # so Mersenne31 is unsupported for now. diff --git a/crypto3/libs/zk/test/systems/plonk/placeholder/placeholder_circuits_dFRI.cpp b/crypto3/libs/zk/test/systems/plonk/placeholder/placeholder_circuits_dFRI.cpp new file mode 100644 index 0000000000..e04a7a25d2 --- /dev/null +++ b/crypto3/libs/zk/test/systems/plonk/placeholder/placeholder_circuits_dFRI.cpp @@ -0,0 +1,147 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2025 Martun Karapetyan +// +// 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. +//---------------------------------------------------------------------------// +// Test all circuits using them twice over a dFRI aggregated proof on one set of parameters (pallas and poseidon) +// + +#define BOOST_TEST_MODULE placeholder_dFRI_circuits_test + +#include +#include + +#include +#include + +#include + +#include "circuits.hpp" +#include "placeholder_dFRI_test_runner.hpp" + +BOOST_AUTO_TEST_SUITE(placeholder_dFRI_circuits) + +using curve_type = algebra::curves::pallas; +using field_type = typename curve_type::base_field_type; +using hash_type = hashes::poseidon>; +using test_runner_type = placeholder_dFRI_test_runner; + +BOOST_AUTO_TEST_CASE(circuit1) +{ + test_tools::random_test_initializer random_test_initializer; + auto circuit = circuit_test_1( + random_test_initializer.alg_random_engines.template get_alg_engine(), + random_test_initializer.generic_random_engine + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_CASE(circuit2) +{ + test_tools::random_test_initializer random_test_initializer; + auto pi0 = random_test_initializer.alg_random_engines.template get_alg_engine()(); + auto circuit = circuit_test_t( + pi0, + random_test_initializer.alg_random_engines.template get_alg_engine(), + random_test_initializer.generic_random_engine + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_CASE(circuit3) +{ + test_tools::random_test_initializer random_test_initializer; + auto circuit = circuit_test_3( + random_test_initializer.alg_random_engines.template get_alg_engine(), + random_test_initializer.generic_random_engine + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_CASE(circuit4) +{ + test_tools::random_test_initializer random_test_initializer; + auto circuit = circuit_test_4( + random_test_initializer.alg_random_engines.template get_alg_engine(), + random_test_initializer.generic_random_engine + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_CASE(circuit5) +{ + test_tools::random_test_initializer random_test_initializer; + auto circuit = circuit_test_5( + random_test_initializer.alg_random_engines.template get_alg_engine(), + random_test_initializer.generic_random_engine + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_CASE(circuit6) +{ + test_tools::random_test_initializer random_test_initializer; + auto circuit = circuit_test_6( + random_test_initializer.alg_random_engines.template get_alg_engine(), + random_test_initializer.generic_random_engine + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_CASE(circuit7) +{ + test_tools::random_test_initializer random_test_initializer; + auto circuit = circuit_test_7( + random_test_initializer.alg_random_engines.template get_alg_engine(), + random_test_initializer.generic_random_engine + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_CASE(circuit8) +{ + test_tools::random_test_initializer random_test_initializer; + auto circuit = circuit_test_8( + random_test_initializer.alg_random_engines.template get_alg_engine(), + random_test_initializer.generic_random_engine + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_CASE(circuit_fib) +{ + test_tools::random_test_initializer random_test_initializer; + auto circuit = circuit_test_fib( + random_test_initializer.alg_random_engines.template get_alg_engine() + ); + test_runner_type test_runner(circuit, circuit); + BOOST_CHECK(test_runner.run_test()); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/crypto3/libs/zk/test/systems/plonk/placeholder/placeholder_dFRI_test_runner.hpp b/crypto3/libs/zk/test/systems/plonk/placeholder/placeholder_dFRI_test_runner.hpp new file mode 100644 index 0000000000..889b564118 --- /dev/null +++ b/crypto3/libs/zk/test/systems/plonk/placeholder/placeholder_dFRI_test_runner.hpp @@ -0,0 +1,233 @@ +//---------------------------------------------------------------------------// +// Copyright (c) 2025 Martun Karapetyan +// +// 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_TEST_PLACEHOLDER_DFRI_TEST_RUNNER_HPP +#define CRYPTO3_ZK_TEST_PLACEHOLDER_DFRI_TEST_RUNNER_HPP + +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "circuits.hpp" + +using namespace nil; +using namespace nil::crypto3; +using namespace nil::crypto3::zk; +using namespace nil::crypto3::zk::snark; + +template +struct placeholder_dFRI_test_runner { + struct placeholder_test_params { + constexpr static const std::size_t lambda = 40; + constexpr static const std::size_t m = 2; + }; + + using circuit_params = placeholder_circuit_params; + using transcript_type = typename transcript::fiat_shamir_heuristic_sequential; + + using lpc_params_type = commitments::list_polynomial_commitment_params< + merkle_hash_type, + transcript_hash_type, + placeholder_test_params::m + >; + + using lpc_type = commitments::list_polynomial_commitment; + using lpc_scheme_type = typename commitments::lpc_commitment_scheme; + using lpc_proof_type = typename lpc_scheme_type::lpc_proof_type; + using lpc_placeholder_params_type = nil::crypto3::zk::snark::placeholder_params; + using policy_type = zk::snark::detail::placeholder_policy; + using circuit_type = circuit_description>; + using fri_type = typename lpc_scheme_type::fri_type; + using proof_of_work_type = typename fri_type::grinding_type::output_type; + using polynomial_type = typename lpc_scheme_type::polynomial_type; + using public_input_type = std::vector>; + using public_preprocessor_type = placeholder_public_preprocessor; + using private_preprocessor_type = placeholder_private_preprocessor; + using common_data_type = typename public_preprocessor_type::preprocessed_data_type::common_data_type; + + using placeholder_aggregated_proof_type = nil::crypto3::zk::snark:: + placeholder_aggregated_proof; + + placeholder_dFRI_test_runner(const circuit_type &circuit1_in, const circuit_type &circuit2_in) + : circuit1(circuit1_in), desc1(circuit1_in.table.witnesses().size(), + circuit1_in.table.public_inputs().size(), + circuit1_in.table.constants().size(), + circuit1_in.table.selectors().size(), + circuit1_in.usable_rows, + circuit1_in.table_rows), + circuit2(circuit2_in), desc2(circuit2_in.table.witnesses().size(), + circuit2_in.table.public_inputs().size(), + circuit2_in.table.constants().size(), + circuit2_in.table.selectors().size(), + circuit2_in.usable_rows, + circuit2_in.table_rows), + constraint_system1(circuit1_in.gates, circuit1_in.copy_constraints, circuit1_in.lookup_gates, circuit1_in.lookup_tables), + constraint_system2(circuit2_in.gates, circuit2_in.copy_constraints, circuit2_in.lookup_gates, circuit2_in.lookup_tables), + assignments1(circuit1_in.table), + assignments2(circuit2_in.table), + table_rows_log(std::log2(circuit1_in.table_rows)), + fri_params(1, table_rows_log, placeholder_test_params::lambda, 4) { + } + + // The code in this function generates an aggregated dFRI proof using the provided 2 circuits. + // It is very similar to the code in the proof-producer. Should something change in the algorithm, + // The corresponding changes must be made both here and in the proof-producer. + bool run_test() { + lpc_scheme_type lpc_scheme1(fri_params); + + typename public_preprocessor_type::preprocessed_data_type + preprocessed_public_data1 = placeholder_public_preprocessor::process( + constraint_system1, assignments1.public_table(), desc1, lpc_scheme1, max_quotient_poly_chunks); + + typename private_preprocessor_type::preprocessed_data_type + preprocessed_private_data1 = placeholder_private_preprocessor::process( + constraint_system1, assignments1.private_table(), desc1); + + auto prover1 = placeholder_prover( + preprocessed_public_data1, std::move(preprocessed_private_data1), desc1, constraint_system1, + lpc_scheme1, true); + auto partial_proof1 = prover1.process(); + + lpc_scheme_type lpc_scheme2(fri_params); + + typename public_preprocessor_type::preprocessed_data_type + preprocessed_public_data2 = placeholder_public_preprocessor::process( + constraint_system2, assignments2.public_table(), desc2, lpc_scheme2, max_quotient_poly_chunks); + + typename private_preprocessor_type::preprocessed_data_type + preprocessed_private_data2 = placeholder_private_preprocessor::process( + constraint_system2, assignments2.private_table(), desc2); + + auto prover2 = placeholder_prover( + preprocessed_public_data2, std::move(preprocessed_private_data2), desc2, constraint_system2, + lpc_scheme2, true); + auto partial_proof2 = prover2.process(); + + // Create the aggregated challenge. + transcript_type transcript_for_aggregation; + + transcript_for_aggregation(prover1.transcript.template challenge()); + transcript_for_aggregation(prover2.transcript.template challenge()); + + // produce the aggregated challenge + auto aggregated_challenge = transcript_for_aggregation.template challenge(); + +std::cout << "Prover aggregated_challenge = " << aggregated_challenge << std::endl; + + // This the transcript that our provers will use, it's not the same as 'transcript_for_aggregation', it's the transcript that + // you get after injesting the aggregated challenge. + transcript_type aggregated_transcript; + aggregated_transcript(aggregated_challenge); + + // Set the batches as fixed and states as committed, take the values of theta powers used. + // lpc_scheme1.set_fixed_polys_values(preprocessed_public_data1.common_data->commitment_scheme_data); + // lpc_scheme2.set_fixed_polys_values(preprocessed_public_data2.common_data->commitment_scheme_data); + + std::size_t theta_power1 = lpc_scheme1.compute_theta_power_for_combined_Q(); + + // We don't use the 'theta_power2' here, but let's keep this code. + std::size_t theta_power2 = lpc_scheme2.compute_theta_power_for_combined_Q(); + + // Calculate combined Q values. + auto challenge_from_aggregated_transcript = aggregated_transcript.template challenge(); +std::cout << "First challenge from agg transcript for combined Q is " << challenge_from_aggregated_transcript << std::endl; + + polynomial_type combined_Q1 = lpc_scheme1.prepare_combined_Q( + challenge_from_aggregated_transcript, 0); + polynomial_type combined_Q2 = lpc_scheme2.prepare_combined_Q( + challenge_from_aggregated_transcript, theta_power1); + + polynomial_type sum_poly = combined_Q1 + combined_Q2; + + lpc_scheme_type lpc_scheme_for_FRI(fri_params); + + typename lpc_scheme_type::fri_proof_type fri_proof; + std::vector consistency_checks_challenges; + proof_of_work_type proof_of_work; + lpc_scheme_for_FRI.proof_eval_FRI_proof( + sum_poly, fri_proof, consistency_checks_challenges, proof_of_work, + aggregated_transcript); + +std::cout << "Prover: consistency_checks_challenges[0] = " << consistency_checks_challenges[0] << std::endl; + + // Generate consistency check proofs. + lpc_proof_type initial_proof1 = lpc_scheme1.proof_eval_lpc_proof(consistency_checks_challenges); + lpc_proof_type initial_proof2 = lpc_scheme2.proof_eval_lpc_proof(consistency_checks_challenges); + + // Aggregate all the parts of proofs into 1 aggregated proof. + placeholder_aggregated_proof_type agg_proof; + agg_proof.partial_proofs.emplace_back(partial_proof1); + agg_proof.partial_proofs.emplace_back(partial_proof2); + agg_proof.aggregated_proof.initial_proofs_per_prover.emplace_back(initial_proof1); + agg_proof.aggregated_proof.initial_proofs_per_prover.emplace_back(initial_proof2); + agg_proof.aggregated_proof.fri_proof = fri_proof; + agg_proof.aggregated_proof.proof_of_work = proof_of_work; + + // Create LPC schemes for the verifiers. + lpc_scheme_type verifier_lpc_scheme1(fri_params); + lpc_scheme_type verifier_lpc_scheme2(fri_params); + + std::vector common_datas = { + *preprocessed_public_data1.common_data, *preprocessed_public_data2.common_data}; + std::vector> table_descriptions = {desc1, desc2}; + std::vector> constraint_systems = {constraint_system1, constraint_system2}; + std::vector commitment_schemes = {verifier_lpc_scheme1, verifier_lpc_scheme2}; + std::vector public_inputs = {assignments1.public_inputs(), assignments2.public_inputs()}; + + bool verifier_res = placeholder_DFRI_verifier::process( + common_datas, agg_proof, table_descriptions, constraint_systems, commitment_schemes, public_inputs); + return verifier_res; + } + + // Fields for circuit 1. + circuit_type circuit1; + plonk_table_description desc1; + typename policy_type::constraint_system_type constraint_system1; + typename policy_type::variable_assignment_type assignments1; + + // Fields for circuit 2. + circuit_type circuit2; + plonk_table_description desc2; + typename policy_type::constraint_system_type constraint_system2; + typename policy_type::variable_assignment_type assignments2; + + // Shared parameters, these must match. + std::size_t table_rows_log; + typename lpc_type::fri_type::params_type fri_params; +}; + +#endif // CRYPTO3_ZK_TEST_PLACEHOLDER_DFRI_TEST_RUNNER_HPP diff --git a/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/aggregated_fri_proof_command.hpp b/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/aggregated_fri_proof_command.hpp index 130eab43de..0241e2bc68 100644 --- a/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/aggregated_fri_proof_command.hpp +++ b/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/aggregated_fri_proof_command.hpp @@ -80,7 +80,7 @@ namespace nil { BOOST_LOG_TRIVIAL(info) << "Writing aggregated FRI proof to " << output_file; - fri_proof_marshalling_type marshalled_proof = nil::crypto3::marshalling::types::fill_fri_round_proof(fri_proof); + fri_proof_marshalling_type marshalled_proof = nil::crypto3::marshalling::types::fill_initial_fri_proof(fri_proof); return detail::encode_marshalling_to_file( output_file, marshalled_proof); @@ -125,6 +125,12 @@ namespace nil { transcript(aggregated_challenge.value()); + // We don't use this challenge, but we should still create it, because the creation of + // combined Q uses this challenge in the previous step. If we don't do this, + // the next challenge taken from this transcript will match that value of 'theta'. + [[maybe_unused]] auto unused_challenge_from_agg_transcript = + transcript.template challenge(); + // Sum up all the polynomials from the files. polynomial_type sum_poly; for (const auto& path : input_combined_Q_polynomial_files) { diff --git a/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/detail/proof_gen.hpp b/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/detail/proof_gen.hpp index 8400bdc9ec..34921089e9 100644 --- a/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/detail/proof_gen.hpp +++ b/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/detail/proof_gen.hpp @@ -232,7 +232,8 @@ namespace nil { nil::crypto3::marshalling::types::field_element< TTypeBase, typename BlueprintField::value_type>; - challenge_marshalling_type marshalled_challenge(proof.eval_proof.challenge); + challenge_marshalling_type marshalled_challenge( + prover.transcript.template challenge()); res = detail::encode_marshalling_to_file( challenge_file_, marshalled_challenge); @@ -242,12 +243,13 @@ namespace nil { BOOST_LOG_TRIVIAL(error) << "Failed to write challenge to file."; } - this->lpc_scheme_->state_commited(crypto3::zk::snark::FIXED_VALUES_BATCH); - this->lpc_scheme_->state_commited(crypto3::zk::snark::VARIABLE_VALUES_BATCH); - this->lpc_scheme_->state_commited(crypto3::zk::snark::PERMUTATION_BATCH); - this->lpc_scheme_->state_commited(crypto3::zk::snark::QUOTIENT_BATCH); - this->lpc_scheme_->state_commited(crypto3::zk::snark::LOOKUP_BATCH); - this->lpc_scheme_->mark_batch_as_fixed(crypto3::zk::snark::FIXED_VALUES_BATCH); + // Looks like we don't need the following lines. + //this->lpc_scheme_->state_commited(crypto3::zk::snark::FIXED_VALUES_BATCH); + //this->lpc_scheme_->state_commited(crypto3::zk::snark::VARIABLE_VALUES_BATCH); + //this->lpc_scheme_->state_commited(crypto3::zk::snark::PERMUTATION_BATCH); + //this->lpc_scheme_->state_commited(crypto3::zk::snark::QUOTIENT_BATCH); + //this->lpc_scheme_->state_commited(crypto3::zk::snark::LOOKUP_BATCH); + //this->lpc_scheme_->mark_batch_as_fixed(crypto3::zk::snark::FIXED_VALUES_BATCH); this->lpc_scheme_->set_fixed_polys_values(this->public_preprocessed_data_->common_data->commitment_scheme_data); std::size_t theta_power = this->lpc_scheme_->compute_theta_power_for_combined_Q(); diff --git a/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/gen_consistency_check_command.hpp b/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/gen_consistency_check_command.hpp index 3d1b0b4d02..97ef4c6469 100644 --- a/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/gen_consistency_check_command.hpp +++ b/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/gen_consistency_check_command.hpp @@ -32,11 +32,9 @@ namespace nil { ConsistencyChecksGenerator( resources::resource_provider& lpc_scheme_provider, - const boost::filesystem::path& combined_Q_file, const boost::filesystem::path& consistency_checks_challenges_output_file, const boost::filesystem::path& output_proof_file - ): combined_Q_file_(combined_Q_file), - consistency_checks_challenges_output_file_(consistency_checks_challenges_output_file), + ) : consistency_checks_challenges_output_file_(consistency_checks_challenges_output_file), output_proof_file_(output_proof_file) { resources::subscribe_value(lpc_scheme_provider, lpc_scheme_); @@ -46,7 +44,6 @@ namespace nil { BOOST_ASSERT(lpc_scheme_); return generate_consistency_checks_to_file( lpc_scheme_, - combined_Q_file_, consistency_checks_challenges_output_file_, output_proof_file_ ); @@ -72,7 +69,6 @@ namespace nil { static CommandResult generate_consistency_checks_to_file( std::shared_ptr lpc_scheme, - const boost::filesystem::path& combined_Q_file, const boost::filesystem::path& consistency_checks_challenges_output_file, const boost::filesystem::path& output_proof_file) { @@ -85,11 +81,7 @@ namespace nil { if (!challenges) return CommandResult::Error(ResultCode::IOError, "Failed to read challenges from {}", consistency_checks_challenges_output_file.string()); - std::optional combined_Q = PolynomialIO::read_poly_from_file(combined_Q_file); - if (!combined_Q) - return CommandResult::Error(ResultCode::IOError, "Failed to read combined Q from {}", combined_Q_file.string()); - - LpcProofType proof = lpc_scheme->proof_eval_lpc_proof(combined_Q.value(), challenges.value()); + LpcProofType proof = lpc_scheme->proof_eval_lpc_proof(challenges.value()); auto const res = save_lpc_consistency_proof_to_file(proof, output_proof_file); if (!res) @@ -101,7 +93,6 @@ namespace nil { private: std::shared_ptr lpc_scheme_; - boost::filesystem::path combined_Q_file_; boost::filesystem::path consistency_checks_challenges_output_file_; boost::filesystem::path output_proof_file_; }; @@ -111,7 +102,6 @@ namespace nil { struct GenerateConsistencyCheckCommand: public command_chain { struct Args { boost::filesystem::path in_lpc_scheme_file; - boost::filesystem::path in_combined_Q_file; boost::filesystem::path out_consistency_checks_challenges_file; boost::filesystem::path out_proof_file; @@ -136,7 +126,6 @@ namespace nil { auto& lpc_scheme_reader = add_step(args.in_lpc_scheme_file); add_step( lpc_scheme_reader, - args.in_combined_Q_file, args.out_consistency_checks_challenges_file, args.out_proof_file ); diff --git a/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/merge_proofs_command.hpp b/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/merge_proofs_command.hpp index 24285969d8..9b0a31eddb 100644 --- a/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/merge_proofs_command.hpp +++ b/proof-producer/bin/proof-producer/include/nil/proof-generator/commands/merge_proofs_command.hpp @@ -132,6 +132,7 @@ namespace nil { merged_proof.aggregated_proof.fri_proof = nil::crypto3::marshalling::types::make_initial_fri_proof(*marshalled_fri_proof); + // TODO(martun): we're missing the proof of work here, need to add. BOOST_LOG_TRIVIAL(info) << "Writing merged proof to \"" << merged_proof_file << "\""; auto marshalled_proof = nil::crypto3::marshalling::types::fill_placeholder_aggregated_proof