mirror of https://github.com/zcash/halo2.git
Refactor keygen to generate pk from vk.
This commit is contained in:
parent
b9737ada93
commit
58479fbcc3
|
@ -226,7 +226,8 @@ fn bench_with_k(name: &str, k: u32, c: &mut Criterion) {
|
||||||
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
||||||
|
|
||||||
// Initialize the proving key
|
// Initialize the proving key
|
||||||
let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail");
|
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail");
|
||||||
|
let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail");
|
||||||
|
|
||||||
let prover_name = name.to_string() + "-prover";
|
let prover_name = name.to_string() + "-prover";
|
||||||
let verifier_name = name.to_string() + "-verifier";
|
let verifier_name = name.to_string() + "-verifier";
|
||||||
|
|
|
@ -257,7 +257,8 @@ fn main() {
|
||||||
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
let empty_circuit: MyCircuit<Fp> = MyCircuit { a: None, k };
|
||||||
|
|
||||||
// Initialize the proving key
|
// Initialize the proving key
|
||||||
let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail");
|
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail");
|
||||||
|
let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail");
|
||||||
|
|
||||||
println!("[Keygen] {}", recorder);
|
println!("[Keygen] {}", recorder);
|
||||||
recorder.clear();
|
recorder.clear();
|
||||||
|
|
|
@ -485,7 +485,8 @@ fn test_proving() {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Initialize the proving key
|
// Initialize the proving key
|
||||||
let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail");
|
let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail");
|
||||||
|
let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail");
|
||||||
|
|
||||||
let mut pubinputs = pk.get_vk().get_domain().empty_lagrange();
|
let mut pubinputs = pk.get_vk().get_domain().empty_lagrange();
|
||||||
pubinputs[0] = aux;
|
pubinputs[0] = aux;
|
||||||
|
|
|
@ -2,12 +2,12 @@ use ff::Field;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
circuit::{Advice, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
||||||
permutation, Error, ProvingKey, VerifyingKey,
|
permutation, Error, LagrangeCoeff, Polynomial, ProvingKey, VerifyingKey,
|
||||||
};
|
};
|
||||||
use crate::arithmetic::{Curve, CurveAffine};
|
use crate::arithmetic::{Curve, CurveAffine};
|
||||||
use crate::poly::{
|
use crate::poly::{
|
||||||
commitment::{Blind, Params},
|
commitment::{Blind, Params},
|
||||||
EvaluationDomain, LagrangeCoeff, Polynomial, Rotation,
|
EvaluationDomain, Rotation,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub(crate) fn create_domain<C, ConcreteCircuit>(
|
pub(crate) fn create_domain<C, ConcreteCircuit>(
|
||||||
|
@ -55,22 +55,15 @@ where
|
||||||
(domain, cs, config)
|
(domain, cs, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate a `ProvingKey` from an instance of `Circuit`.
|
/// Assembly to be used in circuit synthesis.
|
||||||
pub fn keygen<C, ConcreteCircuit>(
|
#[derive(Clone, Debug)]
|
||||||
params: &Params<C>,
|
pub struct Assembly<F: Field> {
|
||||||
circuit: &ConcreteCircuit,
|
|
||||||
) -> Result<ProvingKey<C>, Error>
|
|
||||||
where
|
|
||||||
C: CurveAffine,
|
|
||||||
ConcreteCircuit: Circuit<C::Scalar>,
|
|
||||||
{
|
|
||||||
struct Assembly<F: Field> {
|
|
||||||
fixed: Vec<Polynomial<F, LagrangeCoeff>>,
|
fixed: Vec<Polynomial<F, LagrangeCoeff>>,
|
||||||
permutations: Vec<permutation::keygen::Assembly>,
|
permutations: Vec<permutation::keygen::Assembly>,
|
||||||
_marker: std::marker::PhantomData<F>,
|
_marker: std::marker::PhantomData<F>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> Assignment<F> for Assembly<F> {
|
impl<F: Field> Assignment<F> for Assembly<F> {
|
||||||
fn assign_advice(
|
fn assign_advice(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: Column<Advice>,
|
_: Column<Advice>,
|
||||||
|
@ -111,8 +104,17 @@ where
|
||||||
|
|
||||||
self.permutations[permutation].copy(left_column, left_row, right_column, right_row)
|
self.permutations[permutation].copy(left_column, left_row, right_column, right_row)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Generate a `VerifyingKey` from an instance of `Circuit`.
|
||||||
|
pub fn keygen_vk<C, ConcreteCircuit>(
|
||||||
|
params: &Params<C>,
|
||||||
|
circuit: &ConcreteCircuit,
|
||||||
|
) -> Result<VerifyingKey<C>, Error>
|
||||||
|
where
|
||||||
|
C: CurveAffine,
|
||||||
|
ConcreteCircuit: Circuit<C::Scalar>,
|
||||||
|
{
|
||||||
let (domain, cs, config) = create_domain::<C, ConcreteCircuit>(params);
|
let (domain, cs, config) = create_domain::<C, ConcreteCircuit>(params);
|
||||||
|
|
||||||
let mut assembly: Assembly<C::Scalar> = Assembly {
|
let mut assembly: Assembly<C::Scalar> = Assembly {
|
||||||
|
@ -130,12 +132,12 @@ where
|
||||||
|
|
||||||
let permutation_helper = permutation::keygen::Assembly::build_helper(params, &cs, &domain);
|
let permutation_helper = permutation::keygen::Assembly::build_helper(params, &cs, &domain);
|
||||||
|
|
||||||
let (permutation_pks, permutation_vks) = cs
|
let permutation_vks = cs
|
||||||
.permutations
|
.permutations
|
||||||
.iter()
|
.iter()
|
||||||
.zip(assembly.permutations.into_iter())
|
.zip(assembly.clone().permutations.into_iter())
|
||||||
.map(|(p, assembly)| assembly.build_keys(params, &domain, &permutation_helper, p))
|
.map(|(p, assembly)| assembly.build_vk(params, &domain, &permutation_helper, p))
|
||||||
.unzip();
|
.collect();
|
||||||
|
|
||||||
let fixed_commitments = assembly
|
let fixed_commitments = assembly
|
||||||
.fixed
|
.fixed
|
||||||
|
@ -143,35 +145,77 @@ where
|
||||||
.map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine())
|
.map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let fixed_polys: Vec<_> = assembly
|
Ok(VerifyingKey {
|
||||||
.fixed
|
|
||||||
.iter()
|
|
||||||
.map(|poly| domain.lagrange_to_coeff(poly.clone()))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let fixed_cosets = cs
|
|
||||||
.fixed_queries
|
|
||||||
.iter()
|
|
||||||
.map(|&(column, at)| {
|
|
||||||
let poly = fixed_polys[column.index()].clone();
|
|
||||||
domain.coeff_to_extended(poly, at)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Compute l_0(X)
|
|
||||||
// TODO: this can be done more efficiently
|
|
||||||
let mut l0 = domain.empty_lagrange();
|
|
||||||
l0[0] = C::Scalar::one();
|
|
||||||
let l0 = domain.lagrange_to_coeff(l0);
|
|
||||||
let l0 = domain.coeff_to_extended(l0, Rotation::cur());
|
|
||||||
|
|
||||||
Ok(ProvingKey {
|
|
||||||
vk: VerifyingKey {
|
|
||||||
domain,
|
domain,
|
||||||
fixed_commitments,
|
fixed_commitments,
|
||||||
permutations: permutation_vks,
|
permutations: permutation_vks,
|
||||||
cs,
|
cs,
|
||||||
},
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Generate a `ProvingKey` from a `VerifyingKey` and an instance of `Circuit`.
|
||||||
|
pub fn keygen_pk<C, ConcreteCircuit>(
|
||||||
|
params: &Params<C>,
|
||||||
|
vk: VerifyingKey<C>,
|
||||||
|
circuit: &ConcreteCircuit,
|
||||||
|
) -> Result<ProvingKey<C>, Error>
|
||||||
|
where
|
||||||
|
C: CurveAffine,
|
||||||
|
ConcreteCircuit: Circuit<C::Scalar>,
|
||||||
|
{
|
||||||
|
let mut cs = ConstraintSystem::default();
|
||||||
|
let config = ConcreteCircuit::configure(&mut cs);
|
||||||
|
|
||||||
|
let mut assembly: Assembly<C::Scalar> = Assembly {
|
||||||
|
fixed: vec![vk.domain.empty_lagrange(); vk.cs.num_fixed_columns],
|
||||||
|
permutations: vk
|
||||||
|
.cs
|
||||||
|
.permutations
|
||||||
|
.iter()
|
||||||
|
.map(|p| permutation::keygen::Assembly::new(params.n as usize, p))
|
||||||
|
.collect(),
|
||||||
|
_marker: std::marker::PhantomData,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Synthesize the circuit to obtain SRS
|
||||||
|
circuit.synthesize(&mut assembly, config)?;
|
||||||
|
|
||||||
|
let fixed_polys: Vec<_> = assembly
|
||||||
|
.fixed
|
||||||
|
.iter()
|
||||||
|
.map(|poly| vk.domain.lagrange_to_coeff(poly.clone()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let fixed_cosets = vk
|
||||||
|
.cs
|
||||||
|
.fixed_queries
|
||||||
|
.iter()
|
||||||
|
.map(|&(column, at)| {
|
||||||
|
let poly = fixed_polys[column.index()].clone();
|
||||||
|
vk.domain.coeff_to_extended(poly, at)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let permutation_helper =
|
||||||
|
permutation::keygen::Assembly::build_helper(params, &vk.cs, &vk.domain);
|
||||||
|
|
||||||
|
let permutation_pks = vk
|
||||||
|
.cs
|
||||||
|
.permutations
|
||||||
|
.iter()
|
||||||
|
.zip(assembly.permutations.into_iter())
|
||||||
|
.map(|(p, assembly)| assembly.build_pk(&vk.domain, &permutation_helper, p))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// 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, Rotation::cur());
|
||||||
|
|
||||||
|
Ok(ProvingKey {
|
||||||
|
vk,
|
||||||
l0,
|
l0,
|
||||||
fixed_values: assembly.fixed,
|
fixed_values: assembly.fixed,
|
||||||
fixed_polys,
|
fixed_polys,
|
||||||
|
|
|
@ -14,7 +14,7 @@ pub(crate) struct AssemblyHelper<C: CurveAffine> {
|
||||||
deltaomega: Vec<Vec<C::Scalar>>,
|
deltaomega: Vec<Vec<C::Scalar>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct Assembly {
|
pub(crate) struct Assembly {
|
||||||
pub(crate) mapping: Vec<Vec<(usize, usize)>>,
|
pub(crate) mapping: Vec<Vec<(usize, usize)>>,
|
||||||
aux: Vec<Vec<(usize, usize)>>,
|
aux: Vec<Vec<(usize, usize)>>,
|
||||||
|
@ -132,19 +132,15 @@ impl Assembly {
|
||||||
AssemblyHelper { deltaomega }
|
AssemblyHelper { deltaomega }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_keys<C: CurveAffine>(
|
pub(crate) fn build_vk<C: CurveAffine>(
|
||||||
self,
|
self,
|
||||||
params: &Params<C>,
|
params: &Params<C>,
|
||||||
domain: &EvaluationDomain<C::Scalar>,
|
domain: &EvaluationDomain<C::Scalar>,
|
||||||
helper: &AssemblyHelper<C>,
|
helper: &AssemblyHelper<C>,
|
||||||
p: &Argument,
|
p: &Argument,
|
||||||
) -> (ProvingKey<C>, VerifyingKey<C>) {
|
) -> VerifyingKey<C> {
|
||||||
// Compute permutation polynomials, convert to coset form and
|
// Pre-compute commitments for the SRS.
|
||||||
// pre-compute commitments for the SRS.
|
|
||||||
let mut commitments = vec![];
|
let mut commitments = vec![];
|
||||||
let mut permutations = vec![];
|
|
||||||
let mut polys = vec![];
|
|
||||||
let mut cosets = vec![];
|
|
||||||
for i in 0..p.columns.len() {
|
for i in 0..p.columns.len() {
|
||||||
// Computes the permutation polynomial based on the permutation
|
// Computes the permutation polynomial based on the permutation
|
||||||
// description in the assembly.
|
// description in the assembly.
|
||||||
|
@ -160,19 +156,39 @@ impl Assembly {
|
||||||
.commit_lagrange(&permutation_poly, Blind::default())
|
.commit_lagrange(&permutation_poly, Blind::default())
|
||||||
.to_affine(),
|
.to_affine(),
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
VerifyingKey { commitments }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn build_pk<C: CurveAffine>(
|
||||||
|
self,
|
||||||
|
domain: &EvaluationDomain<C::Scalar>,
|
||||||
|
helper: &AssemblyHelper<C>,
|
||||||
|
p: &Argument,
|
||||||
|
) -> ProvingKey<C> {
|
||||||
|
// Compute permutation polynomials, convert to coset form.
|
||||||
|
let mut permutations = vec![];
|
||||||
|
let mut polys = vec![];
|
||||||
|
let mut cosets = vec![];
|
||||||
|
for i in 0..p.columns.len() {
|
||||||
|
// Computes the permutation polynomial based on the permutation
|
||||||
|
// description in the assembly.
|
||||||
|
let mut permutation_poly = domain.empty_lagrange();
|
||||||
|
for (j, p) in permutation_poly.iter_mut().enumerate() {
|
||||||
|
let (permuted_i, permuted_j) = self.mapping[i][j];
|
||||||
|
*p = helper.deltaomega[permuted_i][permuted_j];
|
||||||
|
}
|
||||||
|
|
||||||
// Store permutation polynomial and precompute its coset evaluation
|
// Store permutation polynomial and precompute its coset evaluation
|
||||||
permutations.push(permutation_poly.clone());
|
permutations.push(permutation_poly.clone());
|
||||||
let poly = domain.lagrange_to_coeff(permutation_poly);
|
let poly = domain.lagrange_to_coeff(permutation_poly);
|
||||||
polys.push(poly.clone());
|
polys.push(poly.clone());
|
||||||
cosets.push(domain.coeff_to_extended(poly, Rotation::cur()));
|
cosets.push(domain.coeff_to_extended(poly, Rotation::cur()));
|
||||||
}
|
}
|
||||||
(
|
|
||||||
ProvingKey {
|
ProvingKey {
|
||||||
permutations,
|
permutations,
|
||||||
polys,
|
polys,
|
||||||
cosets,
|
cosets,
|
||||||
},
|
}
|
||||||
VerifyingKey { commitments },
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue