mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-07 08:13:11 +00:00
Implement compute_z and rewrite of compute_vanishing_polys
This commit is contained in:
parent
1b99f8272f
commit
a71909ba15
@ -292,19 +292,13 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
let subgroup = F::two_adic_subgroup(degree_bits);
|
||||
|
||||
let constant_vecs = self.constant_polys();
|
||||
let constants_commitment = ListPolynomialCommitment::new(
|
||||
constant_vecs.into_iter().map(|v| v.ifft()).collect(),
|
||||
self.config.fri_config.rate_bits,
|
||||
false,
|
||||
);
|
||||
let constants_commitment =
|
||||
ListPolynomialCommitment::new(constant_vecs, self.config.fri_config.rate_bits, false);
|
||||
|
||||
let k_is = get_unique_coset_shifts(degree, self.config.num_routed_wires);
|
||||
let sigma_vecs = self.sigma_vecs(&k_is, &subgroup);
|
||||
let sigmas_commitment = ListPolynomialCommitment::new(
|
||||
sigma_vecs.into_iter().map(|v| v.ifft()).collect(),
|
||||
self.config.fri_config.rate_bits,
|
||||
false,
|
||||
);
|
||||
let sigmas_commitment =
|
||||
ListPolynomialCommitment::new(sigma_vecs, self.config.fri_config.rate_bits, false);
|
||||
|
||||
let constants_root = constants_commitment.merkle_tree.root;
|
||||
let sigmas_root = sigmas_commitment.merkle_tree.root;
|
||||
@ -339,6 +333,7 @@ impl<F: Extendable<D>, const D: usize> CircuitBuilder<F, D> {
|
||||
config: self.config,
|
||||
degree_bits,
|
||||
gates,
|
||||
max_filtered_constraint_degree_bits: 3, // TODO: compute this correctly once filters land.
|
||||
num_gate_constraints,
|
||||
k_is,
|
||||
circuit_digest,
|
||||
|
||||
@ -143,6 +143,9 @@ pub(crate) struct CommonCircuitData<F: Extendable<D>, const D: usize> {
|
||||
/// The types of gates used in this circuit.
|
||||
pub(crate) gates: Vec<GateRef<F, D>>,
|
||||
|
||||
/// The largest number of constraints imposed by any gate.
|
||||
pub(crate) max_filtered_constraint_degree_bits: usize,
|
||||
|
||||
/// The largest number of constraints imposed by any gate.
|
||||
pub(crate) num_gate_constraints: usize,
|
||||
|
||||
@ -176,7 +179,7 @@ impl<F: Extendable<D>, const D: usize> CommonCircuitData<F, D> {
|
||||
}
|
||||
|
||||
pub fn quotient_degree(&self) -> usize {
|
||||
self.constraint_degree() - 1
|
||||
1 << self.max_filtered_constraint_degree_bits - 1
|
||||
}
|
||||
|
||||
pub fn total_constraints(&self) -> usize {
|
||||
|
||||
@ -9,37 +9,73 @@ use crate::fri::{prover::fri_proof, verifier::verify_fri_proof, FriConfig};
|
||||
use crate::merkle_tree::MerkleTree;
|
||||
use crate::plonk_challenger::Challenger;
|
||||
use crate::plonk_common::{reduce_polys_with_iter, reduce_with_iter};
|
||||
use crate::polynomial::polynomial::PolynomialCoeffs;
|
||||
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||
use crate::proof::{FriProof, FriProofTarget, Hash, OpeningSet};
|
||||
use crate::timed;
|
||||
use crate::util::{log2_strict, reverse_index_bits_in_place, transpose};
|
||||
use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place, transpose};
|
||||
|
||||
pub const SALT_SIZE: usize = 2;
|
||||
|
||||
pub struct ListPolynomialCommitment<F: Field> {
|
||||
pub polynomials: Vec<PolynomialCoeffs<F>>,
|
||||
pub values: Vec<PolynomialValues<F>>,
|
||||
pub merkle_tree: MerkleTree<F>,
|
||||
pub degree: usize,
|
||||
pub degree_log: usize,
|
||||
pub rate_bits: usize,
|
||||
pub blinding: bool,
|
||||
}
|
||||
|
||||
impl<F: Field> ListPolynomialCommitment<F> {
|
||||
pub fn new(polynomials: Vec<PolynomialCoeffs<F>>, rate_bits: usize, blinding: bool) -> Self {
|
||||
let degree = polynomials[0].len();
|
||||
/// Creates a list polynomial commitment for the polynomials interpolating the values in `values`.
|
||||
pub fn new(values: Vec<PolynomialValues<F>>, rate_bits: usize, blinding: bool) -> Self {
|
||||
let degree = values[0].len();
|
||||
let polynomials = values.iter().map(|v| v.clone().ifft()).collect::<Vec<_>>();
|
||||
let lde_values = timed!(
|
||||
Self::lde_values(&polynomials, rate_bits, blinding),
|
||||
"to compute LDE"
|
||||
);
|
||||
|
||||
Self::new_from_data(polynomials, values, lde_values, degree, rate_bits, blinding)
|
||||
}
|
||||
|
||||
/// Creates a list polynomial commitment for the polynomials `polynomials`.
|
||||
pub fn new_from_polys(
|
||||
polynomials: Vec<PolynomialCoeffs<F>>,
|
||||
rate_bits: usize,
|
||||
blinding: bool,
|
||||
) -> Self {
|
||||
let degree = polynomials[0].len();
|
||||
let values = polynomials
|
||||
.iter()
|
||||
.map(|v| v.clone().fft())
|
||||
.collect::<Vec<_>>();
|
||||
let lde_values = timed!(
|
||||
Self::lde_values(&polynomials, rate_bits, blinding),
|
||||
"to compute LDE"
|
||||
);
|
||||
|
||||
Self::new_from_data(polynomials, values, lde_values, degree, rate_bits, blinding)
|
||||
}
|
||||
|
||||
fn new_from_data(
|
||||
polynomials: Vec<PolynomialCoeffs<F>>,
|
||||
values: Vec<PolynomialValues<F>>,
|
||||
lde_values: Vec<Vec<F>>,
|
||||
degree: usize,
|
||||
rate_bits: usize,
|
||||
blinding: bool,
|
||||
) -> Self {
|
||||
let mut leaves = timed!(transpose(&lde_values), "to transpose LDEs");
|
||||
reverse_index_bits_in_place(&mut leaves);
|
||||
let merkle_tree = timed!(MerkleTree::new(leaves, false), "to build Merkle tree");
|
||||
|
||||
Self {
|
||||
polynomials,
|
||||
values,
|
||||
merkle_tree,
|
||||
degree,
|
||||
degree_log: log2_strict(degree),
|
||||
rate_bits,
|
||||
blinding,
|
||||
}
|
||||
@ -71,9 +107,8 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn leaf(&self, index: usize) -> &[F] {
|
||||
let leaf = &self.merkle_tree.leaves[index];
|
||||
&leaf[0..leaf.len() - if self.blinding { SALT_SIZE } else { 0 }]
|
||||
pub fn original_value(&self, index: usize) -> Vec<F> {
|
||||
self.values.iter().map(|v| v.values[index]).collect()
|
||||
}
|
||||
|
||||
/// Takes the commitments to the constants - sigmas - wires - zs - quotient — polynomials,
|
||||
@ -88,7 +123,7 @@ impl<F: Field> ListPolynomialCommitment<F> {
|
||||
F: Extendable<D>,
|
||||
{
|
||||
assert!(D > 1, "Not implemented for D=1.");
|
||||
let degree_log = log2_strict(commitments[0].degree);
|
||||
let degree_log = commitments[0].degree_log;
|
||||
let g = F::Extension::primitive_root_of_unity(degree_log);
|
||||
for p in &[zeta, g * zeta] {
|
||||
assert_ne!(
|
||||
@ -267,11 +302,11 @@ mod tests {
|
||||
fn gen_random_test_case<F: Field + Extendable<D>, const D: usize>(
|
||||
k: usize,
|
||||
degree_log: usize,
|
||||
) -> Vec<PolynomialCoeffs<F>> {
|
||||
) -> Vec<PolynomialValues<F>> {
|
||||
let degree = 1 << degree_log;
|
||||
|
||||
(0..k)
|
||||
.map(|_| PolynomialCoeffs::new(F::rand_vec(degree)))
|
||||
.map(|_| PolynomialValues::new(F::rand_vec(degree)))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
139
src/prover.rs
139
src/prover.rs
@ -17,7 +17,7 @@ use crate::timed;
|
||||
use crate::util::transpose;
|
||||
use crate::vars::EvaluationVarsBase;
|
||||
use crate::wire::Wire;
|
||||
use crate::witness::PartialWitness;
|
||||
use crate::witness::{PartialWitness, Witness};
|
||||
|
||||
/// Corresponds to constants - sigmas - wires - zs - quotient — polynomial commitments.
|
||||
pub const PLONK_BLINDING: [bool; 5] = [false, false, true, true, true];
|
||||
@ -31,10 +31,10 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
|
||||
|
||||
let start_proof_gen = Instant::now();
|
||||
|
||||
let mut witness = inputs;
|
||||
let mut partial_witness = inputs;
|
||||
info!("Running {} generators", prover_data.generators.len());
|
||||
timed!(
|
||||
generate_partial_witness(&mut witness, &prover_data.generators),
|
||||
generate_partial_witness(&mut partial_witness, &prover_data.generators),
|
||||
"to generate witness"
|
||||
);
|
||||
|
||||
@ -42,12 +42,15 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
|
||||
let num_wires = config.num_wires;
|
||||
let num_challenges = config.num_challenges;
|
||||
let quotient_degree = common_data.quotient_degree();
|
||||
|
||||
let degree = common_data.degree();
|
||||
let wires_polynomials: Vec<PolynomialCoeffs<F>> = timed!(
|
||||
(0..num_wires)
|
||||
.into_par_iter()
|
||||
.map(|i| compute_wire_polynomial(i, &witness, degree))
|
||||
|
||||
let witness = partial_witness.full_witness(degree, num_wires);
|
||||
|
||||
let wires_values: Vec<PolynomialValues<F>> = timed!(
|
||||
witness
|
||||
.wire_values
|
||||
.iter()
|
||||
.map(|column| PolynomialValues::new(column.clone()))
|
||||
.collect(),
|
||||
"to compute wire polynomials"
|
||||
);
|
||||
@ -55,7 +58,7 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
|
||||
// TODO: Could try parallelizing the transpose, or not doing it explicitly, instead having
|
||||
// merkle_root_bit_rev_order do it implicitly.
|
||||
let wires_commitment = timed!(
|
||||
ListPolynomialCommitment::new(wires_polynomials, fri_config.rate_bits, true),
|
||||
ListPolynomialCommitment::new(wires_values, fri_config.rate_bits, true),
|
||||
"to compute wires commitment"
|
||||
);
|
||||
|
||||
@ -68,7 +71,10 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
|
||||
let betas = challenger.get_n_challenges(num_challenges);
|
||||
let gammas = challenger.get_n_challenges(num_challenges);
|
||||
|
||||
let plonk_z_vecs = timed!(compute_zs(&common_data), "to compute Z's");
|
||||
let plonk_z_vecs = timed!(
|
||||
compute_zs(&witness, &betas, &gammas, &prover_data, &common_data),
|
||||
"to compute Z's"
|
||||
);
|
||||
|
||||
let plonk_zs_commitment = timed!(
|
||||
ListPolynomialCommitment::new(plonk_z_vecs, fri_config.rate_bits, true),
|
||||
@ -107,7 +113,11 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
|
||||
);
|
||||
|
||||
let quotient_polys_commitment = timed!(
|
||||
ListPolynomialCommitment::new(all_quotient_poly_chunks, fri_config.rate_bits, true),
|
||||
ListPolynomialCommitment::new_from_polys(
|
||||
all_quotient_poly_chunks,
|
||||
fri_config.rate_bits,
|
||||
true
|
||||
),
|
||||
"to commit to quotient polys"
|
||||
);
|
||||
|
||||
@ -146,37 +156,44 @@ pub(crate) fn prove<F: Extendable<D>, const D: usize>(
|
||||
}
|
||||
|
||||
fn compute_zs<F: Extendable<D>, const D: usize>(
|
||||
witness: &Witness<F>,
|
||||
betas: &[F],
|
||||
gammas: &[F],
|
||||
prover_data: &ProverOnlyCircuitData<F>,
|
||||
common_data: &CommonCircuitData<F, D>,
|
||||
) -> Vec<PolynomialCoeffs<F>> {
|
||||
) -> Vec<PolynomialValues<F>> {
|
||||
(0..common_data.config.num_challenges)
|
||||
.map(|i| compute_z(common_data, i))
|
||||
.map(|i| compute_z(witness, betas[i], gammas[i], prover_data, common_data))
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn compute_z<F: Extendable<D>, const D: usize>(
|
||||
witness: &Witness<F>,
|
||||
beta: F,
|
||||
gamma: F,
|
||||
prover_data: &ProverOnlyCircuitData<F>,
|
||||
common_data: &CommonCircuitData<F, D>,
|
||||
_i: usize,
|
||||
) -> PolynomialCoeffs<F> {
|
||||
todo!()
|
||||
// let subgroup =
|
||||
// let mut plonk_z_points = vec![F::ONE];
|
||||
// let k_is = common_data.k_is;
|
||||
// for i in 1..common_data.degree() {
|
||||
// let x = subgroup[i - 1];
|
||||
// let mut numerator = F::ONE;
|
||||
// let mut denominator = F::ONE;
|
||||
// for j in 0..NUM_ROUTED_WIRES {
|
||||
// let wire_value = witness.get_indices(i - 1, j);
|
||||
// let k_i = k_is[j];
|
||||
// let s_id = k_i * x;
|
||||
// let s_sigma = sigma_values[j][8 * (i - 1)];
|
||||
// numerator = numerator * (wire_value + beta * s_id + gamma);
|
||||
// denominator = denominator * (wire_value + beta * s_sigma + gamma);
|
||||
// }
|
||||
// let last = *plonk_z_points.last().unwrap();
|
||||
// plonk_z_points.push(last * numerator / denominator);
|
||||
// }
|
||||
// plonk_z_points
|
||||
) -> PolynomialValues<F> {
|
||||
let subgroup = &prover_data.subgroup;
|
||||
let mut plonk_z_points = vec![F::ONE];
|
||||
let k_is = &common_data.k_is;
|
||||
for i in 1..common_data.degree() {
|
||||
let x = subgroup[i - 1];
|
||||
let mut numerator = F::ONE;
|
||||
let mut denominator = F::ONE;
|
||||
let s_sigmas = prover_data.sigmas_commitment.original_value(i - 1);
|
||||
for j in 0..common_data.config.num_routed_wires {
|
||||
let wire_value = witness.get_wire(i - 1, j);
|
||||
let k_i = k_is[j];
|
||||
let s_id = k_i * x;
|
||||
let s_sigma = s_sigmas[j];
|
||||
numerator = numerator * (wire_value + beta * s_id + gamma);
|
||||
denominator = denominator * (wire_value + beta * s_sigma + gamma);
|
||||
}
|
||||
let last = *plonk_z_points.last().unwrap();
|
||||
plonk_z_points.push(last * numerator / denominator);
|
||||
}
|
||||
plonk_z_points.into()
|
||||
}
|
||||
|
||||
fn compute_vanishing_polys<F: Extendable<D>, const D: usize>(
|
||||
@ -188,21 +205,38 @@ fn compute_vanishing_polys<F: Extendable<D>, const D: usize>(
|
||||
gammas: &[F],
|
||||
alphas: &[F],
|
||||
) -> Vec<PolynomialValues<F>> {
|
||||
let lde_size = common_data.lde_size();
|
||||
let lde_gen = common_data.lde_generator();
|
||||
let num_challenges = common_data.config.num_challenges;
|
||||
let points = F::two_adic_subgroup(
|
||||
common_data.degree_bits + common_data.max_filtered_constraint_degree_bits,
|
||||
);
|
||||
let lde_size = points.len();
|
||||
|
||||
let commitment_to_lde = |comm: &ListPolynomialCommitment<F>| -> Vec<PolynomialValues<F>> {
|
||||
comm.polynomials
|
||||
.iter()
|
||||
.map(|p| p.lde(common_data.max_filtered_constraint_degree_bits).fft())
|
||||
.collect()
|
||||
};
|
||||
|
||||
let constants_lde = commitment_to_lde(&prover_data.constants_commitment);
|
||||
let sigmas_lde = commitment_to_lde(&prover_data.sigmas_commitment);
|
||||
let wires_lde = commitment_to_lde(wires_commitment);
|
||||
let zs_lde = commitment_to_lde(plonk_zs_commitment);
|
||||
|
||||
let get_at_index = |ldes: &[PolynomialValues<F>], i: usize| {
|
||||
ldes.iter().map(|l| l.values[i]).collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
let points = F::cyclic_subgroup_known_order(lde_gen, lde_size);
|
||||
let values: Vec<Vec<F>> = points
|
||||
.into_par_iter()
|
||||
.enumerate()
|
||||
.map(|(i, x)| {
|
||||
let i_next = (i + 1) % lde_size;
|
||||
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);
|
||||
let next_plonk_zs = plonk_zs_commitment.leaf(i_next);
|
||||
let s_sigmas = prover_data.sigmas_commitment.leaf(i);
|
||||
let local_constants = &get_at_index(&constants_lde, i);
|
||||
let s_sigmas = &get_at_index(&sigmas_lde, i);
|
||||
let local_wires = &get_at_index(&wires_lde, i);
|
||||
let local_plonk_zs = &get_at_index(&zs_lde, i);
|
||||
let next_plonk_zs = &get_at_index(&zs_lde, i_next);
|
||||
|
||||
debug_assert_eq!(local_wires.len(), common_data.config.num_wires);
|
||||
debug_assert_eq!(local_plonk_zs.len(), num_challenges);
|
||||
@ -230,22 +264,3 @@ fn compute_vanishing_polys<F: Extendable<D>, const D: usize>(
|
||||
.map(PolynomialValues::new)
|
||||
.collect()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
@ -1,11 +1,23 @@
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use crate::circuit_data::{CircuitConfig, CommonCircuitData};
|
||||
use crate::field::extension_field::target::ExtensionTarget;
|
||||
use crate::field::extension_field::{Extendable, FieldExtension};
|
||||
use crate::field::field::Field;
|
||||
use crate::target::Target;
|
||||
use crate::wire::Wire;
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Witness<F: Field> {
|
||||
pub(crate) wire_values: Vec<Vec<F>>,
|
||||
}
|
||||
|
||||
impl<F: Field> Witness<F> {
|
||||
pub fn get_wire(&self, gate: usize, input: usize) -> F {
|
||||
self.wire_values[input][gate]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PartialWitness<F: Field> {
|
||||
@ -121,6 +133,16 @@ impl<F: Field> PartialWitness<F> {
|
||||
self.set_target(target, value);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn full_witness(self, degree: usize, num_wires: usize) -> Witness<F> {
|
||||
let mut wire_values = vec![vec![F::ZERO; degree]; num_wires];
|
||||
self.target_values.into_iter().for_each(|(t, v)| {
|
||||
if let Target::Wire(Wire { gate, input }) = t {
|
||||
wire_values[input][gate] = v;
|
||||
}
|
||||
});
|
||||
Witness { wire_values }
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: Field> Default for PartialWitness<F> {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user