Skip to content

Commit

Permalink
plonk: initial implementation of transcript hasher, addressing issue #56
Browse files Browse the repository at this point in the history
 and PR #61.
  • Loading branch information
Vesselin Velichkov committed Aug 17, 2022
1 parent ee34c38 commit 2fbad61
Show file tree
Hide file tree
Showing 7 changed files with 452 additions and 78 deletions.
30 changes: 25 additions & 5 deletions libsnark/zk_proof_systems/plonk/prover.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,11 +269,15 @@ template<typename ppT> class plonk_prover
/// \param[out] W_polys_blinded_at_secret_g1: the blinded witness
/// polynomials evaluated at the secret input denoted
/// [a]_1, [b]_1, [c]_1 in [GWC19]
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
static round_one_out_t<ppT> round_one(
const round_zero_out_t<ppT> &round_zero_out,
const std::vector<libff::Fr<ppT>> &blind_scalars,
const std::vector<libff::Fr<ppT>> &witness,
const srs<ppT> &srs);
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher);

/// Prover Round 2
///
Expand All @@ -289,13 +293,17 @@ template<typename ppT> class plonk_prover
/// \param[out] z_poly: blinded accumulator poly z(x)
/// \param[out] z_poly_at_secret_g1: blinded accumulator poly z(x)
/// evaluated at secret
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
static round_two_out_t<ppT> round_two(
const libff::Fr<ppT> &beta,
const libff::Fr<ppT> &gamma,
const round_zero_out_t<ppT> &round_zero_out,
const std::vector<libff::Fr<ppT>> blind_scalars,
const std::vector<libff::Fr<ppT>> &witness,
const srs<ppT> &srs);
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher);

/// Prover Round 3
///
Expand All @@ -318,14 +326,18 @@ template<typename ppT> class plonk_prover
/// input zeta i.e. t(zeta)
/// \param[out] z_poly_xomega: the polynomial z(x*w) i.e. z(x) shifted
/// by w
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
static round_three_out_t<ppT> round_three(
const libff::Fr<ppT> &alpha,
const libff::Fr<ppT> &beta,
const libff::Fr<ppT> &gamma,
const round_zero_out_t<ppT> &round_zero_out,
const round_one_out_t<ppT> &round_one_out,
const round_two_out_t<ppT> &round_two_out,
const srs<ppT> &srs);
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher);

/// Prover Round 4
///
Expand Down Expand Up @@ -358,11 +370,15 @@ template<typename ppT> class plonk_prover
/// Python reference implementation does, so we do the
/// same in order to match the test vectors. TODO can
/// remove t_zeta in the future
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
static round_four_out_t<ppT> round_four(
const libff::Fr<ppT> &zeta,
const round_one_out_t<ppT> &round_one_out,
const round_three_out_t<ppT> &round_three_out,
const srs<ppT> &srs);
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher);

/// Prover Round 5
///
Expand Down Expand Up @@ -408,6 +424,9 @@ template<typename ppT> class plonk_prover
/// \param[out] W_zeta_omega_at_secret: commitment to opening proof
/// polynomial W_{zeta omega}(x) at secert input
/// i.e. [W_{zeta omega}(secret)]_1
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
static round_five_out_t<ppT> round_five(
const libff::Fr<ppT> &alpha,
const libff::Fr<ppT> &beta,
Expand All @@ -419,7 +438,8 @@ template<typename ppT> class plonk_prover
const round_two_out_t<ppT> &round_two_out,
const round_three_out_t<ppT> &round_three_out,
const round_four_out_t<ppT> &round_four_out,
const srs<ppT> &srs);
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher);

/// Prover compute SNARK proof
///
Expand Down
85 changes: 72 additions & 13 deletions libsnark/zk_proof_systems/plonk/prover.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,16 @@ round_one_out_t<ppT>::round_one_out_t(
/// \param[out] W_polys_blinded_at_secret_g1: the blinded witness
/// polynomials evaluated at the secret input denoted
/// [a]_1, [b]_1, [c]_1 in [GWC19]
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
template<typename ppT>
round_one_out_t<ppT> plonk_prover<ppT>::round_one(
const round_zero_out_t<ppT> &round_zero_out,
const std::vector<libff::Fr<ppT>> &blind_scalars,
const std::vector<libff::Fr<ppT>> &witness,
const srs<ppT> &srs)
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher)
{
using Field = libff::Fr<ppT>;
const size_t nwitness = NUM_HSETS;
Expand Down Expand Up @@ -140,6 +144,11 @@ round_one_out_t<ppT> plonk_prover<ppT>::round_one(
plonk_evaluate_polys_at_secret_G1<ppT>(
srs.secret_powers_g1, W_polys_blinded, W_polys_blinded_at_secret_g1);

// add outputs from Round 1 to the hash buffer
hasher.add_element(W_polys_blinded_at_secret_g1[a]);
hasher.add_element(W_polys_blinded_at_secret_g1[b]);
hasher.add_element(W_polys_blinded_at_secret_g1[c]);

round_one_out_t<ppT> round_one_out(
std::move(W_polys),
std::move(W_polys_blinded),
Expand Down Expand Up @@ -170,14 +179,18 @@ round_two_out_t<ppT>::round_two_out_t(
/// \param[out] z_poly: blinded accumulator poly z(x)
/// \param[out] z_poly_at_secret_g1: blinded accumulator poly z(x)
/// evaluated at secret
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
template<typename ppT>
round_two_out_t<ppT> plonk_prover<ppT>::round_two(
const libff::Fr<ppT> &beta,
const libff::Fr<ppT> &gamma,
const round_zero_out_t<ppT> &round_zero_out,
const std::vector<libff::Fr<ppT>> blind_scalars,
const std::vector<libff::Fr<ppT>> &witness,
const srs<ppT> &srs)
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher)
{
using Field = libff::Fr<ppT>;

Expand Down Expand Up @@ -212,6 +225,9 @@ round_two_out_t<ppT> plonk_prover<ppT>::round_two(
z_poly_at_secret_g1 =
plonk_evaluate_poly_at_secret_G1<ppT>(srs.secret_powers_g1, z_poly);

// add outputs from Round 2 to the hash buffer
hasher.add_element(z_poly_at_secret_g1);

round_two_out_t<ppT> round_two_out(
std::move(z_poly), std::move(z_poly_at_secret_g1));

Expand Down Expand Up @@ -253,6 +269,9 @@ round_three_out_t<ppT>::round_three_out_t(
/// input zeta i.e. t(zeta)
/// \param[out] z_poly_xomega: the polynomial z(x*w) i.e. z(x) shifted
/// by w
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
template<typename ppT>
round_three_out_t<ppT> plonk_prover<ppT>::round_three(
const libff::Fr<ppT> &alpha,
Expand All @@ -261,7 +280,8 @@ round_three_out_t<ppT> plonk_prover<ppT>::round_three(
const round_zero_out_t<ppT> &round_zero_out,
const round_one_out_t<ppT> &round_one_out,
const round_two_out_t<ppT> &round_two_out,
const srs<ppT> &srs)
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher)
{
using Field = libff::Fr<ppT>;
int num_hgen = NUM_HSETS;
Expand Down Expand Up @@ -473,6 +493,11 @@ round_three_out_t<ppT> plonk_prover<ppT>::round_three(
srs.secret_powers_g1, t_poly[i]);
}

// add outputs from Round 3 to the hash buffer
hasher.add_element(t_poly_at_secret_g1[lo]);
hasher.add_element(t_poly_at_secret_g1[mid]);
hasher.add_element(t_poly_at_secret_g1[hi]);

round_three_out_t<ppT> round_three_out(
std::move(z_poly_xomega),
std::move(t_poly),
Expand Down Expand Up @@ -533,12 +558,16 @@ round_four_out_t<ppT>::round_four_out_t(
/// Python reference implementation \[PlonkPy] does, so we
/// do the same in order to match the test vectors. TODO
/// can remove t_zeta in the future
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
template<typename ppT>
round_four_out_t<ppT> plonk_prover<ppT>::round_four(
const libff::Fr<ppT> &zeta,
const round_one_out_t<ppT> &round_one_out,
const round_three_out_t<ppT> &round_three_out,
const srs<ppT> &srs)
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher)
{
using Field = libff::Fr<ppT>;

Expand Down Expand Up @@ -568,6 +597,14 @@ round_four_out_t<ppT> plonk_prover<ppT>::round_four(
round_three_out.z_poly_xomega,
zeta);

// add outputs from Round 4 to the hash buffer
hasher.add_element(a_zeta);
hasher.add_element(b_zeta);
hasher.add_element(c_zeta);
hasher.add_element(S_0_zeta);
hasher.add_element(S_1_zeta);
hasher.add_element(z_poly_xomega_zeta);

round_four_out_t<ppT> round_four_out(
std::move(a_zeta),
std::move(b_zeta),
Expand Down Expand Up @@ -636,6 +673,9 @@ round_five_out_t<ppT>::round_five_out_t(
/// \param[out] W_zeta_omega_at_secret: commitment to opening proof
/// polynomial W_{zeta omega}(x) at secert input
/// i.e. [W_{zeta omega}(secret)]_1
/// \param[out] transcript_hasher: accumulates the communication
/// transcript into a buffer to be hashed after prover
/// rounds 1,2,3,4,5 (cf. fiat-shamir heuristic).
template<typename ppT>
round_five_out_t<ppT> plonk_prover<ppT>::round_five(
const libff::Fr<ppT> &alpha,
Expand All @@ -648,7 +688,8 @@ round_five_out_t<ppT> plonk_prover<ppT>::round_five(
const round_two_out_t<ppT> &round_two_out,
const round_three_out_t<ppT> &round_three_out,
const round_four_out_t<ppT> &round_four_out,
const srs<ppT> &srs)
const srs<ppT> &srs,
transcript_hasher<ppT> &hasher)
{
using Field = libff::Fr<ppT>;
polynomial<Field> remainder;
Expand Down Expand Up @@ -920,6 +961,11 @@ round_five_out_t<ppT> plonk_prover<ppT>::round_five(
W_zeta_omega_at_secret = plonk_evaluate_poly_at_secret_G1<ppT>(
srs.secret_powers_g1, W_zeta_omega);

// add outputs from Round 5 to the hash buffer
hasher.add_element(r_zeta);
hasher.add_element(W_zeta_at_secret);
hasher.add_element(W_zeta_omega_at_secret);

round_five_out_t<ppT> round_five_out(
std::move(r_zeta),
std::move(W_zeta_at_secret),
Expand Down Expand Up @@ -1016,28 +1062,40 @@ plonk_proof<ppT> plonk_prover<ppT>::compute_proof(

// Prover Round 1
printf("[%s:%d] Prover Round 1...\n", __FILE__, __LINE__);
round_one_out_t<ppT> round_one_out =
plonk_prover::round_one(round_zero_out, blind_scalars, witness, srs);
round_one_out_t<ppT> round_one_out = plonk_prover::round_one(
round_zero_out, blind_scalars, witness, srs, hasher);

printf("[%s:%d] Prover Round 2...\n", __FILE__, __LINE__);
// - beta, gamma: permutation challenges - hashes of transcript of round 1
// - beta: permutation challenges - hashes of transcript of round
// 1 (\attention the original protocl appends a 0, while we don't
// append anyhting to avoid making a copy of the buffer)
const libff::Fr<ppT> beta = hasher.get_hash();
// - gamma: permutation challenges - hashes of transcript of round
// 1 with 1 appended
hasher.add_element(libff::Fr<ppT>::one());
const libff::Fr<ppT> gamma = hasher.get_hash();

round_two_out_t<ppT> round_two_out = plonk_prover::round_two(
beta, gamma, round_zero_out, blind_scalars, witness, srs);
beta, gamma, round_zero_out, blind_scalars, witness, srs, hasher);

printf("[%s:%d] Prover Round 3...\n", __FILE__, __LINE__);
// - alpha: quotient challenge - hash of transcript of rounds 1,2
const libff::Fr<ppT> alpha = hasher.get_hash();
round_three_out_t<ppT> round_three_out = plonk_prover::round_three(
alpha, beta, gamma, round_zero_out, round_one_out, round_two_out, srs);
alpha,
beta,
gamma,
round_zero_out,
round_one_out,
round_two_out,
srs,
hasher);

printf("[%s:%d] Prover Round 4...\n", __FILE__, __LINE__);
// - zeta: evaluation challenge - hash of transcriptof rounds 1,2,3
const libff::Fr<ppT> zeta = hasher.get_hash();
round_four_out_t<ppT> round_four_out =
plonk_prover::round_four(zeta, round_one_out, round_three_out, srs);
round_four_out_t<ppT> round_four_out = plonk_prover::round_four(
zeta, round_one_out, round_three_out, srs, hasher);

printf("[%s:%d] Prover Round 5...\n", __FILE__, __LINE__);
/// - nu: opening challenge -- hash of transcript (denoted by v in
Expand All @@ -1054,7 +1112,8 @@ plonk_proof<ppT> plonk_prover<ppT>::compute_proof(
round_two_out,
round_three_out,
round_four_out,
srs);
srs,
hasher);

// TODO: activate this part when we implement actual hashing of
// communication transcripts
Expand Down
Loading

0 comments on commit 2fbad61

Please sign in to comment.