2021-03-25 15:20:14 -07:00
|
|
|
use std::time::Instant;
|
|
|
|
|
|
|
|
|
|
use log::info;
|
2021-03-28 15:36:51 -07:00
|
|
|
use rayon::prelude::*;
|
2021-03-25 15:20:14 -07:00
|
|
|
|
2021-03-30 13:30:31 -07:00
|
|
|
use crate::circuit_data::{CommonCircuitData, ProverOnlyCircuitData};
|
2021-05-18 15:22:06 +02:00
|
|
|
use crate::field::extension_field::Extendable;
|
2021-05-10 13:10:40 +02:00
|
|
|
use crate::field::fft::ifft;
|
2021-02-09 21:25:21 -08:00
|
|
|
use crate::field::field::Field;
|
2021-03-21 11:17:00 -07:00
|
|
|
use crate::generator::generate_partial_witness;
|
2021-04-01 13:22:54 -07:00
|
|
|
use crate::plonk_challenger::Challenger;
|
2021-06-08 21:23:52 -07:00
|
|
|
use crate::plonk_common::eval_vanishing_poly_base;
|
2021-05-18 16:06:47 +02:00
|
|
|
use crate::polynomial::commitment::ListPolynomialCommitment;
|
2021-03-30 20:16:20 -07:00
|
|
|
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
2021-05-10 13:10:40 +02:00
|
|
|
use crate::proof::Proof;
|
2021-05-14 07:33:46 -07:00
|
|
|
use crate::timed;
|
2021-05-10 13:10:40 +02:00
|
|
|
use crate::util::transpose;
|
2021-05-30 13:25:53 -07:00
|
|
|
use crate::vars::EvaluationVarsBase;
|
2021-03-21 11:57:33 -07:00
|
|
|
use crate::wire::Wire;
|
2021-03-21 11:17:00 -07:00
|
|
|
use crate::witness::PartialWitness;
|
2021-02-09 21:25:21 -08:00
|
|
|
|
2021-05-11 09:56:21 +02:00
|
|
|
/// Corresponds to constants - sigmas - wires - zs - quotient — polynomial commitments.
|
|
|
|
|
pub const PLONK_BLINDING: [bool; 5] = [false, false, true, true, true];
|
|
|
|
|
|
2021-05-30 13:25:53 -07:00
|
|
|
pub(crate) fn prove<F: Extendable<D>, const D: usize>(
|
2021-02-09 21:25:21 -08:00
|
|
|
prover_data: &ProverOnlyCircuitData<F>,
|
2021-05-30 13:25:53 -07:00
|
|
|
common_data: &CommonCircuitData<F, D>,
|
2021-03-21 11:17:00 -07:00
|
|
|
inputs: PartialWitness<F>,
|
2021-05-18 15:44:50 +02:00
|
|
|
) -> Proof<F, D> {
|
2021-05-07 11:30:03 +02:00
|
|
|
let fri_config = &common_data.config.fri_config;
|
|
|
|
|
|
2021-03-30 23:47:29 -07:00
|
|
|
let start_proof_gen = Instant::now();
|
|
|
|
|
|
|
|
|
|
let mut witness = inputs;
|
2021-03-25 15:20:14 -07:00
|
|
|
info!("Running {} generators", prover_data.generators.len());
|
2021-05-07 11:30:03 +02:00
|
|
|
timed!(
|
2021-06-23 13:46:19 +02:00
|
|
|
generate_partial_witness(&mut witness, &prover_data.generators,),
|
2021-05-07 11:30:03 +02:00
|
|
|
"to generate witness"
|
2021-04-21 22:31:45 +02:00
|
|
|
);
|
2021-03-21 11:17:00 -07:00
|
|
|
|
2021-05-07 11:30:03 +02:00
|
|
|
let config = &common_data.config;
|
2021-03-21 11:57:33 -07:00
|
|
|
let num_wires = config.num_wires;
|
2021-05-14 08:07:00 -07:00
|
|
|
let num_challenges = config.num_challenges;
|
2021-04-01 13:22:54 -07:00
|
|
|
let quotient_degree = common_data.quotient_degree();
|
2021-03-25 15:20:14 -07:00
|
|
|
|
2021-03-30 10:02:00 -07:00
|
|
|
let degree = common_data.degree();
|
2021-05-07 11:30:03 +02:00
|
|
|
let wires_polynomials: Vec<PolynomialCoeffs<F>> = timed!(
|
|
|
|
|
(0..num_wires)
|
|
|
|
|
.into_par_iter()
|
|
|
|
|
.map(|i| compute_wire_polynomial(i, &witness, degree))
|
|
|
|
|
.collect(),
|
|
|
|
|
"to compute wire polynomials"
|
2021-04-21 22:31:45 +02:00
|
|
|
);
|
2021-03-25 15:20:14 -07:00
|
|
|
|
2021-03-30 10:02:00 -07:00
|
|
|
// TODO: Could try parallelizing the transpose, or not doing it explicitly, instead having
|
|
|
|
|
// merkle_root_bit_rev_order do it implicitly.
|
2021-05-07 11:30:03 +02:00
|
|
|
let wires_commitment = timed!(
|
2021-05-11 09:56:21 +02:00
|
|
|
ListPolynomialCommitment::new(wires_polynomials, fri_config.rate_bits, true),
|
2021-05-07 11:30:03 +02:00
|
|
|
"to compute wires commitment"
|
2021-04-21 22:31:45 +02:00
|
|
|
);
|
2021-03-21 11:57:33 -07:00
|
|
|
|
2021-03-31 21:15:24 -07:00
|
|
|
let mut challenger = Challenger::new();
|
2021-04-22 16:32:57 -07:00
|
|
|
// Observe the instance.
|
|
|
|
|
// TODO: Need to include public inputs as well.
|
|
|
|
|
challenger.observe_hash(&common_data.circuit_digest);
|
|
|
|
|
|
2021-05-06 23:14:37 +02:00
|
|
|
challenger.observe_hash(&wires_commitment.merkle_tree.root);
|
2021-05-14 08:07:00 -07:00
|
|
|
let betas = challenger.get_n_challenges(num_challenges);
|
|
|
|
|
let gammas = challenger.get_n_challenges(num_challenges);
|
2021-03-31 21:15:24 -07:00
|
|
|
|
2021-05-07 11:30:03 +02:00
|
|
|
let plonk_z_vecs = timed!(compute_zs(&common_data), "to compute Z's");
|
2021-03-30 23:47:29 -07:00
|
|
|
|
2021-05-07 11:30:03 +02:00
|
|
|
let plonk_zs_commitment = timed!(
|
2021-05-11 09:56:21 +02:00
|
|
|
ListPolynomialCommitment::new(plonk_z_vecs, fri_config.rate_bits, true),
|
2021-05-07 11:30:03 +02:00
|
|
|
"to commit to Z's"
|
2021-04-21 22:31:45 +02:00
|
|
|
);
|
2021-03-28 15:36:51 -07:00
|
|
|
|
2021-05-06 23:14:37 +02:00
|
|
|
challenger.observe_hash(&plonk_zs_commitment.merkle_tree.root);
|
2021-03-31 21:15:24 -07:00
|
|
|
|
2021-05-14 08:07:00 -07:00
|
|
|
let alphas = challenger.get_n_challenges(num_challenges);
|
2021-03-31 21:15:24 -07:00
|
|
|
|
2021-05-07 11:30:03 +02:00
|
|
|
let vanishing_polys = timed!(
|
|
|
|
|
compute_vanishing_polys(
|
|
|
|
|
common_data,
|
|
|
|
|
prover_data,
|
2021-05-07 16:22:13 +02:00
|
|
|
&wires_commitment,
|
|
|
|
|
&plonk_zs_commitment,
|
2021-05-07 11:30:03 +02:00
|
|
|
&betas,
|
|
|
|
|
&gammas,
|
|
|
|
|
&alphas,
|
|
|
|
|
),
|
|
|
|
|
"to compute vanishing polys"
|
2021-04-21 22:31:45 +02:00
|
|
|
);
|
2021-04-01 13:22:54 -07:00
|
|
|
|
|
|
|
|
// Compute the quotient polynomials, aka `t` in the Plonk paper.
|
2021-05-23 22:21:27 -07:00
|
|
|
let all_quotient_poly_chunks = timed!(
|
|
|
|
|
vanishing_polys
|
|
|
|
|
.into_par_iter()
|
|
|
|
|
.flat_map(|vanishing_poly| {
|
2021-05-07 11:30:03 +02:00
|
|
|
let vanishing_poly_coeff = ifft(vanishing_poly);
|
2021-05-12 11:20:47 -07:00
|
|
|
let quotient_poly_coeff = vanishing_poly_coeff.divide_by_z_h(degree);
|
2021-05-07 11:30:03 +02:00
|
|
|
// Split t into degree-n chunks.
|
2021-05-23 22:21:27 -07:00
|
|
|
quotient_poly_coeff.chunks(degree)
|
|
|
|
|
})
|
|
|
|
|
.collect(),
|
|
|
|
|
"to compute quotient polys"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let quotient_polys_commitment = timed!(
|
|
|
|
|
ListPolynomialCommitment::new(all_quotient_poly_chunks, fri_config.rate_bits, true),
|
|
|
|
|
"to commit to quotient polys"
|
2021-04-21 22:31:45 +02:00
|
|
|
);
|
2021-03-30 11:46:58 -07:00
|
|
|
|
2021-05-11 10:01:35 +02:00
|
|
|
challenger.observe_hash("ient_polys_commitment.merkle_tree.root);
|
2021-05-06 23:14:37 +02:00
|
|
|
|
2021-05-31 17:49:04 +02:00
|
|
|
let zeta = challenger.get_extension_challenge();
|
2021-05-06 23:14:37 +02:00
|
|
|
|
2021-06-08 21:23:52 -07:00
|
|
|
let (opening_proof, mut openings) = timed!(
|
2021-05-31 17:49:04 +02:00
|
|
|
ListPolynomialCommitment::open_plonk(
|
2021-05-07 16:49:27 +02:00
|
|
|
&[
|
|
|
|
|
&prover_data.constants_commitment,
|
|
|
|
|
&prover_data.sigmas_commitment,
|
|
|
|
|
&wires_commitment,
|
|
|
|
|
&plonk_zs_commitment,
|
|
|
|
|
"ient_polys_commitment,
|
|
|
|
|
],
|
2021-05-31 17:49:04 +02:00
|
|
|
zeta,
|
2021-05-07 16:49:27 +02:00
|
|
|
&mut challenger,
|
2021-05-11 09:56:21 +02:00
|
|
|
&common_data.config.fri_config
|
2021-05-07 16:49:27 +02:00
|
|
|
),
|
|
|
|
|
"to compute opening proofs"
|
2021-05-06 23:14:37 +02:00
|
|
|
);
|
2021-04-06 19:11:21 -07:00
|
|
|
|
2021-04-21 22:31:45 +02:00
|
|
|
info!(
|
|
|
|
|
"{:.3}s for overall witness & proof generation",
|
|
|
|
|
start_proof_gen.elapsed().as_secs_f32()
|
|
|
|
|
);
|
2021-03-21 11:57:33 -07:00
|
|
|
|
2021-03-30 10:02:00 -07:00
|
|
|
Proof {
|
2021-05-06 23:14:37 +02:00
|
|
|
wires_root: wires_commitment.merkle_tree.root,
|
|
|
|
|
plonk_zs_root: plonk_zs_commitment.merkle_tree.root,
|
|
|
|
|
quotient_polys_root: quotient_polys_commitment.merkle_tree.root,
|
2021-03-21 11:57:33 -07:00
|
|
|
openings,
|
2021-05-07 16:22:13 +02:00
|
|
|
opening_proof,
|
2021-03-21 11:57:33 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 13:25:53 -07:00
|
|
|
fn compute_zs<F: Extendable<D>, const D: usize>(
|
|
|
|
|
common_data: &CommonCircuitData<F, D>,
|
|
|
|
|
) -> Vec<PolynomialCoeffs<F>> {
|
2021-05-14 08:07:00 -07:00
|
|
|
(0..common_data.config.num_challenges)
|
2021-03-28 15:36:51 -07:00
|
|
|
.map(|i| compute_z(common_data, i))
|
|
|
|
|
.collect()
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-30 13:25:53 -07:00
|
|
|
fn compute_z<F: Extendable<D>, const D: usize>(
|
|
|
|
|
common_data: &CommonCircuitData<F, D>,
|
|
|
|
|
_i: usize,
|
|
|
|
|
) -> PolynomialCoeffs<F> {
|
2021-05-06 23:14:37 +02:00
|
|
|
PolynomialCoeffs::zero(common_data.degree()) // TODO
|
2021-03-28 15:36:51 -07:00
|
|
|
}
|
|
|
|
|
|
2021-05-30 13:25:53 -07:00
|
|
|
fn compute_vanishing_polys<F: Extendable<D>, const D: usize>(
|
|
|
|
|
common_data: &CommonCircuitData<F, D>,
|
2021-03-28 15:36:51 -07:00
|
|
|
prover_data: &ProverOnlyCircuitData<F>,
|
2021-05-07 16:22:13 +02:00
|
|
|
wires_commitment: &ListPolynomialCommitment<F>,
|
|
|
|
|
plonk_zs_commitment: &ListPolynomialCommitment<F>,
|
2021-04-23 14:25:24 -07:00
|
|
|
betas: &[F],
|
|
|
|
|
gammas: &[F],
|
2021-04-01 13:22:54 -07:00
|
|
|
alphas: &[F],
|
|
|
|
|
) -> Vec<PolynomialValues<F>> {
|
2021-03-28 15:36:51 -07:00
|
|
|
let lde_size = common_data.lde_size();
|
|
|
|
|
let lde_gen = common_data.lde_generator();
|
2021-05-14 08:07:00 -07:00
|
|
|
let num_challenges = common_data.config.num_challenges;
|
2021-03-28 15:36:51 -07:00
|
|
|
|
2021-04-01 13:46:24 -07:00
|
|
|
let points = F::cyclic_subgroup_known_order(lde_gen, lde_size);
|
2021-04-21 22:31:45 +02:00
|
|
|
let values: Vec<Vec<F>> = points
|
2021-05-07 16:49:27 +02:00
|
|
|
.into_par_iter()
|
2021-04-21 22:31:45 +02:00
|
|
|
.enumerate()
|
|
|
|
|
.map(|(i, x)| {
|
|
|
|
|
let i_next = (i + 1) % lde_size;
|
2021-05-07 16:22:13 +02:00
|
|
|
let local_wires = wires_commitment.leaf(i);
|
|
|
|
|
let local_constants = prover_data.constants_commitment.leaf(i);
|
|
|
|
|
let local_plonk_zs = plonk_zs_commitment.leaf(i);
|
2021-05-10 13:10:40 +02:00
|
|
|
let next_plonk_zs = plonk_zs_commitment.leaf(i_next);
|
2021-05-07 16:22:13 +02:00
|
|
|
let s_sigmas = prover_data.sigmas_commitment.leaf(i);
|
2021-04-21 22:31:45 +02:00
|
|
|
|
|
|
|
|
debug_assert_eq!(local_wires.len(), common_data.config.num_wires);
|
2021-05-14 08:07:00 -07:00
|
|
|
debug_assert_eq!(local_plonk_zs.len(), num_challenges);
|
2021-04-21 22:31:45 +02:00
|
|
|
|
2021-05-30 13:25:53 -07:00
|
|
|
let vars = EvaluationVarsBase {
|
2021-04-21 22:31:45 +02:00
|
|
|
local_constants,
|
|
|
|
|
local_wires,
|
|
|
|
|
};
|
2021-06-08 21:23:52 -07:00
|
|
|
eval_vanishing_poly_base(
|
2021-04-21 22:31:45 +02:00
|
|
|
common_data,
|
|
|
|
|
x,
|
|
|
|
|
vars,
|
|
|
|
|
local_plonk_zs,
|
|
|
|
|
next_plonk_zs,
|
|
|
|
|
s_sigmas,
|
2021-04-23 14:25:24 -07:00
|
|
|
betas,
|
|
|
|
|
gammas,
|
2021-04-21 22:31:45 +02:00
|
|
|
alphas,
|
|
|
|
|
)
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
2021-04-01 13:22:54 -07:00
|
|
|
|
2021-04-01 13:46:24 -07:00
|
|
|
transpose(&values)
|
|
|
|
|
.into_iter()
|
2021-04-01 13:22:54 -07:00
|
|
|
.map(PolynomialValues::new)
|
|
|
|
|
.collect()
|
2021-03-28 15:36:51 -07:00
|
|
|
}
|
|
|
|
|
|
2021-05-06 23:14:37 +02:00
|
|
|
fn compute_wire_polynomial<F: Field>(
|
|
|
|
|
input: usize,
|
|
|
|
|
witness: &PartialWitness<F>,
|
|
|
|
|
degree: usize,
|
|
|
|
|
) -> PolynomialCoeffs<F> {
|
|
|
|
|
let wire_values = (0..degree)
|
|
|
|
|
// Some gates do not use all wires, and we do not require that generators populate unused
|
|
|
|
|
// wires, so some wire values will not be set. We can set these to any value; here we
|
|
|
|
|
// arbitrary pick zero. Ideally we would verify that no constraints operate on these unset
|
|
|
|
|
// wires, but that isn't trivial.
|
|
|
|
|
.map(|gate| {
|
|
|
|
|
witness
|
|
|
|
|
.try_get_wire(Wire { gate, input })
|
|
|
|
|
.unwrap_or(F::ZERO)
|
|
|
|
|
})
|
|
|
|
|
.collect();
|
|
|
|
|
PolynomialValues::new(wire_values).ifft()
|
|
|
|
|
}
|