mirror of https://github.com/zcash/halo2.git
Reimplement keygen_pk for fe-be split as keygen_pk_v2
This commit is contained in:
parent
eb5d1aadbe
commit
d318a9d03d
|
@ -373,6 +373,22 @@ pub struct PinnedVerificationKey<'a, C: CurveAffine> {
|
|||
fixed_commitments: &'a Vec<C>,
|
||||
permutation: &'a permutation::VerifyingKey<C>,
|
||||
}
|
||||
|
||||
/// This is a proving key which allows for the creation of proofs for a
|
||||
/// particular circuit.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ProvingKeyV2<C: CurveAffine> {
|
||||
vk: VerifyingKeyV2<C>,
|
||||
l0: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
|
||||
l_last: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
|
||||
l_active_row: Polynomial<C::Scalar, ExtendedLagrangeCoeff>,
|
||||
fixed_values: Vec<Polynomial<C::Scalar, LagrangeCoeff>>,
|
||||
fixed_polys: Vec<Polynomial<C::Scalar, Coeff>>,
|
||||
fixed_cosets: Vec<Polynomial<C::Scalar, ExtendedLagrangeCoeff>>,
|
||||
permutation: permutation::ProvingKey<C>,
|
||||
ev: Evaluator<C>,
|
||||
}
|
||||
|
||||
/// This is a proving key which allows for the creation of proofs for a
|
||||
/// particular circuit.
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
};
|
||||
use group::ff::{Field, PrimeField, WithSmallOrderMulGroup};
|
||||
|
||||
use super::{shuffle, ConstraintSystem, Expression};
|
||||
use super::{shuffle, ConstraintSystem, ConstraintSystemV2Backend, Expression};
|
||||
|
||||
/// Return the index in the polynomial of size `isize` after rotation `rot`.
|
||||
fn get_rotation_idx(idx: usize, rot: i32, rot_scale: i32, isize: i32) -> usize {
|
||||
|
@ -205,6 +205,95 @@ pub struct CalculationInfo {
|
|||
}
|
||||
|
||||
impl<C: CurveAffine> Evaluator<C> {
|
||||
/// Creates a new evaluation structure
|
||||
pub fn new_v2(cs: &ConstraintSystemV2Backend<C::ScalarExt>) -> Self {
|
||||
let mut ev = Evaluator::default();
|
||||
|
||||
// Custom gates
|
||||
let mut parts = Vec::new();
|
||||
for gate in cs.gates.iter() {
|
||||
parts.extend(
|
||||
gate.polynomials()
|
||||
.iter()
|
||||
.map(|poly| ev.custom_gates.add_expression(poly)),
|
||||
);
|
||||
}
|
||||
ev.custom_gates.add_calculation(Calculation::Horner(
|
||||
ValueSource::PreviousValue(),
|
||||
parts,
|
||||
ValueSource::Y(),
|
||||
));
|
||||
|
||||
// Lookups
|
||||
for lookup in cs.lookups.iter() {
|
||||
let mut graph = GraphEvaluator::default();
|
||||
|
||||
let mut evaluate_lc = |expressions: &Vec<Expression<_>>| {
|
||||
let parts = expressions
|
||||
.iter()
|
||||
.map(|expr| graph.add_expression(expr))
|
||||
.collect();
|
||||
graph.add_calculation(Calculation::Horner(
|
||||
ValueSource::Constant(0),
|
||||
parts,
|
||||
ValueSource::Theta(),
|
||||
))
|
||||
};
|
||||
|
||||
// Input coset
|
||||
let compressed_input_coset = evaluate_lc(&lookup.input_expressions);
|
||||
// table coset
|
||||
let compressed_table_coset = evaluate_lc(&lookup.table_expressions);
|
||||
// z(\omega X) (a'(X) + \beta) (s'(X) + \gamma)
|
||||
let right_gamma = graph.add_calculation(Calculation::Add(
|
||||
compressed_table_coset,
|
||||
ValueSource::Gamma(),
|
||||
));
|
||||
let lc = graph.add_calculation(Calculation::Add(
|
||||
compressed_input_coset,
|
||||
ValueSource::Beta(),
|
||||
));
|
||||
graph.add_calculation(Calculation::Mul(lc, right_gamma));
|
||||
|
||||
ev.lookups.push(graph);
|
||||
}
|
||||
|
||||
// Shuffles
|
||||
for shuffle in cs.shuffles.iter() {
|
||||
let evaluate_lc = |expressions: &Vec<Expression<_>>, graph: &mut GraphEvaluator<C>| {
|
||||
let parts = expressions
|
||||
.iter()
|
||||
.map(|expr| graph.add_expression(expr))
|
||||
.collect();
|
||||
graph.add_calculation(Calculation::Horner(
|
||||
ValueSource::Constant(0),
|
||||
parts,
|
||||
ValueSource::Theta(),
|
||||
))
|
||||
};
|
||||
|
||||
let mut graph_input = GraphEvaluator::default();
|
||||
let compressed_input_coset = evaluate_lc(&shuffle.input_expressions, &mut graph_input);
|
||||
let _ = graph_input.add_calculation(Calculation::Add(
|
||||
compressed_input_coset,
|
||||
ValueSource::Gamma(),
|
||||
));
|
||||
|
||||
let mut graph_shuffle = GraphEvaluator::default();
|
||||
let compressed_shuffle_coset =
|
||||
evaluate_lc(&shuffle.shuffle_expressions, &mut graph_shuffle);
|
||||
let _ = graph_shuffle.add_calculation(Calculation::Add(
|
||||
compressed_shuffle_coset,
|
||||
ValueSource::Gamma(),
|
||||
));
|
||||
|
||||
ev.shuffles.push(graph_input);
|
||||
ev.shuffles.push(graph_shuffle);
|
||||
}
|
||||
|
||||
ev
|
||||
}
|
||||
|
||||
/// Creates a new evaluation structure
|
||||
pub fn new(cs: &ConstraintSystem<C::ScalarExt>) -> Self {
|
||||
let mut ev = Evaluator::default();
|
||||
|
|
|
@ -11,8 +11,8 @@ use super::{
|
|||
FloorPlanner, Instance, Selector,
|
||||
},
|
||||
evaluation::Evaluator,
|
||||
permutation, Assigned, Challenge, Error, LagrangeCoeff, Polynomial, ProvingKey, VerifyingKey,
|
||||
VerifyingKeyV2,
|
||||
permutation, Assigned, Challenge, Error, LagrangeCoeff, Polynomial, ProvingKey, ProvingKeyV2,
|
||||
VerifyingKey, VerifyingKeyV2,
|
||||
};
|
||||
use crate::{
|
||||
arithmetic::{parallelize, CurveAffine},
|
||||
|
@ -215,47 +215,11 @@ where
|
|||
{
|
||||
let cs = &circuit.cs;
|
||||
let domain = EvaluationDomain::new(cs.degree() as u32, params.k());
|
||||
// let (domain, cs, config) = create_domain::<C, ConcreteCircuit>(
|
||||
// params.k(),
|
||||
// #[cfg(feature = "circuit-params")]
|
||||
// circuit.params(),
|
||||
// );
|
||||
|
||||
if (params.n() as usize) < cs.minimum_rows() {
|
||||
return Err(Error::not_enough_rows_available(params.k()));
|
||||
}
|
||||
|
||||
// let mut assembly: Assembly<C::Scalar> = Assembly {
|
||||
// k: params.k(),
|
||||
// fixed: vec![domain.empty_lagrange_assigned(); cs.num_fixed_columns],
|
||||
// permutation: permutation::keygen::Assembly::new(params.n() as usize, &cs.permutation),
|
||||
// // selectors: vec![vec![false; params.n() as usize]; cs.num_selectors],
|
||||
// usable_rows: 0..params.n() as usize - (cs.blinding_factors() + 1),
|
||||
// _marker: std::marker::PhantomData,
|
||||
// };
|
||||
|
||||
// Synthesize the circuit to obtain URS
|
||||
// ConcreteCircuit::FloorPlanner::synthesize(
|
||||
// &mut assembly,
|
||||
// circuit,
|
||||
// config,
|
||||
// cs.constants.clone(),
|
||||
// )?;
|
||||
|
||||
// let mut fixed = batch_invert_assigned(assembly.fixed);
|
||||
// let (cs, selector_polys) = if compress_selectors {
|
||||
// cs.compress_selectors(assembly.selectors.clone())
|
||||
// } else {
|
||||
// // After this, the ConstraintSystem should not have any selectors: `verify` does not need them, and `keygen_pk` regenerates `cs` from scratch anyways.
|
||||
// let selectors = std::mem::take(&mut assembly.selectors);
|
||||
// cs.directly_convert_selectors_to_fixed(selectors)
|
||||
// };
|
||||
// fixed.extend(
|
||||
// selector_polys
|
||||
// .into_iter()
|
||||
// .map(|poly| domain.lagrange_from_vec(poly)),
|
||||
// );
|
||||
|
||||
let permutation_vk =
|
||||
circuit
|
||||
.preprocessing
|
||||
|
@ -367,6 +331,90 @@ where
|
|||
))
|
||||
}
|
||||
|
||||
/// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `CompiledCircuit`.
|
||||
pub fn keygen_pk_v2<'params, C, P>(
|
||||
params: &P,
|
||||
vk: VerifyingKeyV2<C>,
|
||||
circuit: &CompiledCircuitV2<C::Scalar>,
|
||||
) -> Result<ProvingKeyV2<C>, Error>
|
||||
where
|
||||
C: CurveAffine,
|
||||
P: Params<'params, C>,
|
||||
{
|
||||
let cs = &circuit.cs;
|
||||
|
||||
if (params.n() as usize) < cs.minimum_rows() {
|
||||
return Err(Error::not_enough_rows_available(params.k()));
|
||||
}
|
||||
|
||||
let fixed_polys: Vec<_> = circuit
|
||||
.preprocessing
|
||||
.fixed
|
||||
.iter()
|
||||
.map(|poly| vk.domain.lagrange_to_coeff(poly.clone()))
|
||||
.collect();
|
||||
|
||||
let fixed_cosets = fixed_polys
|
||||
.iter()
|
||||
.map(|poly| vk.domain.coeff_to_extended(poly.clone()))
|
||||
.collect();
|
||||
|
||||
let permutation_pk =
|
||||
circuit
|
||||
.preprocessing
|
||||
.permutation
|
||||
.clone()
|
||||
.build_pk(params, &vk.domain, &cs.permutation);
|
||||
|
||||
// Compute l_0(X)
|
||||
// TODO: this can be done more efficiently
|
||||
let mut l0 = vk.domain.empty_lagrange();
|
||||
l0[0] = C::Scalar::ONE;
|
||||
let l0 = vk.domain.lagrange_to_coeff(l0);
|
||||
let l0 = vk.domain.coeff_to_extended(l0);
|
||||
|
||||
// Compute l_blind(X) which evaluates to 1 for each blinding factor row
|
||||
// and 0 otherwise over the domain.
|
||||
let mut l_blind = vk.domain.empty_lagrange();
|
||||
for evaluation in l_blind[..].iter_mut().rev().take(cs.blinding_factors()) {
|
||||
*evaluation = C::Scalar::ONE;
|
||||
}
|
||||
let l_blind = vk.domain.lagrange_to_coeff(l_blind);
|
||||
let l_blind = vk.domain.coeff_to_extended(l_blind);
|
||||
|
||||
// Compute l_last(X) which evaluates to 1 on the first inactive row (just
|
||||
// before the blinding factors) and 0 otherwise over the domain
|
||||
let mut l_last = vk.domain.empty_lagrange();
|
||||
l_last[params.n() as usize - cs.blinding_factors() - 1] = C::Scalar::ONE;
|
||||
let l_last = vk.domain.lagrange_to_coeff(l_last);
|
||||
let l_last = vk.domain.coeff_to_extended(l_last);
|
||||
|
||||
// Compute l_active_row(X)
|
||||
let one = C::Scalar::ONE;
|
||||
let mut l_active_row = vk.domain.empty_extended();
|
||||
parallelize(&mut l_active_row, |values, start| {
|
||||
for (i, value) in values.iter_mut().enumerate() {
|
||||
let idx = i + start;
|
||||
*value = one - (l_last[idx] + l_blind[idx]);
|
||||
}
|
||||
});
|
||||
|
||||
// Compute the optimized evaluation data structure
|
||||
let ev = Evaluator::new_v2(&vk.cs);
|
||||
|
||||
Ok(ProvingKeyV2 {
|
||||
vk,
|
||||
l0,
|
||||
l_last,
|
||||
l_active_row,
|
||||
fixed_values: circuit.preprocessing.fixed.clone(),
|
||||
fixed_polys,
|
||||
fixed_cosets,
|
||||
permutation: permutation_pk,
|
||||
ev,
|
||||
})
|
||||
}
|
||||
|
||||
/// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `Circuit`.
|
||||
pub fn keygen_pk<'params, C, P, ConcreteCircuit>(
|
||||
params: &P,
|
||||
|
|
Loading…
Reference in New Issue