mirror of
https://github.com/saymrwulf/pasta_curves-source.git
synced 2026-09-06 20:20:34 +00:00
Update structured reference string and API for permutation argument.
This commit is contained in:
parent
85fd924b15
commit
dc5df10832
4 changed files with 186 additions and 42 deletions
46
src/plonk.rs
46
src/plonk.rs
|
|
@ -32,6 +32,9 @@ pub struct SRS<C: CurveAffine> {
|
||||||
fixed_commitments: Vec<C>,
|
fixed_commitments: Vec<C>,
|
||||||
fixed_polys: Vec<Vec<C::Scalar>>,
|
fixed_polys: Vec<Vec<C::Scalar>>,
|
||||||
fixed_cosets: Vec<Vec<C::Scalar>>,
|
fixed_cosets: Vec<Vec<C::Scalar>>,
|
||||||
|
permutation_commitments: Vec<Vec<C>>,
|
||||||
|
permutation_polys: Vec<Vec<Vec<C::Scalar>>>,
|
||||||
|
permutation_cosets: Vec<Vec<Vec<C::Scalar>>>,
|
||||||
meta: MetaCircuit<C::Scalar>,
|
meta: MetaCircuit<C::Scalar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,6 +90,10 @@ fn test_proving() {
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
const K: u32 = 5;
|
const K: u32 = 5;
|
||||||
|
|
||||||
|
/// This represents an advice wire at a certain row in the MetaCircuit
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct Variable(AdviceWire, usize);
|
||||||
|
|
||||||
// Initialize the polynomial commitment parameters
|
// Initialize the polynomial commitment parameters
|
||||||
let params: Params<EqAffine> = Params::new::<DummyHash<Fq>>(K);
|
let params: Params<EqAffine> = Params::new::<DummyHash<Fq>>(K);
|
||||||
|
|
||||||
|
|
@ -99,6 +106,8 @@ fn test_proving() {
|
||||||
sb: FixedWire,
|
sb: FixedWire,
|
||||||
sc: FixedWire,
|
sc: FixedWire,
|
||||||
sm: FixedWire,
|
sm: FixedWire,
|
||||||
|
|
||||||
|
perm: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
trait StandardCS<FF: Field> {
|
trait StandardCS<FF: Field> {
|
||||||
|
|
@ -108,6 +117,7 @@ fn test_proving() {
|
||||||
fn raw_add<F>(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error>
|
fn raw_add<F>(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Result<(FF, FF, FF), Error>;
|
F: FnOnce() -> Result<(FF, FF, FF), Error>;
|
||||||
|
fn copy(&mut self, a: Variable, b: Variable) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MyCircuit<F: Field> {
|
struct MyCircuit<F: Field> {
|
||||||
|
|
@ -160,9 +170,9 @@ fn test_proving() {
|
||||||
self.cs
|
self.cs
|
||||||
.assign_fixed(self.config.sm, index, || Ok(FF::one()))?;
|
.assign_fixed(self.config.sm, index, || Ok(FF::one()))?;
|
||||||
Ok((
|
Ok((
|
||||||
Variable::new(self.config.a, index),
|
Variable(self.config.a, index),
|
||||||
Variable::new(self.config.b, index),
|
Variable(self.config.b, index),
|
||||||
Variable::new(self.config.c, index),
|
Variable(self.config.c, index),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
fn raw_add<F>(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error>
|
fn raw_add<F>(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error>
|
||||||
|
|
@ -192,11 +202,28 @@ fn test_proving() {
|
||||||
self.cs
|
self.cs
|
||||||
.assign_fixed(self.config.sm, index, || Ok(FF::zero()))?;
|
.assign_fixed(self.config.sm, index, || Ok(FF::zero()))?;
|
||||||
Ok((
|
Ok((
|
||||||
Variable::new(self.config.a, index),
|
Variable(self.config.a, index),
|
||||||
Variable::new(self.config.b, index),
|
Variable(self.config.b, index),
|
||||||
Variable::new(self.config.c, index),
|
Variable(self.config.c, index),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
fn copy(&mut self, a: Variable, b: Variable) -> Result<(), Error> {
|
||||||
|
let left_wire = match a.0 {
|
||||||
|
x if x == self.config.a => 0,
|
||||||
|
x if x == self.config.b => 1,
|
||||||
|
x if x == self.config.c => 2,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
let right_wire = match b.0 {
|
||||||
|
x if x == self.config.a => 0,
|
||||||
|
x if x == self.config.b => 1,
|
||||||
|
x if x == self.config.c => 2,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.cs
|
||||||
|
.copy(self.config.perm, left_wire, a.1, right_wire, b.1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> Circuit<F> for MyCircuit<F> {
|
impl<F: Field> Circuit<F> for MyCircuit<F> {
|
||||||
|
|
@ -207,6 +234,8 @@ fn test_proving() {
|
||||||
let b = meta.advice_wire();
|
let b = meta.advice_wire();
|
||||||
let c = meta.advice_wire();
|
let c = meta.advice_wire();
|
||||||
|
|
||||||
|
let perm = meta.permutation(&[a, b, c]);
|
||||||
|
|
||||||
let sa = meta.fixed_wire();
|
let sa = meta.fixed_wire();
|
||||||
let sb = meta.fixed_wire();
|
let sb = meta.fixed_wire();
|
||||||
let sc = meta.fixed_wire();
|
let sc = meta.fixed_wire();
|
||||||
|
|
@ -233,6 +262,7 @@ fn test_proving() {
|
||||||
sb,
|
sb,
|
||||||
sc,
|
sc,
|
||||||
sm,
|
sm,
|
||||||
|
perm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -253,7 +283,7 @@ fn test_proving() {
|
||||||
a_squared.ok_or(Error::SynthesisError)?,
|
a_squared.ok_or(Error::SynthesisError)?,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let (a1, _, _) = cs.raw_add(|| {
|
let (_, b1, _) = cs.raw_add(|| {
|
||||||
let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2));
|
let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2));
|
||||||
Ok((
|
Ok((
|
||||||
self.a.ok_or(Error::SynthesisError)?,
|
self.a.ok_or(Error::SynthesisError)?,
|
||||||
|
|
@ -261,7 +291,7 @@ fn test_proving() {
|
||||||
fin.ok_or(Error::SynthesisError)?,
|
fin.ok_or(Error::SynthesisError)?,
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
cs.cs.assign_copy(a1, c0)?;
|
cs.copy(b1, c0)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
|
|
@ -14,17 +14,6 @@ pub struct FixedWire(pub usize);
|
||||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
pub struct AdviceWire(pub usize);
|
pub struct AdviceWire(pub usize);
|
||||||
|
|
||||||
/// This represents an advice wire at a certain row in the MetaCircuit
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
|
||||||
pub struct Variable(pub AdviceWire, pub usize);
|
|
||||||
|
|
||||||
impl Variable {
|
|
||||||
/// Construct a Variable
|
|
||||||
pub fn new(wire: AdviceWire, index: usize) -> Variable {
|
|
||||||
Variable(wire, index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This trait allows a [`Circuit`] to direct some backend to assign a witness
|
/// This trait allows a [`Circuit`] to direct some backend to assign a witness
|
||||||
/// for a constraint system.
|
/// for a constraint system.
|
||||||
pub trait ConstraintSystem<F: Field> {
|
pub trait ConstraintSystem<F: Field> {
|
||||||
|
|
@ -45,7 +34,14 @@ pub trait ConstraintSystem<F: Field> {
|
||||||
) -> Result<(), Error>;
|
) -> Result<(), Error>;
|
||||||
|
|
||||||
/// Assign two advice wires to have the same value
|
/// Assign two advice wires to have the same value
|
||||||
fn assign_copy(&mut self, left: Variable, right: Variable) -> Result<(), Error>;
|
fn copy(
|
||||||
|
&mut self,
|
||||||
|
permutation: usize,
|
||||||
|
left_wire: usize,
|
||||||
|
left_row: usize,
|
||||||
|
right_wire: usize,
|
||||||
|
right_row: usize,
|
||||||
|
) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a trait that circuits provide implementations for so that the
|
/// This is a trait that circuits provide implementations for so that the
|
||||||
|
|
@ -165,6 +161,14 @@ pub struct MetaCircuit<F> {
|
||||||
|
|
||||||
// Mapping from a witness vector rotation to the index in the point vector.
|
// Mapping from a witness vector rotation to the index in the point vector.
|
||||||
pub(crate) rotations: HashMap<Rotation, PointIndex>,
|
pub(crate) rotations: HashMap<Rotation, PointIndex>,
|
||||||
|
|
||||||
|
// Vector of permutation arguments, where each corresponds to a set of wires
|
||||||
|
// that are involved in a permutation argument. As an example, we could have
|
||||||
|
// a permutation argument between wires (A, B, C) which allows copy
|
||||||
|
// constraints to be enforced between advice wire values in A, B and C, and
|
||||||
|
// another permutation between wires (B, C, D) which allows the same with D
|
||||||
|
// instead of A.
|
||||||
|
pub(crate) permutations: Vec<Vec<AdviceWire>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> Default for MetaCircuit<F> {
|
impl<F: Field> Default for MetaCircuit<F> {
|
||||||
|
|
@ -179,11 +183,19 @@ impl<F: Field> Default for MetaCircuit<F> {
|
||||||
fixed_queries: Vec::new(),
|
fixed_queries: Vec::new(),
|
||||||
advice_queries: Vec::new(),
|
advice_queries: Vec::new(),
|
||||||
rotations,
|
rotations,
|
||||||
|
permutations: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> MetaCircuit<F> {
|
impl<F: Field> MetaCircuit<F> {
|
||||||
|
/// Add a permutation argument for some advice wires
|
||||||
|
pub fn permutation(&mut self, wires: &[AdviceWire]) -> usize {
|
||||||
|
let index = self.permutations.len();
|
||||||
|
self.permutations.push(wires.to_vec());
|
||||||
|
index
|
||||||
|
}
|
||||||
|
|
||||||
/// Query a fixed wire at a relative position
|
/// Query a fixed wire at a relative position
|
||||||
pub fn query_fixed(&mut self, wire: FixedWire, at: i32) -> Polynomial<F> {
|
pub fn query_fixed(&mut self, wire: FixedWire, at: i32) -> Polynomial<F> {
|
||||||
let at = Rotation(at);
|
let at = Rotation(at);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{
|
use super::{
|
||||||
circuit::{AdviceWire, Circuit, ConstraintSystem, FixedWire, MetaCircuit, Variable},
|
circuit::{AdviceWire, Circuit, ConstraintSystem, FixedWire, MetaCircuit},
|
||||||
domain::Rotation,
|
domain::Rotation,
|
||||||
hash_point, Error, Proof, SRS,
|
hash_point, Error, Proof, SRS,
|
||||||
};
|
};
|
||||||
|
|
@ -54,7 +54,14 @@ impl<C: CurveAffine> Proof<C> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_copy(&mut self, _: Variable, _: Variable) -> Result<(), Error> {
|
fn copy(
|
||||||
|
&mut self,
|
||||||
|
_: usize,
|
||||||
|
_: usize,
|
||||||
|
_: usize,
|
||||||
|
_: usize,
|
||||||
|
_: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
// We only care about advice wires here
|
// We only care about advice wires here
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
||||||
135
src/plonk/srs.rs
135
src/plonk/srs.rs
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{
|
use super::{
|
||||||
circuit::{AdviceWire, Circuit, ConstraintSystem, FixedWire, MetaCircuit, Variable},
|
circuit::{AdviceWire, Circuit, ConstraintSystem, FixedWire, MetaCircuit},
|
||||||
domain::EvaluationDomain,
|
domain::{EvaluationDomain, Rotation},
|
||||||
Error, SRS,
|
Error, SRS,
|
||||||
};
|
};
|
||||||
use crate::arithmetic::{Curve, CurveAffine, Field};
|
use crate::arithmetic::{Curve, CurveAffine, Field};
|
||||||
|
|
@ -15,7 +15,7 @@ impl<C: CurveAffine> SRS<C> {
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
struct Assembly<F: Field> {
|
struct Assembly<F: Field> {
|
||||||
fixed: Vec<Vec<F>>,
|
fixed: Vec<Vec<F>>,
|
||||||
copy: Vec<Vec<Variable>>,
|
copy: Vec<Vec<Vec<(usize, usize)>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F: Field> ConstraintSystem<F> for Assembly<F> {
|
impl<F: Field> ConstraintSystem<F> for Assembly<F> {
|
||||||
|
|
@ -44,12 +44,38 @@ impl<C: CurveAffine> SRS<C> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> {
|
fn copy(
|
||||||
*self
|
&mut self,
|
||||||
.copy
|
permutation: usize,
|
||||||
.get_mut((left.0).0)
|
left_wire: usize,
|
||||||
.and_then(|v| v.get_mut(left.1))
|
left_row: usize,
|
||||||
.ok_or(Error::BoundsFailure)? = right;
|
right_wire: usize,
|
||||||
|
right_row: usize,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let left: (usize, usize) = *self.copy[permutation]
|
||||||
|
.get_mut(left_wire)
|
||||||
|
.and_then(|wire| wire.get_mut(left_row))
|
||||||
|
.ok_or(Error::BoundsFailure)?;
|
||||||
|
|
||||||
|
let right: (usize, usize) = *self.copy[permutation]
|
||||||
|
.get_mut(right_wire)
|
||||||
|
.and_then(|wire| wire.get_mut(right_row))
|
||||||
|
.ok_or(Error::BoundsFailure)?;
|
||||||
|
|
||||||
|
if left == (left_wire, left_row) || right == (right_wire, right_row) {
|
||||||
|
// Don't perform the copy constraint because it will undo
|
||||||
|
// the effect of the permutation.
|
||||||
|
} else {
|
||||||
|
*self.copy[permutation]
|
||||||
|
.get_mut(left_wire)
|
||||||
|
.and_then(|wire| wire.get_mut(left_row))
|
||||||
|
.ok_or(Error::BoundsFailure)? = right;
|
||||||
|
|
||||||
|
*self.copy[permutation]
|
||||||
|
.get_mut(right_wire)
|
||||||
|
.and_then(|wire| wire.get_mut(right_row))
|
||||||
|
.ok_or(Error::BoundsFailure)? = left;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
@ -58,30 +84,96 @@ impl<C: CurveAffine> SRS<C> {
|
||||||
let mut meta = MetaCircuit::default();
|
let mut meta = MetaCircuit::default();
|
||||||
let config = ConcreteCircuit::configure(&mut meta);
|
let config = ConcreteCircuit::configure(&mut meta);
|
||||||
|
|
||||||
|
let mut degree = 1;
|
||||||
|
for poly in meta.gates.iter() {
|
||||||
|
degree = std::cmp::max(degree, poly.degree());
|
||||||
|
}
|
||||||
|
for permutation in &meta.permutations {
|
||||||
|
degree = std::cmp::max(degree, permutation.len() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
let domain = EvaluationDomain::new(degree as u32, params.k);
|
||||||
|
|
||||||
|
let mut largest_permutation_length = 0;
|
||||||
|
for permutation in &meta.permutations {
|
||||||
|
largest_permutation_length =
|
||||||
|
std::cmp::max(permutation.len(), largest_permutation_length);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut omega_powers = Vec::with_capacity(params.n as usize);
|
||||||
|
{
|
||||||
|
let mut cur = C::Scalar::one();
|
||||||
|
for _ in 0..params.n {
|
||||||
|
omega_powers.push(cur);
|
||||||
|
cur *= &domain.get_omega();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut deltaomega = Vec::with_capacity(largest_permutation_length);
|
||||||
|
{
|
||||||
|
let mut cur = C::Scalar::one();
|
||||||
|
for _ in 0..largest_permutation_length {
|
||||||
|
let mut omega_powers = omega_powers.clone();
|
||||||
|
for o in &mut omega_powers {
|
||||||
|
*o *= &cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
deltaomega.push(omega_powers);
|
||||||
|
|
||||||
|
cur *= &C::Scalar::DELTA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut assembly: Assembly<C::Scalar> = Assembly {
|
let mut assembly: Assembly<C::Scalar> = Assembly {
|
||||||
fixed: vec![vec![C::Scalar::zero(); params.n as usize]; meta.num_fixed_wires],
|
fixed: vec![vec![C::Scalar::zero(); params.n as usize]; meta.num_fixed_wires],
|
||||||
copy: vec![
|
copy: vec![],
|
||||||
vec![Variable::new(AdviceWire(0), 0); params.n as usize];
|
|
||||||
meta.num_advice_wires
|
|
||||||
],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
for permutation in &meta.permutations {
|
||||||
|
let mut wires = vec![];
|
||||||
|
for (i, _) in permutation.iter().enumerate() {
|
||||||
|
wires.push((0..params.n).map(|j| (i, j as usize)).collect());
|
||||||
|
}
|
||||||
|
assembly.copy.push(wires);
|
||||||
|
}
|
||||||
|
|
||||||
// Synthesize the circuit to obtain SRS
|
// Synthesize the circuit to obtain SRS
|
||||||
circuit.synthesize(&mut assembly, config)?;
|
circuit.synthesize(&mut assembly, config)?;
|
||||||
|
|
||||||
|
// Compute permutation polynomials
|
||||||
|
let mut permutation_commitments = vec![];
|
||||||
|
let mut permutation_polys = vec![];
|
||||||
|
let mut permutation_cosets = vec![];
|
||||||
|
for (permutation_index, permutation) in meta.permutations.iter().enumerate() {
|
||||||
|
let mut commitments = vec![];
|
||||||
|
let mut polys = vec![];
|
||||||
|
let mut cosets = vec![];
|
||||||
|
for (i, _) in permutation.iter().enumerate() {
|
||||||
|
let permutation_poly: Vec<_> = (0..params.n as usize)
|
||||||
|
.map(|j| {
|
||||||
|
let (permuted_i, permuted_j) = assembly.copy[permutation_index][i][j];
|
||||||
|
deltaomega[permuted_i][permuted_j]
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
commitments.push(
|
||||||
|
params
|
||||||
|
.commit_lagrange(&permutation_poly, C::Scalar::one())
|
||||||
|
.to_affine(),
|
||||||
|
);
|
||||||
|
polys.push(permutation_poly.clone());
|
||||||
|
cosets.push(domain.obtain_coset(permutation_poly, Rotation::default()));
|
||||||
|
}
|
||||||
|
permutation_commitments.push(commitments);
|
||||||
|
permutation_polys.push(polys);
|
||||||
|
permutation_cosets.push(cosets);
|
||||||
|
}
|
||||||
|
|
||||||
let fixed_commitments = assembly
|
let fixed_commitments = assembly
|
||||||
.fixed
|
.fixed
|
||||||
.iter()
|
.iter()
|
||||||
.map(|poly| params.commit_lagrange(poly, C::Scalar::one()).to_affine())
|
.map(|poly| params.commit_lagrange(poly, C::Scalar::one()).to_affine())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut degree = 1;
|
|
||||||
for poly in meta.gates.iter() {
|
|
||||||
degree = std::cmp::max(degree, poly.degree());
|
|
||||||
}
|
|
||||||
|
|
||||||
let domain = EvaluationDomain::new(degree as u32, params.k);
|
|
||||||
|
|
||||||
let fixed_polys: Vec<_> = assembly
|
let fixed_polys: Vec<_> = assembly
|
||||||
.fixed
|
.fixed
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|
@ -102,6 +194,9 @@ impl<C: CurveAffine> SRS<C> {
|
||||||
fixed_commitments,
|
fixed_commitments,
|
||||||
fixed_polys,
|
fixed_polys,
|
||||||
fixed_cosets,
|
fixed_cosets,
|
||||||
|
permutation_commitments,
|
||||||
|
permutation_polys,
|
||||||
|
permutation_cosets,
|
||||||
meta,
|
meta,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue