From d87d7e7dbc47a1714079df6e3f693218732bdfcd Mon Sep 17 00:00:00 2001 From: Martun Karapetyan Date: Wed, 11 Sep 2024 11:48:41 +0400 Subject: [PATCH] Dividing LPC and FRI into stages and creating structures for aggregated FRI. --- .../detail/polynomial/basic_fri.hpp | 232 ++++++++++++++---- .../crypto3/zk/commitments/polynomial/lpc.hpp | 211 ++++++++++++++-- .../snark/systems/plonk/placeholder/proof.hpp | 70 +++++- .../systems/plonk/placeholder/prover.hpp | 26 +- .../nil/crypto3/zk/transcript/fiat_shamir.hpp | 22 ++ libs/zk/test/commitment/fri.cpp | 3 + 6 files changed, 467 insertions(+), 97 deletions(-) diff --git a/libs/zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp b/libs/zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp index cdf02d4d9..a32ef505e 100644 --- a/libs/zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp +++ b/libs/zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp @@ -268,7 +268,61 @@ namespace nil { std::vector round_proofs; }; + struct commitments_part_of_proof { + bool operator==(const commitments_part_of_proof& rhs) const { + return fri_roots == rhs.fri_roots && + final_polynomial == rhs.final_polynomial; + } + + bool operator!=(const commitments_part_of_proof& rhs) const { + return !(rhs == *this); + } + + // Vector of size 'step_list.size()'. + std::vector fri_roots; + math::polynomial final_polynomial; + }; + + struct round_proofs_batch_type { + bool operator==(const round_proofs_batch_type &rhs) const { + return round_proofs == rhs.round_proofs; + } + + bool operator!=(const round_proofs_batch_type &rhs) const { + return !(rhs == *this); + } + + // Vector of size 'lambda'. + std::vector> round_proofs; + }; + + struct initial_proofs_batch_type { + bool operator==(const initial_proofs_batch_type &rhs) const { + return initial_proofs == rhs.initial_proofs; + } + + bool operator!=(const initial_proofs_batch_type &rhs) const { + return !(rhs == *this); + } + + // Vector of size 'lambda'. + std::vector> initial_proofs; + }; + struct proof_type { + proof_type() = default; + proof_type(const proof_type&) = default; + + proof_type(const round_proofs_batch_type& round_proofs, + const initial_proofs_batch_type& intial_proofs) + : fri_roots(round_proofs.fri_roots) + , final_polynomial(round_proofs.final_polynomial) { + for (std::size_t i = 0; i < intial_proofs.initial_proofs.size(); ++i) { + query_proofs.emplace_back( + {intial_proofs.initial_proofs[i], round_proofs.round_proofs[i]}); + } + } + bool operator==(const proof_type &rhs) const { // TODO(martun): check if the following comment can be deleted. // if( FRI::use_grinding && proof_of_work != rhs.proof_of_work ){ @@ -355,13 +409,13 @@ namespace nil { FRI>::value, bool>::type = true> static typename FRI::precommitment_type - precommit(math::polynomial_dfs &f, + precommit(const math::polynomial_dfs &f, std::shared_ptr> D, const std::size_t fri_step) { - if (f.size() != D->size()) { - f.resize(D->size(), nullptr, D); + throw std::runtime_error("Polynomial size does not match the domain size in FRI precommit."); } + std::size_t domain_size = D->size(); std::size_t coset_size = 1 << fri_step; std::size_t leafs_number = domain_size / coset_size; @@ -420,6 +474,10 @@ namespace nil { math::polynomial_dfs f_dfs; f_dfs.from_coefficients(f); + if (f_dfs.size() != D->size()) { + f_dfs.resize(D->size(), nullptr, D); + } + return precommit(f_dfs, D, fri_step); } @@ -660,12 +718,10 @@ namespace nil { static std::tuple< std::vector, std::vector, - std::vector, - math::polynomial + typename FRI::commitments_part_of_proof > commit_phase( const PolynomialType& combined_Q, - const std::map &precommitments, const typename FRI::precommitment_type &combined_Q_precommitment, const typename FRI::params_type &fri_params, typename FRI::transcript_type &transcript) @@ -673,8 +729,7 @@ namespace nil { PROFILE_SCOPE("Basic FRI commit phase"); std::vector fs; std::vector fri_trees; - std::vector fri_roots; - math::polynomial final_polynomial; + typename FRI::commitments_part_of_proof commitments_proof; auto f = combined_Q; auto precommitment = combined_Q_precommitment; @@ -683,7 +738,7 @@ namespace nil { for (std::size_t i = 0; i < fri_params.step_list.size(); i++) { fs.push_back(f); fri_trees.push_back(precommitment); - fri_roots.push_back(commit(precommitment)); + commitments_proof.fri_roots.push_back(commit(precommitment)); 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(); @@ -696,17 +751,25 @@ namespace nil { f = commitments::detail::fold_polynomial(f, alpha); } } - if (i != fri_params.step_list.size() - 1) - precommitment = precommit(f, fri_params.D[t], fri_params.step_list[i + 1]); + if (i != fri_params.step_list.size() - 1) { + const auto& D = fri_params.D[t]; + if constexpr (std::is_same, + PolynomialType>::value) { + if (f.size() != D->size()) { + f.resize(D->size(), nullptr, D); + } + } + precommitment = precommit(f, D, fri_params.step_list[i + 1]); + } } fs.push_back(f); if constexpr (std::is_same, PolynomialType>::value) { - final_polynomial = math::polynomial(f.coefficients()); + commitments_proof.final_polynomial = math::polynomial(f.coefficients()); } else { - final_polynomial = f; + commitments_proof.final_polynomial = f; } - return std::make_tuple(fs, fri_trees, fri_roots, final_polynomial); + return std::make_tuple(fs, fri_trees, commitments_proof); } /** @brief Convert a set of polynomials from DFS form into coefficients form */ @@ -840,11 +903,6 @@ namespace nil { static std::vector build_round_proofs( const typename FRI::params_type &fri_params, - const std::map> &g, - const std::map< - std::size_t, - std::vector> - > &g_coeffs, const std::vector &fri_trees, const std::vector &fs, const math::polynomial &final_polynomial, @@ -915,18 +973,44 @@ namespace nil { template - static std::vector - query_phase( - const std::map &precommitments, + static typename FRI::round_proofs_batch_type query_phase_round_proofs( const typename FRI::params_type &fri_params, - typename FRI::transcript_type &transcript, - const std::map> &g, const std::vector &fri_trees, const std::vector &fs, - const math::polynomial &final_polynomial) + const math::polynomial &final_polynomial, + const std::vector& challenges) { - PROFILE_SCOPE("Basic FRI query phase"); - std::vector query_proofs(fri_params.lambda); + typename FRI::round_proofs_batch_type proof; + + 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]; + x = x.pow((FRI::field_type::modulus - 1) / domain_size); + + std::uint64_t x_index = 0; + + while (fri_params.D[0]->get_domain_element(x_index) != x) { + ++x_index; + } + + // Fill round proofs + std::vector round_proofs = + build_round_proofs( + fri_params, fri_trees, fs, final_polynomial, x_index); + + proof.round_proofs.emplace_back(std::move(round_proofs)); + } + return proof; + } + + template + static typename FRI::initial_proofs_batch_type query_phase_initial_proofs( + const std::map &precommitments, + const typename FRI::params_type &fri_params, + const std::map> &g, + const std::vector& challenges) + { + typename FRI::initial_proofs_batch_type proof; // If we have DFS polynomials, and we are going to resize them, better convert them to coefficients form, // and compute their values in those 2 * FRI::lambda points each, which is normally 2 * 20. @@ -937,8 +1021,8 @@ 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 = transcript.template challenge(); - x = x.pow((FRI::field_type::modulus - 1)/domain_size); + typename FRI::field_type::value_type x = challenges[query_id]; + x = x.pow((FRI::field_type::modulus - 1) / domain_size); std::uint64_t x_index = 0; @@ -946,34 +1030,74 @@ namespace nil { ++x_index; } - // Initial proof std::map initial_proof = build_initial_proof( precommitments, fri_params, g, g_coeffs, x_index); - // Fill round proofs - std::vector - round_proofs = build_round_proofs( - fri_params, g, g_coeffs, fri_trees, fs, final_polynomial, x_index); + proof.initial_proofs.emplace_back(std::move(initial_proof)); + } + return proof; + } + + template + static std::vector + query_phase_with_challenges( + const std::map &precommitments, + const typename FRI::params_type &fri_params, + const std::vector& challenges, + const std::map> &g, + const std::vector &fri_trees, + const std::vector &fs, + const math::polynomial &final_polynomial) + { + typename FRI::initial_proofs_batch_type initial_proofs = + query_phase_initial_proofs( + precommitments, fri_params, g, challenges); + + typename FRI::round_proofs_batch_type round_proofs = + query_phase_round_proofs( + fri_params, fri_trees, fs, final_polynomial, challenges); + + // Join intial proofs and round proofs into a structure of query proofs. + std::vector query_proofs(fri_params.lambda); - typename FRI::query_proof_type query_proof = {std::move(initial_proof), std::move(round_proofs)}; - query_proofs[query_id] = std::move(query_proof); + for (std::size_t query_id = 0; query_id < fri_params.lambda; query_id++) { + query_proofs[query_id] = {std::move(initial_proofs.initial_proofs[query_id]), + std::move(round_proofs.round_proofs[query_id])}; } + return query_proofs; + } - return std::move(query_proofs); + template + static std::vector + query_phase( + const std::map &precommitments, + const typename FRI::params_type &fri_params, + typename FRI::transcript_type &transcript, + const std::map> &g, + const std::vector &fri_trees, + const std::vector &fs, + const math::polynomial &final_polynomial) + { + PROFILE_SCOPE("Basic FRI query phase"); + std::vector challenges = + transcript.template challenges(fri_params.lambda); + + return query_phase_with_challenges( + precommitments, fri_params, challenges, g, fri_trees, fs, final_polynomial); } template, - FRI>::value, - bool>::type = true> + std::is_base_of< + commitments::detail::basic_batched_fri< + typename FRI::field_type, typename FRI::merkle_tree_hash_type, + typename FRI::transcript_hash_type, + FRI::m, typename FRI::grinding_type>, + FRI>::value, + bool>::type = true> static typename FRI::proof_type proof_eval( const std::map> &g, const PolynomialType& combined_Q, @@ -992,18 +1116,20 @@ namespace nil { // Commit phase std::vector fri_trees; - std::vector fri_roots; std::vector fs; - math::polynomial final_polynomial; + math::polynomial final_polynomial; + + // Contains fri_roots and final_polynomial. + typename FRI::commitments_part_of_proof commitments_proof; - std::tie(fs, fri_trees, fri_roots, final_polynomial) = - commit_phase( - combined_Q, precommitments, + std::tie(fs, fri_trees, commitments_proof) = + commit_phase( + combined_Q, combined_Q_precommitment, fri_params, transcript); // Grinding - if ( fri_params.use_grinding ) { + if (fri_params.use_grinding) { PROFILE_SCOPE("Basic FRI grinding phase"); proof.proof_of_work = FRI::grinding_type::generate(transcript, fri_params.grinding_parameter); } @@ -1011,10 +1137,10 @@ namespace nil { // Query phase proof.query_proofs = query_phase( precommitments, fri_params, transcript, - g, fri_trees, fs, final_polynomial); + g, fri_trees, fs, commitments_proof.final_polynomial); - proof.fri_roots = std::move(fri_roots); - proof.final_polynomial = std::move(final_polynomial); + proof.fri_roots = std::move(commitments_proof.fri_roots); + proof.final_polynomial = std::move(commitments_proof.final_polynomial); return proof; } diff --git a/libs/zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp b/libs/zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp index 8b5b695d9..f93adac47 100644 --- a/libs/zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp +++ b/libs/zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp @@ -46,6 +46,7 @@ namespace nil { namespace commitments { // Placeholder-friendly class. + // LPCScheme is usually 'batched_list_polynomial_commitment<...>'. template> class lpc_commitment_scheme : public polys_evaluator(); preprocessed_data_type result; @@ -132,6 +136,7 @@ namespace nil { commitment_type commit(std::size_t index) { this->state_commited(index); + _trees[index] = nil::crypto3::zk::algorithms::precommit( this->_polys[index], _fri_params.D[0], _fri_params.step_list.front()); return _trees[index].root(); @@ -149,24 +154,142 @@ namespace nil { BOOST_ASSERT(this->_points.size() == this->_polys.size()); BOOST_ASSERT(this->_points.size() == this->_z.get_batches_num()); - for(auto const& it: this->_trees) { + // For each batch we have a merkle tree. + for (auto const& it: this->_trees) { transcript(it.second.root()); } // Prepare z-s and combined_Q; auto theta = transcript.template challenge(); - typename field_type::value_type theta_acc = field_type::value_type::one(); + polynomial_type combined_Q = prepare_combined_Q(theta); + + auto fri_proof = commit_and_fri_proof(combined_Q, transcript); + return proof_type({this->_z, fri_proof}); + } + + /** This function must be called for the cases where we want to skip the + * round proof for FRI. Must be called once per instance of prover for the aggregated FRI. + * \param[in] combined_Q - Polynomial combined_Q was already computed by the current + prover in the previous step of the aggregated FRI protocol. + * \param[in] transcript - This transcript is initialized from a challenge sent from the "Main" prover, + on which the round proof was created for the polynomial F(x) = Sum(combined_Q). + */ + lpc_proof_type proof_eval_lpc_proof( + const polynomial_type& combined_Q, transcript_type &transcript) { + + this->eval_polys(); + + BOOST_ASSERT(this->_points.size() == this->_polys.size()); + BOOST_ASSERT(this->_points.size() == this->_z.get_batches_num()); + + // For each batch we have a merkle tree. + for (auto const& it: this->_trees) { + transcript(it.second.root()); + } + + std::vector challenges = + transcript.template challenges(this->_fri_params.lambda); + + typename fri_type::initial_proofs_batch_type initial_proofs = + nil::crypto3::zk::algorithms::query_phase_initial_proofs( + this->_trees, this->_fri_params, this->_polys, challenges); + return {this->_z, initial_proofs}; + } + + /** This function must be called once for the aggregated FRI, to proof that polynomial + 'sum_poly' has low degree. + * \param[in] sum_poly - polynomial F(x) = Sum(combined_Q). + * \param[in] transcript - This transcript is initialized on the main prover, which has digested + challenges from all the other provers. + */ + fri_proof_type proof_eval_FRI_proof(const polynomial_type& sum_poly, transcript_type &transcript) { + // TODO(martun): this function belongs to FRI, not here, will move later. + // Precommit to sum_poly. + if (sum_poly.size() != _fri_params.D[0]->size()) { + sum_poly.resize(_fri_params.D[0]->size(), nullptr, _fri_params.D[0]); + } + precommitment_type sum_poly_precommitment = nil::crypto3::zk::algorithms::precommit( + sum_poly, + _fri_params.D[0], + _fri_params.step_list.front() + ); + + std::vector fri_trees; + std::vector fs; + math::polynomial final_polynomial; + + // Contains fri_roots and final_polynomial. + typename fri_type::commitments_part_of_proof commitments_proof; + + // Commit to sum_poly. + std::tie(fs, fri_trees, commitments_proof) = + nil::crypto3::zk::algorithms::commit_phase( + sum_poly, + sum_poly_precommitment, + _fri_params, transcript); + + std::vector challenges = + transcript.template challenges(this->_fri_params.lambda); + + fri_proof_type result; + + result.fri_round_proof = nil::crypto3::zk::algorithms::query_phase_round_proofs< + fri_type, polynomial_type>( + _fri_params, + fri_trees, + fs, + sum_poly, + challenges); + + result.fri_commitments_proof_part.fri_roots = std::move(commitments_proof.fri_roots); + result.fri_commitments_proof_part.final_polynomial = std::move(final_polynomial); + + return result; + } + + typename fri_type::proof_type commit_and_fri_proof( + const polynomial_type& combined_Q, transcript_type &transcript) { + + + precommitment_type combined_Q_precommitment = nil::crypto3::zk::algorithms::precommit( + combined_Q, + _fri_params.D[0], + _fri_params.step_list.front() + ); + + typename fri_type::proof_type fri_proof = nil::crypto3::zk::algorithms::proof_eval< + fri_type, polynomial_type>( + this->_polys, + combined_Q, + this->_trees, + combined_Q_precommitment, + this->_fri_params, + transcript + ); + return fri_proof; + } + + /** \brief + * \param theta The value of challenge. When called from aggregated FRI, this values is sent from + the "main prover" machine. + * \param starting_power When aggregated FRI is used, the value is not zero, it's the total degree of all + the polynomials in all the provers with indices lower than the current one. + */ + polynomial_type prepare_combined_Q( + const typename field_type::value_type& theta, + std::size_t starting_power = 0) { + typename field_type::value_type theta_acc = theta.pow(starting_power); polynomial_type combined_Q; math::polynomial V; auto points = this->get_unique_points(); math::polynomial combined_Q_normal; - for (auto const &point: points){ + for (auto const &point: points) { V = {-point, 1u}; math::polynomial Q_normal; - for(std::size_t i: this->_z.get_batches()){ - for(std::size_t j = 0; j < this->_z.get_batch_size(i); j++){ + for (std::size_t i: this->_z.get_batches()) { + for (std::size_t j = 0; j < this->_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; math::polynomial g_normal; @@ -185,6 +308,7 @@ namespace nil { combined_Q_normal += Q_normal; } + // TODO(martun): the following code is the same as above with point = _etha, de-duplicate it. for (std::size_t i: this->_z.get_batches()) { if (!_batch_fixed[i]) continue; @@ -212,27 +336,14 @@ namespace nil { if constexpr (std::is_same, PolynomialType>::value) { combined_Q.from_coefficients(combined_Q_normal); + if (combined_Q.size() != _fri_params.D[0]->size()) { + combined_Q.resize(_fri_params.D[0]->size(), nullptr, _fri_params.D[0]); + } } else { combined_Q = std::move(combined_Q_normal); } - precommitment_type combined_Q_precommitment = nil::crypto3::zk::algorithms::precommit( - combined_Q, - _fri_params.D[0], - _fri_params.step_list.front() - ); - - typename fri_type::proof_type fri_proof = nil::crypto3::zk::algorithms::proof_eval< - fri_type, polynomial_type - >( - this->_polys, - combined_Q, - this->_trees, - combined_Q_precommitment, - this->_fri_params, - transcript - ); - return proof_type({this->_z, fri_proof}); + return combined_Q; } bool verify_eval( @@ -421,6 +532,60 @@ namespace nil { eval_storage_type z; typename basic_fri::proof_type fri_proof; }; + + // Represents an initial proof, which must be created for each of the N provers. + struct lpc_proof_type { + bool operator==(const lpc_proof_type &rhs) const { + return initial_fri_proofs == rhs.initial_fri_proofs && z == rhs.z; + } + + bool operator!=(const lpc_proof_type &rhs) const { + return !(rhs == *this); + } + + eval_storage_type z; + typename basic_fri::initial_proofs_batch_type initial_fri_proofs; + }; + + // Represents a round proof, which must be created just once on the main prover. + struct fri_proof_type { + bool operator==(const fri_proof_type &rhs) const { + return fri_round_proof == rhs.fri_round_proof && + fri_commitments_proof_part == rhs.fri_commitments_proof_part; + } + + bool operator!=(const fri_proof_type &rhs) const { + return !(rhs == *this); + } + + // We have a single round proof for checking that F(X) is a low degree polynomial. + typename basic_fri::round_proofs_batch_type fri_round_proof; + + // Contains fri_roots and final_polynomial that correspond to the polynomial F(x). + typename basic_fri::commitments_part_of_proof fri_commitments_proof_part; + }; + + // A single instance of this class will store all the LPC proofs for a group of provers + // when aggregated FRI is used. + struct aggregated_proof_type { + bool operator==(const aggregated_proof_type &rhs) const { + return fri_proof == rhs.fri_proof && + intial_proofs_per_prover == rhs.intial_proofs_per_prover && + proof_of_work == rhs.proof_of_work; + } + + bool operator!=(const proof_type &rhs) const { + return !(rhs == *this); + } + + // We have a single round proof for checking that F(X) is a low degree polynomial. + fri_proof_type fri_proof; + + // For each prover we have an initial proof. + std::vector intial_proofs_per_prover; + + typename LPCParams::grinding_type::output_type proof_of_work; + }; }; template diff --git a/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp b/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp index 8c57cb86f..c5cd9b9d3 100644 --- a/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp +++ b/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp @@ -40,6 +40,33 @@ namespace nil { constexpr std::size_t QUOTIENT_BATCH = 3; constexpr std::size_t LOOKUP_BATCH = 4; + // A part of the placeholder_proof. Used for proofs with aggregated FRI. + template + struct placeholder_partial_proof { + static constexpr std::size_t FIXED_VALUES_BATCH = 0; + static constexpr std::size_t VARIABLE_VALUES_BATCH = 1; + static constexpr std::size_t PERMUTATION_BATCH = 2; + static constexpr std::size_t QUOTIENT_BATCH = 3; + static constexpr std::size_t LOOKUP_BATCH = 4; + + typedef FieldType field_type; + typedef ParamsType params_type; + + using commitment_scheme_type = typename ParamsType::commitment_scheme_type; + using commitment_type = typename commitment_scheme_type::commitment_type; + + placeholder_partial_proof() = default; + + bool operator==(const placeholder_partial_proof &rhs) const { + return commitments == rhs.commitments; + } + bool operator!=(const placeholder_partial_proof &rhs) const { + return !(rhs == *this); + } + + std::map commitments; + }; + /** * A proof for the Placeholder scheme. * @@ -48,10 +75,10 @@ namespace nil { * about the structure for marshalling purposes. */ template - struct placeholder_proof { + struct placeholder_proof : public placeholder_partial_proof { static constexpr std::size_t FIXED_VALUES_BATCH = 0; static constexpr std::size_t VARIABLE_VALUES_BATCH = 1; - static constexpr std::size_t PERMUTATION_BATCH =2; + static constexpr std::size_t PERMUTATION_BATCH = 2; static constexpr std::size_t QUOTIENT_BATCH = 3; static constexpr std::size_t LOOKUP_BATCH = 4; @@ -76,20 +103,45 @@ namespace nil { } }; - placeholder_proof() { - } - - std::map commitments; - evaluation_proof eval_proof; + placeholder_proof() = default; bool operator==(const placeholder_proof &rhs) const { - return - commitments == rhs.commitments && + return placeholder_partial_proof::operator==(rhs) && eval_proof == rhs.eval_proof; } bool operator!=(const placeholder_proof &rhs) const { return !(rhs == *this); } + + evaluation_proof eval_proof; + }; + + /** + * An aggregated proof for the Placeholder scheme. It contains N partial proofs from N provers, with a shared + * aggregated FRI proof. + */ + template + struct placeholder_aggregated_proof { + typedef FieldType field_type; + typedef ParamsType params_type; + + using circuit_params_type = typename ParamsType::circuit_params_type; + using commitment_scheme_type = typename ParamsType::commitment_scheme_type; + using commitment_type = typename commitment_scheme_type::commitment_type; + + placeholder_aggregated_proof() = default; + + bool operator==(const placeholder_aggregated_proof &rhs) const { + return partial_proofs == rhs.partial_proofs && + aggregated_proof == rhs.aggregated_proof; + } + bool operator!=(const placeholder_aggregated_proof &rhs) const { + return !(rhs == *this); + } + + // This vector contains N partial proofs, one per prover. + std::vector> partial_proofs; + typename commitment_type::aggregated_proof_type aggregated_proof; }; } // namespace snark } // namespace zk diff --git a/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp b/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp index 679ee8b5c..f81bb2fd2 100644 --- a/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp +++ b/libs/zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp @@ -97,11 +97,12 @@ namespace nil { typename private_preprocessor_type::preprocessed_data_type preprocessed_private_data, const plonk_table_description &table_description, const plonk_constraint_system &constraint_system, - commitment_scheme_type commitment_scheme + commitment_scheme_type commitment_scheme, + bool skip_commitment_scheme_eval_proofs = false ) { auto prover = placeholder_prover( preprocessed_public_data, std::move(preprocessed_private_data), table_description, - constraint_system, commitment_scheme); + constraint_system, commitment_scheme, skip_commitment_scheme_eval_proofs); return prover.process(); } @@ -110,7 +111,8 @@ namespace nil { typename private_preprocessor_type::preprocessed_data_type preprocessed_private_data, const plonk_table_description &table_description, const plonk_constraint_system &constraint_system, - const commitment_scheme_type &commitment_scheme + const commitment_scheme_type &commitment_scheme, + bool skip_commitment_scheme_eval_proofs = false ) : preprocessed_public_data(preprocessed_public_data) , table_description(table_description) @@ -122,6 +124,7 @@ namespace nil { , transcript(std::vector({})) , _is_lookup_enabled(constraint_system.lookup_gates().size() > 0) , _commitment_scheme(commitment_scheme) + , _skip_commitment_scheme_eval_proofs(skip_commitment_scheme_eval_proofs) { // Initialize transcript. transcript(preprocessed_public_data.common_data.vk.constraint_system_with_params_hash); @@ -204,12 +207,11 @@ namespace nil { } transcript(_proof.commitments[QUOTIENT_BATCH]); - // 8. Run evaluation proofs - _proof.eval_proof.challenge = transcript.template challenge(); - generate_evaluation_points(); + if (!_skip_commitment_scheme_eval_proofs) { + // 8. Run evaluation proofs + _proof.eval_proof.challenge = transcript.template challenge(); + generate_evaluation_points(); - { - PROFILE_SCOPE("commitment scheme proof eval time"); _proof.eval_proof.eval_proof = _commitment_scheme.proof_eval(transcript); } @@ -369,14 +371,14 @@ namespace nil { } } - if(_is_lookup_enabled||constraint_system.copy_constraints().size() > 0){ + if (_is_lookup_enabled||constraint_system.copy_constraints().size() > 0) { _commitment_scheme.append_eval_point(PERMUTATION_BATCH, _proof.eval_proof.challenge); } - if( constraint_system.copy_constraints().size() > 0 ) + if (constraint_system.copy_constraints().size() > 0) _commitment_scheme.append_eval_point(PERMUTATION_BATCH, 0, _proof.eval_proof.challenge * _omega); - if(_is_lookup_enabled) { + if (_is_lookup_enabled) { _commitment_scheme.append_eval_point(PERMUTATION_BATCH, preprocessed_public_data.common_data.permutation_parts, _proof.eval_proof.challenge * _omega); _commitment_scheme.append_eval_point(LOOKUP_BATCH, _proof.eval_proof.challenge); @@ -387,7 +389,6 @@ namespace nil { _commitment_scheme.append_eval_point(QUOTIENT_BATCH, _proof.eval_proof.challenge); - // fixed values' rotations (table columns) std::size_t i = 0; std::size_t start_index = preprocessed_public_data.identity_polynomials.size() + @@ -479,6 +480,7 @@ namespace nil { typename FieldType::value_type _omega; std::vector _challenge_point; commitment_scheme_type _commitment_scheme; + bool _skip_commitment_scheme_eval_proofs; }; } // namespace snark } // namespace zk diff --git a/libs/zk/include/nil/crypto3/zk/transcript/fiat_shamir.hpp b/libs/zk/include/nil/crypto3/zk/transcript/fiat_shamir.hpp index 8f8ce1be0..92da6d01a 100644 --- a/libs/zk/include/nil/crypto3/zk/transcript/fiat_shamir.hpp +++ b/libs/zk/include/nil/crypto3/zk/transcript/fiat_shamir.hpp @@ -230,6 +230,17 @@ namespace nil { return result; } + template + std::vector challenges(std::size_t N) { + + std::vector result; + for (std::size_t i = 0; i < N; ++i) { + result.push_back(challenge()); + } + + return result; + } + private: typename hash_type::digest_type state; }; @@ -341,6 +352,17 @@ namespace nil { return result; } + template + std::vector challenges(std::size_t N) { + + std::vector result; + for (std::size_t i = 0; i < N; ++i) { + result.push_back(challenge()); + } + + return result; + } + public: hashes::detail::poseidon_sponge_construction_custom sponge; }; diff --git a/libs/zk/test/commitment/fri.cpp b/libs/zk/test/commitment/fri.cpp index a6064750d..776b3b4c5 100644 --- a/libs/zk/test/commitment/fri.cpp +++ b/libs/zk/test/commitment/fri.cpp @@ -130,6 +130,9 @@ void fri_basic_test() if constexpr (std::is_same, PolynomialType>::value) { f.from_coefficients(coefficients); + if (f.size() != params.D[0]->size()) { + f.resize(params.D[0]->size(), nullptr, params.D[0]); + } } else { f = PolynomialType(coefficients); }