Skip to content

Commit

Permalink
Implement stage 'consistency-checks'.
Browse files Browse the repository at this point in the history
  • Loading branch information
martun committed Sep 19, 2024
1 parent a478dcf commit 498376a
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,7 @@ namespace nil {
proof_type proof_eval(transcript_type &transcript) {
PROFILE_SCOPE("LPC proof_eval");

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());
}
eval_polys_and_add_roots_to_transcipt(transcript);

// Prepare z-s and combined_Q;
auto theta = transcript.template challenge<field_type>();
Expand All @@ -168,16 +160,7 @@ namespace nil {
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) {

void eval_polys_and_add_roots_to_transcipt(transcript_type &transcript) {
this->eval_polys();

BOOST_ASSERT(this->_points.size() == this->_polys.size());
Expand All @@ -187,9 +170,18 @@ namespace nil {
for (auto const& it: this->_trees) {
transcript(it.second.root());
}
}

std::vector<typename fri_type::field_type::value_type> challenges =
transcript.template challenges<typename fri_type::field_type>(this->_fri_params.lambda);
/** 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] challenges - These challenges were 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,
const std::vector<typename fri_type::field_type::value_type>& challenges) {

typename fri_type::initial_proofs_batch_type initial_proofs =
nil::crypto3::zk::algorithms::query_phase_initial_proofs<fri_type, polynomial_type>(
Expand Down Expand Up @@ -357,7 +349,6 @@ 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() {
std::size_t theta_power = 0;
this->eval_polys();
this->build_points_map();

auto points = this->get_unique_points();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,13 @@ namespace nil {
// 8. Run evaluation proofs
_proof.eval_proof.challenge = transcript.template challenge<FieldType>();
generate_evaluation_points();

if (!_skip_commitment_scheme_eval_proofs) {
_proof.eval_proof.eval_proof = _commitment_scheme.proof_eval(transcript);
} else {
// This is required for aggregated prover. If we do not run the LPC proof right now,
// we still need to push the merkle tree roots into the transcript.
_commitment_scheme.eval_polys_and_add_roots_to_transcipt(transcript);
}

return _proof;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,15 +152,7 @@ namespace nil {
proof_type proof_eval(transcript_type &transcript) {
PROFILE_SCOPE("LPC proof_eval");

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());
}
eval_polys_and_add_roots_to_transcipt(transcript);

// Prepare z-s and combined_Q;
auto theta = transcript.template challenge<field_type>();
Expand All @@ -170,28 +162,27 @@ namespace nil {
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) {

void eval_polys_and_add_roots_to_transcipt(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<typename fri_type::field_type::value_type> challenges =
transcript.template challenges<typename fri_type::field_type>(this->_fri_params.lambda);
/** 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] challenges - These challenges were 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,
const std::vector<typename fri_type::field_type::value_type>& challenges) {

typename fri_type::initial_proofs_batch_type initial_proofs =
nil::crypto3::zk::algorithms::query_phase_initial_proofs<fri_type, polynomial_type>(
Expand Down Expand Up @@ -436,7 +427,6 @@ 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() {
std::size_t theta_power = 0;
this->eval_polys();
this->build_points_map();

auto points = this->get_unique_points();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,10 @@ namespace nil {
generate_evaluation_points();
if (!_skip_commitment_scheme_eval_proofs) {
_proof.eval_proof.eval_proof = _commitment_scheme.proof_eval(transcript);
} else {
// This is required for aggregated prover. If we do not run the LPC proof right now,
// we still need to push the merkle tree roots into the transcript.
_commitment_scheme.eval_polys_and_add_roots_to_transcipt(transcript);
}

return _proof;
Expand Down
30 changes: 23 additions & 7 deletions proof-producer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ 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.

## Using proof-producer to generate and verify a single proof

Generate a proof and verify it:
```bash
./build/bin/proof-producer/proof-producer-single-threaded \
Expand Down Expand Up @@ -111,7 +113,9 @@ Verify generated proof:
-q 10
```

Partial proof:
## Using proof-producer to generate and verify an aggregated proof.

Partial proof, ran on each prover.
```bash
./build/bin/proof-producer/proof-producer-single-threaded \
--stage partial-prove \
Expand All @@ -129,7 +133,7 @@ Partial proof:
--json $CIRCUIT-proof.json
```

Aggregate challenges, done once on the main prover
Aggregate challenges, done once on the main prover.
```bash
./build/bin/proof-producer/proof-producer-single-threaded \
--stage="generate-aggregated-challenge" \
Expand All @@ -138,23 +142,35 @@ Aggregate challenges, done once on the main prover
--aggregated-challenge-file="aggregated_challenge.dat"
```

Compute polynomial combined_Q, done on each prover
Compute polynomial combined_Q, done on each prover. Please notice that the caller must provide the correct value of --combined-Q-starting-power, which can be taken from "$CIRCUIT-theta-power.txt" generated on stage "partial-prove".
```bash
./build/bin/proof-producer/proof-producer-single-threaded \
--stage="compute-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"
--commitment-state-file="$CIRCUIT-commitment_state.dat" \
--combined-Q-polynomial-file="$CIRCUIT-combined-Q.dat"
```

Compute aggregated FRI proof done once on the main prover. This is a part of the complete proof.
Compute aggregated FRI proof done once on the main prover. This is a part of the complete proof. The '--assignment-description-file' can point to any description file, since only the number of rows matters.
```bash
./build/bin/proof-producer/proof-producer-single-threaded \
--stage="aggregated-FRI" \
--assignment-description-file="assignment-description.dat"
--aggregated-challenge-file="aggregated_challenge.dat" \
--input-combined-Q-polynomial-files "combined-Q-1.dat" "combined-Q-2.dat" \
--input-combined-Q-polynomial-files "$CIRCUIT1-combined-Q.dat" "$CIRCUIT2_combined-Q.dat" \
--proof="aggregated_FRI_proof.bin" \
--proof-of-work-file="POW.dat" \
--consistency-checks-challenges-file="challenges.dat"
```

Compute LPC consistency check proofs for polynomial combined_Q, done on each prover.
```bash
./build/bin/proof-producer/proof-producer-single-threaded \
--stage="consistency-checks" \
--commitment-state-file="$CIRCUIT-commitment_scheme_state.dat" \
--combined-Q-polynomial-file="$CIRCUIT-combined-Q.dat" \
--consistency-checks-challenges-file="challenges.dat" \
--proof="$CIRCUIT-LPC_consistency_check_proof.bin"
```

Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ namespace nil {
PARTIAL_PROVE = 5,
COMPUTE_COMBINED_Q = 6,
GENERATE_AGGREGATED_FRI_PROOF = 7,
GENERATE_LPC_INITIAL_PROOF = 8,
GENERATE_CONSISTENCY_CHECKS_PROOF = 8,
MERGE_PROOFS = 9
};

Expand All @@ -124,7 +124,8 @@ namespace nil {
{"partial-prove", ProverStage::PARTIAL_PROVE},
{"compute-combined-Q", ProverStage::COMPUTE_COMBINED_Q},
{"merge-proofs", ProverStage::MERGE_PROOFS},
{"aggregated-FRI", ProverStage::GENERATE_AGGREGATED_FRI_PROOF}
{"aggregated-FRI", ProverStage::GENERATE_AGGREGATED_FRI_PROOF},
{"consistency-checks", ProverStage::GENERATE_CONSISTENCY_CHECKS_PROOF}
};
auto it = stage_map.find(stage);
if (it == stage_map.end()) {
Expand Down Expand Up @@ -768,7 +769,7 @@ namespace nil {

bool save_challenge_vector_to_file(
const std::vector<typename BlueprintField::value_type>& challenges,
const boost::filesystem::path &consistency_checks_challenges_output_file) {
const boost::filesystem::path& consistency_checks_challenges_output_file) {

using challenge_vector_marshalling_type = nil::crypto3::marshalling::types::field_element_vector<
typename BlueprintField::value_type, TTypeBase>;
Expand All @@ -783,6 +784,28 @@ namespace nil {
consistency_checks_challenges_output_file, marshalled_challenges);
}

std::optional<std::vector<typename BlueprintField::value_type>> read_challenge_vector_from_file(
const boost::filesystem::path& input_file) {

using challenge_vector_marshalling_type = nil::crypto3::marshalling::types::field_element_vector<
typename BlueprintField::value_type, TTypeBase>;

if (!nil::proof_generator::can_read_from_file(input_file.string())) {
BOOST_LOG_TRIVIAL(error) << "Can't read file " << input_file;
return std::nullopt;
}

auto marshalled_challenges = detail::decode_marshalling_from_file<challenge_vector_marshalling_type>(
input_file);

if (!marshalled_challenges) {
return std::nullopt;
}

return nil::crypto3::marshalling::types::make_field_element_vector<
typename BlueprintField::value_type, Endianness>(marshalled_challenges.value());
}

bool generate_aggregated_FRI_proof_to_file(
const boost::filesystem::path &aggregated_challenge_file,
const std::vector<boost::filesystem::path>& input_combined_Q_polynomial_files,
Expand Down Expand Up @@ -824,6 +847,41 @@ namespace nil {
save_challenge_vector_to_file(challenges, consistency_checks_challenges_output_file);
}

bool save_lpc_consistency_proof_to_file(
const typename LpcScheme::lpc_proof_type& lpc_consistency_proof,
const boost::filesystem::path &output_file) {
// TODO(martun): consider changinge the class name 'inital_eval_proof'.
using lpc_consistency_proof_marshalling_type = nil::crypto3::marshalling::types::inital_eval_proof<
TTypeBase, LpcScheme>;

BOOST_LOG_TRIVIAL(info) << "Writing LPC consistency proof to " << output_file << std::endl;

lpc_consistency_proof_marshalling_type marshalled_proof = nil::crypto3::marshalling::types::fill_initial_eval_proof<Endianness, LpcScheme>(lpc_consistency_proof);

return detail::encode_marshalling_to_file<lpc_consistency_proof_marshalling_type>(
output_file, marshalled_proof);
}

bool generate_consistency_checks_to_file(
const boost::filesystem::path& combined_Q_file,
const boost::filesystem::path& consistency_checks_challenges_output_file,
const boost::filesystem::path& output_proof_file) {

std::optional<std::vector<typename BlueprintField::value_type>> challenges = read_challenge_vector_from_file(
consistency_checks_challenges_output_file);
if (!challenges)
return false;

std::optional<polynomial_type> combined_Q = read_poly_from_file<polynomial_type>(combined_Q_file);
if (!combined_Q)
return false;

typename LpcScheme::lpc_proof_type proof = lpc_scheme_->proof_eval_lpc_proof(
combined_Q.value(), challenges.value());

return save_lpc_consistency_proof_to_file(proof, output_proof_file);
}

private:
const std::size_t expand_factor_;
const std::size_t max_quotient_chunks_;
Expand Down
2 changes: 1 addition & 1 deletion proof-producer/bin/proof-producer/src/arg_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ namespace nil {
// clang-format off
auto options_appender = config.add_options()
("stage", make_defaulted_option(prover_options.stage),
"Stage of the prover to run, one of (all, preprocess, prove, verify, generate-aggregated-challenge, generate-combined-Q, aggregated-FRI). Defaults to 'all'.")
"Stage of the prover to run, one of (all, preprocess, prove, verify, generate-aggregated-challenge, generate-combined-Q, aggregated-FRI, consistency-checks). Defaults to 'all'.")
("proof,p", make_defaulted_option(prover_options.proof_file_path), "Proof file")
("json,j", make_defaulted_option(prover_options.json_file_path), "JSON proof file")
("common-data", make_defaulted_option(prover_options.preprocessed_common_data_path), "Preprocessed common data file")
Expand Down
9 changes: 9 additions & 0 deletions proof-producer/bin/proof-producer/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ int run_prover(const nil::proof_generator::ProverOptions& prover_options) {
prover_options.proof_of_work_output_file,
prover_options.consistency_checks_challenges_file);
break;
case nil::proof_generator::detail::ProverStage::GENERATE_CONSISTENCY_CHECKS_PROOF:
prover_result =
prover.read_commitment_scheme_from_file(prover_options.commitment_scheme_state_path) &&
prover.generate_consistency_checks_to_file(
prover_options.combined_Q_polynomial_file,
prover_options.consistency_checks_challenges_file,
prover_options.proof_file_path
);
break;
}
} catch (const std::exception& e) {
BOOST_LOG_TRIVIAL(error) << e.what();
Expand Down

0 comments on commit 498376a

Please sign in to comment.