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 65094a2595..19162bd299 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 @@ -1088,7 +1088,6 @@ namespace nil { precommitments, fri_params, challenges, g, fri_trees, fs, final_polynomial); } - template fri_trees; std::vector fs; - math::polynomial final_polynomial; // Contains fri_roots and final_polynomial. typename FRI::commitments_part_of_proof commitments_proof; 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 120adf3767..f6e6079f2e 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 @@ -148,6 +148,7 @@ namespace nil { } proof_type proof_eval(transcript_type &transcript) { + PROFILE_SCOPE("LPC proof_eval"); this->eval_polys(); @@ -352,8 +353,9 @@ namespace nil { } // Computes and returns the maximal power of theta used to compute the value of Combined_Q. - std::size_t compute_theta_power_for_combined_Q() const { + std::size_t compute_theta_power_for_combined_Q() { std::size_t theta_power = 0; + this->eval_polys(); this->build_points_map(); auto points = this->get_unique_points(); @@ -371,8 +373,9 @@ namespace nil { } for (std::size_t i: this->_z.get_batches()) { - if (!_batch_fixed.at(i)) + if (!_batch_fixed[i]) { continue; + } theta_power += this->_z.get_batch_size(i); } 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 f3e235dfad..96ad8f1fa3 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 @@ -29,6 +29,7 @@ #define CRYPTO3_ZK_PLONK_PLACEHOLDER_PROOF_HPP #include +#include namespace nil { namespace crypto3 { 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 f81bb2fd2b..1037b78d75 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 @@ -90,14 +90,15 @@ namespace nil { constexpr static const std::size_t permutation_parts = 3; constexpr static const std::size_t lookup_parts = 6; constexpr static const std::size_t f_parts = 8; - public: + + public: static inline placeholder_proof process( const typename public_preprocessor_type::preprocessed_data_type &preprocessed_public_data, 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, + const commitment_scheme_type& commitment_scheme, bool skip_commitment_scheme_eval_proofs = false ) { auto prover = placeholder_prover( @@ -207,17 +208,20 @@ 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(); - _proof.eval_proof.eval_proof = _commitment_scheme.proof_eval(transcript); } return _proof; } + commitment_scheme_type& get_commitment_scheme() { + return _commitment_scheme; + } + private: std::vector quotient_polynomial_split_dfs() { PROFILE_SCOPE("quotient_polynomial_split_dfs"); diff --git a/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp b/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp index ddc90f0e09..4123cee72a 100644 --- a/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp +++ b/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/commitments/detail/polynomial/basic_fri.hpp @@ -185,24 +185,6 @@ namespace nil { , expand_factor(expand_factor) { } - params_type( - std::size_t max_degree, - std::vector>> D, - std::vector step_list_in, - std::size_t expand_factor, - std::size_t lambda, - bool use_grinding = false, - std::size_t grinding_parameter = 16 - ) : lambda(lambda) - , use_grinding(use_grinding) - , grinding_parameter(grinding_parameter) - , max_degree(max_degree) - , D(D) - , r(std::accumulate(step_list_in.begin(), step_list_in.end(), 0)) - , step_list(step_list_in) - , expand_factor(expand_factor) - {} - bool operator==(const params_type &rhs) const { if (D.size() != rhs.D.size()) { return false; @@ -256,7 +238,7 @@ namespace nil { } // For the last round it's final_polynomial's values - + // Values for the next round. polynomial_values_type y; @@ -436,7 +418,7 @@ namespace nil { if (f.size() != D->size()) { 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; @@ -782,7 +764,6 @@ namespace nil { } precommitment = precommit(f, D, fri_params.step_list[i + 1]); } - } fs.push_back(f); if constexpr (std::is_same, PolynomialType>::value) { @@ -1159,7 +1140,7 @@ namespace nil { std::vector fs; // Contains fri_roots and final_polynomial. - typename FRI::commitments_part_of_proof commitments_proof; + typename FRI::commitments_part_of_proof commitments_proof; std::tie(fs, fri_trees, commitments_proof) = commit_phase( diff --git a/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp b/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp index 835a21ce7a..b2eb79466a 100644 --- a/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp +++ b/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/commitments/polynomial/lpc.hpp @@ -158,7 +158,7 @@ namespace nil { BOOST_ASSERT(this->_points.size() == this->_z.get_batches_num()); // For each batch we have a merkle tree. - for(auto const& it: this->_trees) { + for (auto const& it: this->_trees) { transcript(it.second.root()); } @@ -168,7 +168,7 @@ namespace nil { 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. @@ -176,7 +176,7 @@ namespace nil { 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) { @@ -271,7 +271,9 @@ namespace nil { ); return fri_proof; } - /** \brief + + /** \brief Computes polynomial combined_Q. In case this function changes, + the function 'compute_theta_power_for_combined_Q' below should be changed accordingly. * \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 @@ -280,13 +282,12 @@ namespace nil { 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; - this->build_points_map(); + 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; @@ -410,6 +411,7 @@ namespace nil { Q_normal -= _fixed_polys_values[i][j] * theta_acc; theta_acc *= theta; } + Q_normal = Q_normal / V; }, ThreadPool::PoolLevel::HIGH); @@ -429,6 +431,37 @@ namespace nil { return combined_Q; } + // Computes and returns the maximal power of theta used to compute the value of Combined_Q. + std::size_t compute_theta_power_for_combined_Q() { + std::size_t theta_power = 0; + this->eval_polys(); + this->build_points_map(); + + auto points = this->get_unique_points(); + + for (auto const &point: points) { + for (std::size_t i: this->_z.get_batches()) { + for (std::size_t j = 0; j < this->_z.get_batch_size(i); j++) { + auto iter = this->_points_map[i][j].find(point); + if (iter == this->_points_map[i][j].end()) + continue; + + theta_power++; + } + } + } + + for (std::size_t i: this->_z.get_batches()) { + if (!_batch_fixed[i]) { + continue; + } + + theta_power += this->_z.get_batch_size(i); + } + + return theta_power; + } + bool verify_eval( const proof_type &proof, const std::map &commitments, diff --git a/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp b/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp index c5cd9b9d35..96ad8f1fa3 100644 --- a/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp +++ b/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/proof.hpp @@ -29,6 +29,7 @@ #define CRYPTO3_ZK_PLONK_PLACEHOLDER_PROOF_HPP #include +#include namespace nil { namespace crypto3 { @@ -88,6 +89,7 @@ namespace nil { 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; + using partial_proof_type = placeholder_partial_proof; struct evaluation_proof { // TODO: remove it! @@ -105,6 +107,12 @@ namespace nil { placeholder_proof() = default; + placeholder_proof(const partial_proof_type &partial_proof) : + placeholder_partial_proof(partial_proof) {} + + placeholder_proof(const partial_proof_type &partial_proof, const evaluation_proof &eval_proof) : + placeholder_partial_proof(partial_proof), eval_proof(eval_proof) {} + bool operator==(const placeholder_proof &rhs) const { return placeholder_partial_proof::operator==(rhs) && eval_proof == rhs.eval_proof; @@ -141,7 +149,7 @@ namespace nil { // This vector contains N partial proofs, one per prover. std::vector> partial_proofs; - typename commitment_type::aggregated_proof_type aggregated_proof; + typename commitment_scheme_type::aggregated_proof_type aggregated_proof; }; } // namespace snark } // namespace zk diff --git a/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp b/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp index d70f066384..b057d8029c 100644 --- a/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp +++ b/parallel-crypto3/libs/parallel-zk/include/nil/crypto3/zk/snark/systems/plonk/placeholder/prover.hpp @@ -90,14 +90,15 @@ namespace nil { constexpr static const std::size_t permutation_parts = 3; constexpr static const std::size_t lookup_parts = 6; constexpr static const std::size_t f_parts = 8; - public: + + public: static inline placeholder_proof process( const typename public_preprocessor_type::preprocessed_data_type &preprocessed_public_data, 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, + const commitment_scheme_type& commitment_scheme, bool skip_commitment_scheme_eval_proofs = false ) { auto prover = placeholder_prover( @@ -208,17 +209,19 @@ 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(); - _proof.eval_proof.eval_proof = _commitment_scheme.proof_eval(transcript); } return _proof; } + commitment_scheme_type& get_commitment_scheme() { + return _commitment_scheme; + } + private: std::vector quotient_polynomial_split_dfs() { PROFILE_SCOPE("quotient_polynomial_split_dfs"); @@ -396,7 +399,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() + diff --git a/parallel-crypto3/libs/parallel-zk/test/commitment/lpc.cpp b/parallel-crypto3/libs/parallel-zk/test/commitment/lpc.cpp index a6e92d6528..d7a763ea69 100644 --- a/parallel-crypto3/libs/parallel-zk/test/commitment/lpc.cpp +++ b/parallel-crypto3/libs/parallel-zk/test/commitment/lpc.cpp @@ -203,15 +203,15 @@ BOOST_AUTO_TEST_SUITE(lpc_math_polynomial_suite); // Setup params + std::size_t degree_log = std::ceil(std::log2(d - 1)); typename fri_type::params_type fri_params( - d - 1, // max_degree - D, - generate_random_step_list(r, 1, test_global_rnd_engine), - 2, //expand_factor + 1, /*max_step*/ + degree_log, lambda, - true, - 12 - ); + 2, //expand_factor + true, // use_grinding + 12 // grinding_parameter + ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; lpc_scheme_type lpc_scheme_prover(fri_params); @@ -304,13 +304,13 @@ BOOST_AUTO_TEST_SUITE(lpc_math_polynomial_suite); typedef zk::commitments::fri fri_type; // Setup params + std::size_t degree_log = std::ceil(std::log2(d - 1)); typename fri_type::params_type fri_params( - d - 1, // max_degree - D, - generate_random_step_list(r, 5, test_global_rnd_engine), - 2, //expand_factor - lambda - ); + 5, /*max_step*/ + degree_log, + lambda, + 2 //expand_factor + ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; lpc_scheme_type lpc_scheme_prover(fri_params); @@ -396,20 +396,14 @@ BOOST_AUTO_TEST_SUITE(lpc_math_polynomial_suite); static_assert(!zk::is_commitment::value); // Setup params - constexpr static const std::size_t d_extended = d; - std::size_t extended_log = boost::static_log2::value; - std::vector>> D = - math::calculate_domain_set(extended_log, r + 1); - - // Setup params + std::size_t degree_log = std::ceil(std::log2(d - 1)); typename fri_type::params_type fri_params( - d - 1, // max_degree - D, - generate_random_step_list(r, 1, test_global_rnd_engine), - 2, //expand_factor + 1, /*max_step*/ + degree_log, lambda, - true - ); + 2, //expand_factor + true // use_grinding + ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme; lpc_scheme_type lpc_scheme_prover(fri_params); @@ -498,20 +492,16 @@ BOOST_AUTO_TEST_SUITE(lpc_params_test_suite) static_assert(!zk::is_commitment::value); static_assert(!zk::is_commitment::value); - constexpr static const std::size_t d_extended = d; - std::size_t extended_log = boost::static_log2::value; - std::vector>> D = - math::calculate_domain_set(extended_log, r); - + // Setup params + std::size_t degree_log = std::ceil(std::log2(d - 1)); typename fri_type::params_type fri_params( - d - 1, // max_degree - D, - generate_random_step_list(r, 1, test_global_rnd_engine), - 2, //expand_factor + 1, /*max_step*/ + degree_log, lambda, - true, + 2, // expand_factor + true, // use_grinding 8 - ); + ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; lpc_scheme_type lpc_scheme_prover(fri_params); @@ -595,13 +585,14 @@ BOOST_AUTO_TEST_SUITE(lpc_params_test_suite) std::vector>> D = math::calculate_domain_set(extended_log, r); + // Setup params + std::size_t degree_log = std::ceil(std::log2(d - 1)); typename fri_type::params_type fri_params( - d - 1, // max_degree - D, - generate_random_step_list(r, 1, test_global_rnd_engine), - 2, //expand_factor - lambda - ); + 1, /*max_step*/ + degree_log, + lambda, + 2 //expand_factor + ); using lpc_scheme_type = nil::crypto3::zk::commitments::lpc_commitment_scheme>; lpc_scheme_type lpc_scheme_prover(fri_params); diff --git a/proof-producer/CMakeLists.txt b/proof-producer/CMakeLists.txt index 9eefb3270e..3d5a995a9d 100644 --- a/proof-producer/CMakeLists.txt +++ b/proof-producer/CMakeLists.txt @@ -26,6 +26,26 @@ include(CMSetupVersion) cm_project(proof-producer WORKSPACE_NAME ${CMAKE_WORKSPACE_NAME} LANGUAGES CXX) +# This is useful due to some build systems (Ninja in particular) are piping +# compiler output and compiler switches it's output to plain text +option (FORCE_COLORED_OUTPUT "Always produce ANSI-colored output (GNU/Clang only)." FALSE) +if (${FORCE_COLORED_OUTPUT}) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") + add_compile_options (-fdiagnostics-color=always) + elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + add_compile_options (-fcolor-diagnostics) + endif () +endif () + +# The file compile_commands.json is generated in build directory, so LSP could +# pick it up and guess all include paths, defines and other stuff. +# If Nix is used, LSP could not guess the locations of implicit include +# directories, so we need to include them explicitly. +if(CMAKE_EXPORT_COMPILE_COMMANDS) + set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES + ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) +endif() + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake") find_package(crypto3 REQUIRED) diff --git a/proof-producer/README.md b/proof-producer/README.md index ecf9335b0b..92548d7e6d 100644 --- a/proof-producer/README.md +++ b/proof-producer/README.md @@ -1,15 +1,26 @@ # Proof producer for the =nil; Proof Market -This repository contains the proof producer for the =nil; [Proof Market](https://proof.market/), which is a part of the =nil; [zkllvm toolchain](https://github.com/NilFoundation/zkLLVM) for zk-enabled applications development. +This repository contains the proof producer for the =nil; +[Proof Market](https://proof.market/), which is a part of the =nil; +[zkllvm toolchain](https://github.com/NilFoundation/zkLLVM) for zk-enabled +applications development. # How to use -The input for the proof producer is a circified version of the algorithm to be proven. This circified version of the algorithm is generated by the [zkllvm](https://raw.githubusercontent.com/NilFoundation/zkllvm) toolchain. +The input for the proof producer is a circified version of the algorithm to be +proven. This circified version of the algorithm is generated by the +[zkllvm](https://raw.githubusercontent.com/NilFoundation/zkllvm) toolchain. -Typically, you want to use the proof producer to participate in the =nil; Proof Market. In this case, you need to have a valid account on the =nil; Proof Market, which you can create through the [Proof Market web interface](https://proof.market/) or by using the [Proof Market CLI](https://github.com/NilFoundation/proof-market-toolchain/). +Typically, you want to use the proof producer to participate in the =nil; +Proof Market. In this case, you need to have a valid account on the =nil; +Proof Market, which you can create through the +[Proof Market web interface](https://proof.market/) or by using the +[Proof Market CLI](https://github.com/NilFoundation/proof-market-toolchain/). # Installation -All parts of the zkLLVM toolchain are distributed in form of deb packages. To install them, you need to add the =nil; repository to your systems package manager: +All parts of the zkLLVM toolchain are distributed in form of deb packages. +To install them, you need to add the =nil; repository to your systems package +manager: ```bash echo 'deb [trusted=yes] http://deb.nil.foundation/ubuntu/ all main' >>/etc/apt/sources.list @@ -24,15 +35,22 @@ apt install proof-producer # Usage -The proof producer is a command line tool. To see the list of available options, run: +The proof producer is a command line tool. To see the list of available +options, run: ```bash proof-generator --help ``` -To produce a proof, you need to provide the proof producer with the file with the circuit definition and the assignment table with the values of the execution trace. You generate them from the [zkllvm examples](https://github.com/NilFoundation/zkLLVM) or download the existing ones using the [Proof Market CLI](https://github.com/NilFoundation/proof-market-toolchain/). +To produce a proof, you need to provide the proof producer with the file with +the circuit definition and the assignment table with the values of the +execution trace. You generate them from the +[zkllvm examples](https://github.com/NilFoundation/zkLLVM) or download the +existing ones using the +[Proof Market CLI](https://github.com/NilFoundation/proof-market-toolchain/). -When you have the circuit definition and the assignment table, you can produce a proof by running: +When you have the circuit definition and the assignment table, you can produce +a proof by running: ```bash proof-generator --circuit --assignment --proof @@ -42,36 +60,90 @@ proof-generator --circuit --assignment --proof # Sample calls to proof-producer -In all the calls you can change the executable name from proof-producer-single-threaded to proof-producer-multi-threaded to run on all the CPUs of your machine. +In all the calls you can change the executable name from +proof-producer-single-threaded to proof-producer-multi-threaded to run on all +the CPUs of your machine. Generate a proof and verify it: ```bash -./build/bin/proof-producer/proof-producer-single-threaded --circuit="circuit.crct" --assignment-table="assignment.tbl" --proof="proof.bin" -q 10 +./build/bin/proof-producer/proof-producer-single-threaded \ + --circuit="circuit.crct" \ + --assignment-table="assignment.tbl" \ + --proof="proof.bin" -q 10 ``` Making a call to preprocessor: ```bash -./build/bin/proof-producer/proof-producer-single-threaded --stage="preprocess" --circuit="circuit.crct" --assignment-table="assignment.tbl" --common-data="preprocessed_common_data.dat" --preprocessed-data="preprocessed.dat" --commitment-state-file="commitment_state.dat" --assignment-description-file="assignment-description.dat" -q 10 +./build/bin/proof-producer/proof-producer-single-threaded \ + --stage="preprocess" \ + --circuit="circuit.crct" \ + --assignment-table="assignment.tbl" \ + --common-data="preprocessed_common_data.dat" \ + --preprocessed-data="preprocessed.dat" \ + --commitment-state-file="commitment_state.dat" \ + --assignment-description-file="assignment-description.dat" \ + -q 10 ``` Making a call to prover: ```bash -./build/bin/proof-producer/proof-producer-single-threaded --stage="prove" --circuit="circuit.crct" --assignment-table="assignment.tbl" --common-data="preprocessed_common_data.dat" --preprocessed-data="preprocessed.dat" --commitment-state-file="commitment_state.dat" --proof="proof.bin" -q 10 +./build/bin/proof-producer/proof-producer-single-threaded \ + --stage="prove" \ + --circuit="circuit.crct" \ + --assignment-table="assignment.tbl" \ + --common-data="preprocessed_common_data.dat" \ + --preprocessed-data="preprocessed.dat" \ + --commitment-state-file="commitment_state.dat" \ + --proof="proof.bin" \ + -q 10 ``` Verify generated proof: ```bash -./build/bin/proof-producer/proof-producer-single-threaded --stage="verify" --circuit="circuit.crct" --common-data="preprocessed_common_data.dat" --proof="proof.bin" --assignment-description-file="assignment-description.dat" -q 10 +./build/bin/proof-producer/proof-producer-single-threaded \ + --stage="verify" \ + --circuit="circuit.crct" \ + --common-data="preprocessed_common_data.dat" \ + --proof="proof.bin" \ + --assignment-description-file="assignment-description.dat" \ + -q 10 +``` + +Partial proof: +```bash +./build/bin/proof-producer/proof-producer-single-threaded \ + --stage partial-prove \ + --grind-param 16 \ + --max-quotient-chunks 10 \ + --circuit circuits-and-assignments/$CIRCUIT/circuit.crct \ + --assignment-table circuits-and-assignments/$CIRCUIT/assignment.tbl \ + --common-data $CIRCUIT-common_data.dat \ + --preprocessed-data $CIRCUIT-preprocessed.dat \ + --commitment-state-file $CIRCUIT-commitment_state.dat \ + --assignment-description-file $CIRCUIT-assignment-description.dat \ + --challenge-file $CIRCUIT-challenge.dat \ + --theta-power-file $CIRCUIT-theta-power.txt \ + --proof $CIRCUIT-proof.dat \ + --json $CIRCUIT-proof.json ``` Aggregate challenges, done once on the main prover ```bash -./build/bin/proof-producer/proof-producer-single-threaded --stage="generate-aggregated-challenge" --input-challenge-files challenge1.dat challenge2.dat --aggregated-challenge-file="aggregated_challenge.dat" +./build/bin/proof-producer/proof-producer-single-threaded \ + --stage="generate-aggregated-challenge" \ + --input-challenge-files challenge1.dat \ + --input-challenge-files challenge2.dat \ + --aggregated-challenge-file="aggregated_challenge.dat" ``` Compute polynomial combined_Q, done on each prover ```bash -./build/bin/proof-producer/proof-producer-single-threaded --stage="generate-combined-Q" --aggregated-challenge-file="aggregated_challenge.dat" --combined-Q-starting-power=0 --commitment-state-file="commitment_state.dat" --combined-Q-polynomial-file="combined-Q.dat" +./build/bin/proof-producer/proof-producer-single-threaded \ + --stage="generate-combined-Q" \ + --aggregated-challenge-file="aggregated_challenge.dat" \ + --combined-Q-starting-power=0 \ + --commitment-state-file="commitment_state.dat" \ + --combined-Q-polynomial-file="combined-Q.dat" ``` diff --git a/proof-producer/bin/proof-producer/include/nil/proof-generator/arg_parser.hpp b/proof-producer/bin/proof-producer/include/nil/proof-generator/arg_parser.hpp index e678de6f64..065a26b090 100644 --- a/proof-producer/bin/proof-producer/include/nil/proof-generator/arg_parser.hpp +++ b/proof-producer/bin/proof-producer/include/nil/proof-generator/arg_parser.hpp @@ -18,6 +18,7 @@ #define PROOF_GENERATOR_ARG_PARSER_HPP #include +#include #include #include @@ -43,7 +44,12 @@ namespace nil { boost::filesystem::path circuit_file_path; boost::filesystem::path assignment_table_file_path; boost::filesystem::path assignment_description_file_path; + boost::filesystem::path challenge_file_path; + boost::filesystem::path theta_power_file_path; std::vector input_challenge_files; + std::vector partial_proof_files; + std::vector aggregated_proof_files; + boost::filesystem::path last_proof_file; boost::filesystem::path aggregated_challenge_file = "aggregated_challenge.dat"; boost::filesystem::path combined_Q_polynomial_file = "combined_Q.dat"; std::size_t combined_Q_starting_power; diff --git a/proof-producer/bin/proof-producer/include/nil/proof-generator/prover.hpp b/proof-producer/bin/proof-producer/include/nil/proof-generator/prover.hpp index 3cac0de5e1..ec29b5549b 100644 --- a/proof-producer/bin/proof-producer/include/nil/proof-generator/prover.hpp +++ b/proof-producer/bin/proof-producer/include/nil/proof-generator/prover.hpp @@ -122,7 +122,8 @@ namespace nil { {"verify", ProverStage::VERIFY}, {"generate-aggregated-challenge", ProverStage::GENERATE_AGGREGATED_CHALLENGE}, {"partial-prove", ProverStage::PARTIAL_PROVE}, - {"compute-combined-Q", ProverStage::COMPUTE_COMBINED_Q} + {"compute-combined-Q", ProverStage::COMPUTE_COMBINED_Q}, + {"merge-proofs", ProverStage::MERGE_PROOFS}, }; auto it = stage_map.find(stage); if (it == stage_map.end()) { @@ -237,6 +238,90 @@ namespace nil { return res; } + // The caller must call the preprocessor or load the preprocessed data before calling this function. + bool generate_partial_proof_to_file( + boost::filesystem::path proof_file_, + std::optional challenge_file_, + std::optional theta_power_file) { + if (!nil::proof_generator::can_write_to_file(proof_file_.string())) { + BOOST_LOG_TRIVIAL(error) << "Can't write to file " << proof_file_; + return false; + } + + BOOST_ASSERT(public_preprocessed_data_); + BOOST_ASSERT(private_preprocessed_data_); + BOOST_ASSERT(table_description_); + BOOST_ASSERT(constraint_system_); + BOOST_ASSERT(lpc_scheme_); + + BOOST_LOG_TRIVIAL(info) << "Generating proof..."; + auto prover = nil::crypto3::zk::snark::placeholder_prover( + *public_preprocessed_data_, + *private_preprocessed_data_, + *table_description_, + *constraint_system_, + *lpc_scheme_, + true); + Proof proof = prover.process(); + BOOST_LOG_TRIVIAL(info) << "Proof generated"; + + BOOST_LOG_TRIVIAL(info) << "Writing proof to " << proof_file_; + auto filled_placeholder_proof = + nil::crypto3::marshalling::types::fill_placeholder_proof(proof, lpc_scheme_->get_fri_params()); + bool res = nil::proof_generator::detail::encode_marshalling_to_file( + proof_file_, + filled_placeholder_proof, + true + ); + if (res) { + BOOST_LOG_TRIVIAL(info) << "Proof written."; + } else { + BOOST_LOG_TRIVIAL(error) << "Failed to write proof to file."; + } + + if (!challenge_file_) { + BOOST_LOG_TRIVIAL(error) << "Challenge output file is not set."; + return false; + } + if (!theta_power_file) { + BOOST_LOG_TRIVIAL(error) << "Theta power file is not set."; + return false; + } + BOOST_LOG_TRIVIAL(info) << "Writing challenge"; + using challenge_marshalling_type = + nil::crypto3::marshalling::types::field_element< + TTypeBase, typename BlueprintField::value_type>; + + challenge_marshalling_type marshalled_challenge(proof.eval_proof.challenge); + + res = detail::encode_marshalling_to_file( + *challenge_file_, marshalled_challenge); + if (res) { + BOOST_LOG_TRIVIAL(info) << "Challenge written."; + } else { + BOOST_LOG_TRIVIAL(error) << "Failed to write challenge to file."; + } + + auto commitment_scheme = prover.get_commitment_scheme(); + + commitment_scheme.state_commited(crypto3::zk::snark::FIXED_VALUES_BATCH); + commitment_scheme.state_commited(crypto3::zk::snark::VARIABLE_VALUES_BATCH); + commitment_scheme.state_commited(crypto3::zk::snark::PERMUTATION_BATCH); + commitment_scheme.state_commited(crypto3::zk::snark::QUOTIENT_BATCH); + commitment_scheme.state_commited(crypto3::zk::snark::LOOKUP_BATCH); + commitment_scheme.mark_batch_as_fixed(crypto3::zk::snark::FIXED_VALUES_BATCH); + + commitment_scheme.set_fixed_polys_values(common_data_->commitment_scheme_data); + + std::size_t theta_power = commitment_scheme.compute_theta_power_for_combined_Q(); + + auto output_file = open_file(theta_power_file->string(), std::ios_base::out); + (*output_file) << theta_power << std::endl; + output_file->close(); + + return res; + } + bool verify_from_file(boost::filesystem::path proof_file_) { create_lpc_scheme(); @@ -420,6 +505,7 @@ namespace nil { ); table_description_.emplace(table_description); assignment_table_.emplace(std::move(assignment_table)); + public_inputs_.emplace(assignment_table_->public_inputs()); return true; } @@ -588,6 +674,45 @@ namespace nil { return save_poly_to_file(combined_Q, output_combined_Q_file); } + bool merge_proofs( + const std::vector &partial_proof_files, + const std::vector &aggregated_proof_files, + const boost::filesystem::path &last_proof_file, + const boost::filesystem::path &merged_proof_file) + { + nil::crypto3::zk::snark::placeholder_aggregated_proof + merged_proof; + + for(auto const& partial_proof_file: partial_proof_files) { + using ProofMarshalling = nil::crypto3::marshalling::types:: + placeholder_proof, Proof>; + + BOOST_LOG_TRIVIAL(info) << "Reading partial proof from file \"" << partial_proof_file << "\""; + auto marshalled_proof = detail::decode_marshalling_from_file(partial_proof_file, true); + if (!marshalled_proof) { + return false; + } + auto partial_proof = nil::crypto3::marshalling::types::make_placeholder_proof(*marshalled_proof); + merged_proof.partial_proofs.emplace_back(partial_proof); + } + + for(auto const& aggregated_proof_file: aggregated_proof_files) { + + /* TODO: Need marshalling for initial_proofs (lpc_proof_type) */ + BOOST_LOG_TRIVIAL(info) << "Reading aggregated part proof from file \"" << aggregated_proof_file << "\""; + // merged_proof.aggregated_proof.intial_proofs_per_prover.emplace_back(initial_proof); + } + + /* TODO: Need marshalling for top-level proof, (fri_proof_type) */ + BOOST_LOG_TRIVIAL(info) << "Reading single round part proof from file \"" << last_proof_file << "\""; + // merged_proof.fri_proof = ... + + + BOOST_LOG_TRIVIAL(info) << "Writing merged proof to \"" << merged_proof_file << "\""; + + return true; + } + private: const std::size_t expand_factor_; const std::size_t max_quotient_chunks_; diff --git a/proof-producer/bin/proof-producer/src/arg_parser.cpp b/proof-producer/bin/proof-producer/src/arg_parser.cpp index 1f5e29dee9..12b9ec9b1d 100644 --- a/proof-producer/bin/proof-producer/src/arg_parser.cpp +++ b/proof-producer/bin/proof-producer/src/arg_parser.cpp @@ -91,12 +91,23 @@ namespace nil { ("max-quotient-chunks,q", make_defaulted_option(prover_options.max_quotient_chunks), "Maximum quotient polynomial parts amount") ("input-challenge-files,u", po::value>(&prover_options.input_challenge_files)->multitoken(), "Input challenge files. Used with 'generate-aggregated-challenge' stage.") + ("challenge-file", po::value(&prover_options.challenge_file_path), + "Input challenge files. Used with 'generate-aggregated-challenge' stage.") + ("theta-power-file", po::value(&prover_options.theta_power_file_path), + "File to output theta power. Used by main prover to arrange starting powers of Q") ("aggregated-challenge-file", po::value(&prover_options.aggregated_challenge_file), "Aggregated challenge file. Used with 'generate-aggregated-challenge' stage") ("combined-Q-polynomial-file", po::value(&prover_options.combined_Q_polynomial_file), "File containing the polynomial combined-Q, generated on a single prover.") ("combined-Q-starting-power", po::value(&prover_options.combined_Q_starting_power), - "The starting power for combined-Q polynomial for the current prover."); + "The starting power for combined-Q polynomial for the current prover.") + ("partial-proof", po::value>(&prover_options.partial_proof_files)->multitoken(), + "Partial proofs. Used with 'merge-proofs' stage.") + ("aggregated-proof", po::value>(&prover_options.aggregated_proof_files)->multitoken(), + "Parts of aggregated proof. Used with 'merge-proofs' stage.") + ("last-proof", po::value(&prover_options.last_proof_file)->multitoken(), + "Last proof of aggregated proof. Used with 'merge-proofs' stage.") + ; // clang-format on po::options_description cmdline_options("nil; Proof Producer"); diff --git a/proof-producer/bin/proof-producer/src/main.cpp b/proof-producer/bin/proof-producer/src/main.cpp index 41a5fad19d..62826a01f4 100644 --- a/proof-producer/bin/proof-producer/src/main.cpp +++ b/proof-producer/bin/proof-producer/src/main.cpp @@ -50,7 +50,7 @@ int run_prover(const nil::proof_generator::ProverOptions& prover_options) { prover.generate_to_file( prover_options.proof_file_path, prover_options.json_file_path, - false/*don't skip verification*/) && + false/*don't skip verification*/) && prover.save_preprocessed_common_data_to_file(prover_options.preprocessed_common_data_path) && prover.save_public_preprocessed_data_to_file(prover_options.preprocessed_public_data_path) && prover.save_commitment_state_to_file(prover_options.commitment_scheme_state_path); @@ -78,6 +78,20 @@ int run_prover(const nil::proof_generator::ProverOptions& prover_options) { prover_options.json_file_path, true/*skip verification*/); break; + case nil::proof_generator::detail::ProverStage::PARTIAL_PROVE: + // Load preprocessed data from file and generate the proof. + prover_result = + prover.read_circuit(prover_options.circuit_file_path) && + prover.read_assignment_table(prover_options.assignment_table_file_path) && + prover.read_public_preprocessed_data_from_file(prover_options.preprocessed_public_data_path) && + prover.read_preprocessed_common_data_from_file(prover_options.preprocessed_common_data_path) && + prover.read_commitment_scheme_from_file(prover_options.commitment_scheme_state_path) && + prover.preprocess_private_data() && + prover.generate_partial_proof_to_file( + prover_options.proof_file_path, + prover_options.challenge_file_path, + prover_options.theta_power_file_path); + break; case nil::proof_generator::detail::ProverStage::VERIFY: prover_result = prover.read_circuit(prover_options.circuit_file_path) && @@ -91,9 +105,19 @@ int run_prover(const nil::proof_generator::ProverOptions& prover_options) { prover_options.input_challenge_files, prover_options.aggregated_challenge_file ); + break; + case nil::proof_generator::detail::ProverStage::MERGE_PROOFS: + prover_result = + prover.merge_proofs( + prover_options.partial_proof_files, + prover_options.aggregated_proof_files, + prover_options.last_proof_file, + prover_options.proof_file_path); + break; } } catch (const std::exception& e) { BOOST_LOG_TRIVIAL(error) << e.what(); + throw e; return 1; } return prover_result ? 0 : 1;