2020-11-12 16:08:08 -08:00
|
|
|
use ff::Field;
|
2021-02-22 11:02:53 -08:00
|
|
|
use group::Curve;
|
2020-11-12 16:08:08 -08:00
|
|
|
|
2020-09-29 07:25:04 -07:00
|
|
|
use super::{
|
2021-02-18 23:07:08 -08:00
|
|
|
circuit::{Advice, Any, Assignment, Circuit, Column, ConstraintSystem, Fixed},
|
2021-02-18 22:53:26 -08:00
|
|
|
permutation, Error, LagrangeCoeff, Permutation, Polynomial, ProvingKey, VerifyingKey,
|
2020-09-29 07:25:04 -07:00
|
|
|
};
|
2021-02-22 11:02:53 -08:00
|
|
|
use crate::arithmetic::CurveAffine;
|
2020-09-29 07:25:04 -07:00
|
|
|
use crate::poly::{
|
|
|
|
commitment::{Blind, Params},
|
2021-01-13 09:23:01 -08:00
|
|
|
EvaluationDomain, Rotation,
|
2020-09-29 07:25:04 -07:00
|
|
|
};
|
|
|
|
|
2021-01-12 07:01:50 -08:00
|
|
|
pub(crate) fn create_domain<C, ConcreteCircuit>(
|
|
|
|
params: &Params<C>,
|
|
|
|
) -> (
|
|
|
|
EvaluationDomain<C::Scalar>,
|
|
|
|
ConstraintSystem<C::Scalar>,
|
|
|
|
ConcreteCircuit::Config,
|
|
|
|
)
|
|
|
|
where
|
|
|
|
C: CurveAffine,
|
|
|
|
ConcreteCircuit: Circuit<C::Scalar>,
|
|
|
|
{
|
|
|
|
let mut cs = ConstraintSystem::default();
|
|
|
|
let config = ConcreteCircuit::configure(&mut cs);
|
|
|
|
|
|
|
|
// The permutation argument will serve alongside the gates, so must be
|
|
|
|
// accounted for.
|
|
|
|
let mut degree = cs
|
|
|
|
.permutations
|
|
|
|
.iter()
|
|
|
|
.map(|p| p.required_degree())
|
|
|
|
.max()
|
|
|
|
.unwrap_or(1);
|
|
|
|
|
|
|
|
// The lookup argument also serves alongside the gates and must be accounted
|
|
|
|
// for.
|
|
|
|
degree = std::cmp::max(
|
|
|
|
degree,
|
|
|
|
cs.lookups
|
|
|
|
.iter()
|
|
|
|
.map(|l| l.required_degree())
|
|
|
|
.max()
|
|
|
|
.unwrap_or(1),
|
|
|
|
);
|
|
|
|
|
|
|
|
// Account for each gate to ensure our quotient polynomial is the
|
|
|
|
// correct degree and that our extended domain is the right size.
|
2021-01-22 11:46:06 -08:00
|
|
|
for (_, poly) in cs.gates.iter() {
|
2021-01-12 07:01:50 -08:00
|
|
|
degree = std::cmp::max(degree, poly.degree());
|
|
|
|
}
|
|
|
|
|
|
|
|
let domain = EvaluationDomain::new(degree as u32, params.k);
|
|
|
|
|
|
|
|
(domain, cs, config)
|
|
|
|
}
|
|
|
|
|
2021-01-13 09:23:01 -08:00
|
|
|
/// Assembly to be used in circuit synthesis.
|
2021-01-21 20:31:27 -08:00
|
|
|
#[derive(Debug)]
|
2021-01-22 08:57:38 -08:00
|
|
|
struct Assembly<F: Field> {
|
2021-01-13 09:23:01 -08:00
|
|
|
fixed: Vec<Polynomial<F, LagrangeCoeff>>,
|
|
|
|
permutations: Vec<permutation::keygen::Assembly>,
|
|
|
|
_marker: std::marker::PhantomData<F>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<F: Field> Assignment<F> for Assembly<F> {
|
2021-01-22 08:43:36 -08:00
|
|
|
fn enter_region<NR, N>(&mut self, _: N)
|
|
|
|
where
|
|
|
|
NR: Into<String>,
|
|
|
|
N: FnOnce() -> NR,
|
|
|
|
{
|
|
|
|
// Do nothing; we don't care about regions in this context.
|
|
|
|
}
|
|
|
|
|
|
|
|
fn exit_region(&mut self) {
|
|
|
|
// Do nothing; we don't care about regions in this context.
|
|
|
|
}
|
|
|
|
|
2021-01-22 08:57:38 -08:00
|
|
|
fn assign_advice<V, A, AR>(
|
2021-01-13 09:23:01 -08:00
|
|
|
&mut self,
|
2021-01-22 08:57:38 -08:00
|
|
|
_: A,
|
2021-01-13 09:23:01 -08:00
|
|
|
_: Column<Advice>,
|
|
|
|
_: usize,
|
2021-01-22 08:57:38 -08:00
|
|
|
_: V,
|
|
|
|
) -> Result<(), Error>
|
|
|
|
where
|
|
|
|
V: FnOnce() -> Result<F, Error>,
|
|
|
|
A: FnOnce() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
2021-01-13 09:23:01 -08:00
|
|
|
// We only care about fixed columns here
|
|
|
|
Ok(())
|
2020-09-29 07:25:04 -07:00
|
|
|
}
|
|
|
|
|
2021-01-22 08:57:38 -08:00
|
|
|
fn assign_fixed<V, A, AR>(
|
2021-01-13 09:23:01 -08:00
|
|
|
&mut self,
|
2021-01-22 08:57:38 -08:00
|
|
|
_: A,
|
2021-01-13 09:23:01 -08:00
|
|
|
column: Column<Fixed>,
|
|
|
|
row: usize,
|
2021-01-22 08:57:38 -08:00
|
|
|
to: V,
|
|
|
|
) -> Result<(), Error>
|
|
|
|
where
|
|
|
|
V: FnOnce() -> Result<F, Error>,
|
|
|
|
A: FnOnce() -> AR,
|
|
|
|
AR: Into<String>,
|
|
|
|
{
|
2021-01-13 09:23:01 -08:00
|
|
|
*self
|
|
|
|
.fixed
|
|
|
|
.get_mut(column.index())
|
|
|
|
.and_then(|v| v.get_mut(row))
|
|
|
|
.ok_or(Error::BoundsFailure)? = to()?;
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2020-09-29 07:25:04 -07:00
|
|
|
|
2021-01-13 09:23:01 -08:00
|
|
|
fn copy(
|
|
|
|
&mut self,
|
2021-02-18 22:53:26 -08:00
|
|
|
permutation: &Permutation,
|
2021-02-18 23:07:08 -08:00
|
|
|
left_column: Column<Any>,
|
2021-01-13 09:23:01 -08:00
|
|
|
left_row: usize,
|
2021-02-18 23:07:08 -08:00
|
|
|
right_column: Column<Any>,
|
2021-01-13 09:23:01 -08:00
|
|
|
right_row: usize,
|
|
|
|
) -> Result<(), Error> {
|
|
|
|
// Check bounds first
|
2021-02-18 22:53:26 -08:00
|
|
|
if permutation.index() >= self.permutations.len() {
|
2021-01-13 09:23:01 -08:00
|
|
|
return Err(Error::BoundsFailure);
|
2020-09-29 07:25:04 -07:00
|
|
|
}
|
|
|
|
|
2021-02-18 23:07:08 -08:00
|
|
|
let left_column_index = permutation
|
|
|
|
.mapping()
|
|
|
|
.iter()
|
|
|
|
.position(|c| c == &left_column)
|
|
|
|
.ok_or(Error::SynthesisError)?;
|
|
|
|
let right_column_index = permutation
|
|
|
|
.mapping()
|
|
|
|
.iter()
|
|
|
|
.position(|c| c == &right_column)
|
|
|
|
.ok_or(Error::SynthesisError)?;
|
|
|
|
|
|
|
|
self.permutations[permutation.index()].copy(
|
|
|
|
left_column_index,
|
|
|
|
left_row,
|
|
|
|
right_column_index,
|
|
|
|
right_row,
|
|
|
|
)
|
2020-09-29 07:25:04 -07:00
|
|
|
}
|
2021-01-22 10:36:42 -08:00
|
|
|
|
|
|
|
fn push_namespace<NR, N>(&mut self, _: N)
|
|
|
|
where
|
|
|
|
NR: Into<String>,
|
|
|
|
N: FnOnce() -> NR,
|
|
|
|
{
|
|
|
|
// Do nothing; we don't care about namespaces in this context.
|
|
|
|
}
|
|
|
|
|
|
|
|
fn pop_namespace(&mut self, _: Option<String>) {
|
|
|
|
// Do nothing; we don't care about namespaces in this context.
|
|
|
|
}
|
2021-01-13 09:23:01 -08:00
|
|
|
}
|
2020-09-29 07:25:04 -07:00
|
|
|
|
2021-01-13 09:23:01 -08:00
|
|
|
/// 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>,
|
|
|
|
{
|
2021-01-12 07:01:50 -08:00
|
|
|
let (domain, cs, config) = create_domain::<C, ConcreteCircuit>(params);
|
2020-09-29 07:25:04 -07:00
|
|
|
|
|
|
|
let mut assembly: Assembly<C::Scalar> = Assembly {
|
2020-11-05 19:13:54 -08:00
|
|
|
fixed: vec![domain.empty_lagrange(); cs.num_fixed_columns],
|
2020-12-22 10:11:42 -08:00
|
|
|
permutations: cs
|
|
|
|
.permutations
|
|
|
|
.iter()
|
2020-12-21 21:56:30 -08:00
|
|
|
.map(|p| permutation::keygen::Assembly::new(params.n as usize, p))
|
2020-12-22 10:11:42 -08:00
|
|
|
.collect(),
|
2020-09-29 07:25:04 -07:00
|
|
|
_marker: std::marker::PhantomData,
|
|
|
|
};
|
|
|
|
|
2021-01-21 20:31:27 -08:00
|
|
|
// Synthesize the circuit to obtain URS
|
2020-09-29 07:25:04 -07:00
|
|
|
circuit.synthesize(&mut assembly, config)?;
|
|
|
|
|
2020-12-22 10:11:42 -08:00
|
|
|
let permutation_helper = permutation::keygen::Assembly::build_helper(params, &cs, &domain);
|
|
|
|
|
2021-01-13 09:23:01 -08:00
|
|
|
let permutation_vks = cs
|
2020-12-22 10:11:42 -08:00
|
|
|
.permutations
|
|
|
|
.iter()
|
2021-01-21 15:40:25 -08:00
|
|
|
.zip(assembly.permutations.into_iter())
|
2021-01-13 09:23:01 -08:00
|
|
|
.map(|(p, assembly)| assembly.build_vk(params, &domain, &permutation_helper, p))
|
|
|
|
.collect();
|
2020-09-29 07:25:04 -07:00
|
|
|
|
|
|
|
let fixed_commitments = assembly
|
|
|
|
.fixed
|
|
|
|
.iter()
|
|
|
|
.map(|poly| params.commit_lagrange(poly, Blind::default()).to_affine())
|
|
|
|
.collect();
|
|
|
|
|
2021-01-13 09:23:01 -08:00
|
|
|
Ok(VerifyingKey {
|
|
|
|
domain,
|
|
|
|
fixed_commitments,
|
|
|
|
permutations: permutation_vks,
|
|
|
|
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,
|
|
|
|
};
|
|
|
|
|
2021-01-21 20:31:27 -08:00
|
|
|
// Synthesize the circuit to obtain URS
|
2021-01-13 09:23:01 -08:00
|
|
|
circuit.synthesize(&mut assembly, config)?;
|
|
|
|
|
2020-09-29 07:25:04 -07:00
|
|
|
let fixed_polys: Vec<_> = assembly
|
|
|
|
.fixed
|
2020-11-30 22:35:56 -08:00
|
|
|
.iter()
|
2021-01-13 09:23:01 -08:00
|
|
|
.map(|poly| vk.domain.lagrange_to_coeff(poly.clone()))
|
2020-09-29 07:25:04 -07:00
|
|
|
.collect();
|
|
|
|
|
2021-01-13 09:23:01 -08:00
|
|
|
let fixed_cosets = vk
|
|
|
|
.cs
|
2020-09-29 07:25:04 -07:00
|
|
|
.fixed_queries
|
|
|
|
.iter()
|
2020-11-05 19:13:54 -08:00
|
|
|
.map(|&(column, at)| {
|
2020-11-09 08:45:52 -08:00
|
|
|
let poly = fixed_polys[column.index()].clone();
|
2021-01-13 09:23:01 -08:00
|
|
|
vk.domain.coeff_to_extended(poly, at)
|
2020-09-29 07:25:04 -07:00
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
2021-01-13 09:23:01 -08:00
|
|
|
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();
|
|
|
|
|
2020-09-29 07:25:04 -07:00
|
|
|
// Compute l_0(X)
|
|
|
|
// TODO: this can be done more efficiently
|
2021-01-13 09:23:01 -08:00
|
|
|
let mut l0 = vk.domain.empty_lagrange();
|
2020-09-29 07:25:04 -07:00
|
|
|
l0[0] = C::Scalar::one();
|
2021-01-13 09:23:01 -08:00
|
|
|
let l0 = vk.domain.lagrange_to_coeff(l0);
|
|
|
|
let l0 = vk.domain.coeff_to_extended(l0, Rotation::cur());
|
2020-09-29 07:25:04 -07:00
|
|
|
|
|
|
|
Ok(ProvingKey {
|
2021-01-13 09:23:01 -08:00
|
|
|
vk,
|
2020-09-29 07:25:04 -07:00
|
|
|
l0,
|
2020-11-30 22:35:56 -08:00
|
|
|
fixed_values: assembly.fixed,
|
2020-09-29 07:25:04 -07:00
|
|
|
fixed_polys,
|
|
|
|
fixed_cosets,
|
2020-11-30 18:09:03 -08:00
|
|
|
permutations: permutation_pks,
|
2020-09-29 07:25:04 -07:00
|
|
|
})
|
|
|
|
}
|