Optimize verifier eq (#102)

* wip we need to be able to do batch opening for different poly sizes or pad poly with zeros

* fix small public inputs. Only works for pow2 pubinput

Co-authored-by: Charles Chen <chancharles92@gmail.com>
This commit is contained in:
Benedikt Bünz
2022-11-20 09:26:35 -08:00
committed by GitHub
parent cf49741b7e
commit 768db4eb04
8 changed files with 56 additions and 22 deletions

View File

@@ -24,7 +24,6 @@ rayon = { version = "1.5.2", default-features = false, optional = true }
[dev-dependencies]
ark-bls12-381 = { version = "0.3.0", default-features = false, features = [ "curve" ] }
# Benchmarks
[[bench]]
name = "hyperplonk-benches"

View File

@@ -10,6 +10,7 @@ use crate::{
};
pub struct MockCircuit<F: PrimeField> {
pub public_inputs: Vec<F>,
pub witnesses: Vec<WitnessColumn<F>>,
pub index: HyperPlonkIndex<F>,
}
@@ -85,10 +86,12 @@ impl<F: PrimeField> MockCircuit<F> {
witnesses[i].append(cur_witness[i]);
}
}
let pub_input_len = ark_std::cmp::min(4, num_constraints);
let public_inputs = witnesses[0].0[0..pub_input_len].to_vec();
let params = HyperPlonkParams {
num_constraints,
num_pub_input: num_constraints,
num_pub_input: public_inputs.len(),
gate_func: gate.clone(),
};
@@ -99,7 +102,11 @@ impl<F: PrimeField> MockCircuit<F> {
selectors,
};
Self { witnesses, index }
Self {
public_inputs,
witnesses,
index,
}
}
pub fn is_satisfied(&self) -> bool {
@@ -177,7 +184,6 @@ mod test {
assert!(circuit.is_satisfied());
let index = circuit.index;
// generate pk and vks
let (pk, vk) =
<PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::preprocess(
@@ -187,14 +193,14 @@ mod test {
let proof =
<PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::prove(
&pk,
&circuit.witnesses[0].0,
&circuit.public_inputs,
&circuit.witnesses,
)?;
let verify =
<PolyIOP<Fr> as HyperPlonkSNARK<Bls12_381, MultilinearKzgPCS<Bls12_381>>>::verify(
&vk,
&circuit.witnesses[0].0,
&circuit.public_inputs,
&proof,
)?;
assert!(verify);

View File

@@ -324,8 +324,11 @@ where
// - 4.4. public input consistency checks
// - pi_poly(r_pi) where r_pi is sampled from transcript
let r_pi = transcript.get_and_append_challenge_vectors(b"r_pi", ell)?;
let tmp_point = [vec![E::Fr::zero(); num_vars - ell], r_pi].concat();
pcs_acc.insert_poly_and_points(&witness_polys[0], &witness_commits[0], &tmp_point);
// padded with zeros
let r_pi_padded = [r_pi, vec![E::Fr::zero(); num_vars - ell]].concat();
// Evaluate witness_poly[0] at r_pi||0s which is equal to public_input evaluated
// at r_pi. Assumes that public_input is a power of 2
pcs_acc.insert_poly_and_points(&witness_polys[0], &witness_commits[0], &r_pi_padded);
end_timer!(step);
// =======================================================================
@@ -515,7 +518,7 @@ where
// =======================================================================
// 3. Verify the opening against the commitment
// =======================================================================
let step = start_timer!(|| "verify commitments");
let step = start_timer!(|| "assemble commitments");
// generate evaluation points and commitments
let mut comms = vec![];
@@ -535,7 +538,6 @@ where
points.push(perm_check_point_0.clone());
points.push(perm_check_point_1.clone());
points.push(prod_final_query_point);
// frac(x)'s points
comms.push(proof.perm_check_proof.frac_comm);
comms.push(proof.perm_check_proof.frac_comm);
@@ -575,21 +577,24 @@ where
// - 4.4. public input consistency checks
// - pi_poly(r_pi) where r_pi is sampled from transcript
let r_pi = transcript.get_and_append_challenge_vectors(b"r_pi", ell)?;
let tmp_point = [vec![E::Fr::zero(); num_vars - ell], r_pi].concat();
// check public evaluation
let pi_poly = DenseMultilinearExtension::from_evaluations_slice(ell as usize, pub_input);
let expect_pi_eval = evaluate_opt(&pi_poly, &tmp_point[..]);
let expect_pi_eval = evaluate_opt(&pi_poly, &r_pi[..]);
if expect_pi_eval != *pi_eval {
return Err(HyperPlonkErrors::InvalidProver(format!(
"Public input eval mismatch: got {}, expect {}",
pi_eval, expect_pi_eval,
)));
}
comms.push(proof.witness_commits[0]);
points.push(tmp_point);
let r_pi_padded = [r_pi, vec![E::Fr::zero(); num_vars - ell]].concat();
comms.push(proof.witness_commits[0]);
points.push(r_pi_padded);
assert_eq!(comms.len(), proof.batch_openings.f_i_eval_at_point_i.len());
end_timer!(step);
let step = start_timer!(|| "PCS batch verify");
// check proof
let res = PCS::batch_verify(
&vk.pcs_param,

View File

@@ -137,6 +137,13 @@ pub(crate) fn prover_sanity_check<F: PrimeField>(
params.num_pub_input
)));
}
if !pub_input.len().is_power_of_two() {
return Err(HyperPlonkErrors::InvalidProver(format!(
"Public input length is not power of two: got {}",
pub_input.len(),
)));
}
// witnesses length
for (i, w) in witnesses.iter().enumerate() {
if w.0.len() != params.num_constraints {