Allow commitments to generic advice wire polynomials

This commit is contained in:
Sean Bowe 2020-08-22 16:10:27 -06:00
parent c16141be9a
commit 7edffe0197
No known key found for this signature in database
GPG key ID: 95684257D8F8B031
5 changed files with 191 additions and 17 deletions

View file

@ -42,15 +42,21 @@ pub struct SRS<C: CurveAffine> {
sd_commitment: C,
sm_commitment: C,
domain: EvaluationDomain<C::Scalar>,
fixed_commitments: Vec<C>,
fixed_polys: Vec<(Vec<C::Scalar>, Vec<C::Scalar>)>,
meta: MetaCircuit,
}
/// This is an object which represents a (Turbo)PLONK proof.
// This structure must never allow points at infinity.
#[derive(Debug, Clone)]
pub struct Proof<C: CurveAffine> {
a_commitment: C,
b_commitment: C,
c_commitment: C,
d_commitment: C,
advice_commitments: Vec<C>,
h_commitments: Vec<C>,
a_eval_x: C::Scalar,
b_eval_x: C::Scalar,
@ -77,6 +83,8 @@ pub enum Error {
IncompatibleParams,
/// The constraint system is not satisfied.
ConstraintSystemFailure,
/// Out of bounds index passed to a backend
BoundsFailure,
}
fn hash_point<C: CurveAffine, H: Hasher<C::Base>>(
@ -103,7 +111,16 @@ fn test_proving() {
// Initialize the polynomial commitment parameters
let params: Params<EqAffine> = Params::new::<DummyHash<Fq>>(K);
struct MyConfig {}
struct MyConfig {
a: Wire,
b: Wire,
c: Wire,
sa: Wire,
sb: Wire,
sc: Wire,
sm: Wire,
}
struct MyCircuit<F: Field> {
a: Option<F>,
}
@ -112,7 +129,24 @@ fn test_proving() {
type Config = MyConfig;
fn configure(meta: &mut MetaCircuit) -> MyConfig {
MyConfig {}
let a = meta.advice_wire();
let b = meta.advice_wire();
let c = meta.advice_wire();
let sa = meta.fixed_wire();
let sb = meta.fixed_wire();
let sc = meta.fixed_wire();
let sm = meta.fixed_wire();
MyConfig {
a,
b,
c,
sa,
sb,
sc,
sm,
}
}
fn synthesize(
@ -137,6 +171,42 @@ fn test_proving() {
//cs.copy(c, e);
}
// Similar to the above...
let mut row = 0;
for _ in 0..10 {
cs.assign(Variable(config.a, row), || {
self.a.ok_or(Error::SynthesisError)
})?;
cs.assign(Variable(config.b, row), || {
self.a.ok_or(Error::SynthesisError)
})?;
let a_squared = self.a.map(|a| a.square());
cs.assign(Variable(config.c, row), || {
self.a.ok_or(Error::SynthesisError)
})?;
// Multiplication gate
cs.assign(Variable(config.sa, row), || Ok(Field::zero()))?;
cs.assign(Variable(config.sb, row), || Ok(Field::zero()))?;
cs.assign(Variable(config.sc, row), || Ok(Field::one()))?;
cs.assign(Variable(config.sm, row), || Ok(Field::one()))?;
row += 1;
cs.assign(Variable(config.a, row), || {
self.a.ok_or(Error::SynthesisError)
})?;
cs.assign(Variable(config.b, row), || {
a_squared.ok_or(Error::SynthesisError)
})?;
let fin = a_squared.and_then(|a_squared| self.a.map(|a| a + a_squared));
cs.assign(Variable(config.c, row), || fin.ok_or(Error::SynthesisError))?;
// Addition gate
cs.assign(Variable(config.sa, row), || Ok(Field::one()))?;
cs.assign(Variable(config.sb, row), || Ok(Field::one()))?;
cs.assign(Variable(config.sc, row), || Ok(Field::one()))?;
cs.assign(Variable(config.sm, row), || Ok(Field::zero()))?;
row += 1;
}
Ok(())
}
}

View file

@ -6,7 +6,7 @@ use crate::arithmetic::Field;
/// This represents a PLONK wire, which could be a fixed (selector) wire or an
/// advice wire.
#[derive(Clone, Debug)]
#[derive(Copy, Clone, Debug)]
pub enum Wire {
/// A wires
A,
@ -16,15 +16,23 @@ pub enum Wire {
C,
/// D wires
D,
/// Fixed wires
Fixed(usize),
/// Advice wires
Advice(usize),
}
/// Represents a pointer to a value in the constraint system.
#[derive(Clone, Debug)]
pub struct Variable(pub(crate) Wire, pub(crate) usize);
pub struct Variable(pub Wire, pub usize);
/// This trait allows a [`Circuit`] to direct some backend to assign a witness
/// for a constraint system.
pub trait ConstraintSystem<F: Field> {
/// Assign a wire value
fn assign(&mut self, var: Variable, to: impl FnOnce() -> Result<F, Error>)
-> Result<(), Error>;
/// Creates a gate.
fn create_gate(
&mut self,
@ -131,8 +139,8 @@ impl<F> Mul<F> for Polynomial<F> {
/// permutation arrangements.
#[derive(Debug, Clone)]
pub struct MetaCircuit {
// num_fixed_wires: usize,
// num_advice_wires: usize,
pub(crate) num_fixed_wires: usize,
pub(crate) num_advice_wires: usize,
// permutations: Vec<Vec<Wire>>,
// gates: Vec<Polynomial>,
// queries: HashSet<(Wire, usize)>,
@ -141,6 +149,24 @@ pub struct MetaCircuit {
impl Default for MetaCircuit {
fn default() -> MetaCircuit {
MetaCircuit {}
MetaCircuit {
num_fixed_wires: 0,
num_advice_wires: 0,
}
}
}
impl MetaCircuit {
/// Allocate a new fixed wire
pub fn fixed_wire(&mut self) -> Wire {
let tmp = Wire::Fixed(self.num_fixed_wires);
self.num_fixed_wires += 1;
tmp
}
/// Allocate a new advice wire
pub fn advice_wire(&mut self) -> Wire {
let tmp = Wire::Advice(self.num_advice_wires);
self.num_advice_wires += 1;
tmp
}
}

View file

@ -1,5 +1,5 @@
use super::{
circuit::{Circuit, ConstraintSystem, MetaCircuit, Wire, Variable},
circuit::{Circuit, ConstraintSystem, MetaCircuit, Variable, Wire},
hash_point, Error, Proof, SRS,
};
use crate::arithmetic::{
@ -31,9 +31,29 @@ impl<C: CurveAffine> Proof<C> {
sc: Vec<F>,
sd: Vec<F>,
sm: Vec<F>,
advice: Vec<Vec<F>>,
}
impl<F: Field> ConstraintSystem<F> for WitnessCollection<F> {
fn assign(
&mut self,
var: Variable,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> {
// We only care about advice wires here.
match var.0 {
Wire::Advice(index) => {
*self
.advice
.get_mut(index)
.and_then(|v| v.get_mut(var.1))
.ok_or(Error::BoundsFailure)? = to()?;
}
_ => {}
}
Ok(())
}
fn create_gate(
&mut self,
sa: F,
@ -66,6 +86,9 @@ impl<C: CurveAffine> Proof<C> {
// }
}
let mut meta = MetaCircuit::default();
let config = ConcreteCircuit::configure(&mut meta);
let mut witness = WitnessCollection {
a: vec![],
b: vec![],
@ -76,12 +99,9 @@ impl<C: CurveAffine> Proof<C> {
sc: vec![],
sd: vec![],
sm: vec![],
advice: vec![vec![C::Scalar::zero(); params.n as usize]; meta.num_advice_wires],
};
let mut meta = MetaCircuit::default();
let config = ConcreteCircuit::configure(&mut meta);
// Synthesize the circuit to obtain the witness and other information.
circuit.synthesize(&mut witness, config)?;
@ -115,10 +135,21 @@ impl<C: CurveAffine> Proof<C> {
let c_commitment = params.commit_lagrange(&witness.c, c_blind).to_affine();
let d_commitment = params.commit_lagrange(&witness.d, d_blind).to_affine();
let advice_blinds = vec![C::Scalar::one(); witness.advice.len()]; // TODO: not random
let advice_commitments = witness
.advice
.iter()
.zip(advice_blinds.iter())
.map(|(poly, blind)| params.commit_lagrange(poly, *blind).to_affine())
.collect();
hash_point(&mut transcript, &a_commitment)?;
hash_point(&mut transcript, &b_commitment)?;
hash_point(&mut transcript, &c_commitment)?;
hash_point(&mut transcript, &d_commitment)?;
for commitment in &advice_commitments {
hash_point(&mut transcript, commitment)?;
}
let domain = &srs.domain;
@ -127,6 +158,12 @@ impl<C: CurveAffine> Proof<C> {
let (c_coset, c_poly) = domain.obtain_coset(witness.c);
let (d_coset, d_poly) = domain.obtain_coset(witness.d);
let advice_polys: Vec<_> = witness
.advice
.into_iter()
.map(|poly| domain.obtain_coset(poly))
.collect();
// (a * sa) + (b * sb) + (a * sm * b) + (d * sd) - (c * sc)
let mut h_poly = Vec::with_capacity(a_coset.len());
for ((((((((a, b), c), d), sa), sb), sc), sd), sm) in a_coset
@ -253,6 +290,7 @@ impl<C: CurveAffine> Proof<C> {
b_commitment,
c_commitment,
d_commitment,
advice_commitments,
h_commitments,
a_eval_x,
b_eval_x,

View file

@ -1,5 +1,5 @@
use super::{
circuit::{Circuit, ConstraintSystem, MetaCircuit, Wire, Variable},
circuit::{Circuit, ConstraintSystem, MetaCircuit, Variable, Wire},
domain::EvaluationDomain,
Error, GATE_DEGREE, SRS,
};
@ -19,9 +19,28 @@ impl<C: CurveAffine> SRS<C> {
sc: Vec<F>,
sd: Vec<F>,
sm: Vec<F>,
fixed: Vec<Vec<F>>,
}
impl<F: Field> ConstraintSystem<F> for Assembly<F> {
fn assign(
&mut self,
var: Variable,
to: impl FnOnce() -> Result<F, Error>,
) -> Result<(), Error> {
// We only care about fixed wires here.
match var.0 {
Wire::Fixed(index) => {
*self
.fixed
.get_mut(index)
.and_then(|v| v.get_mut(var.1))
.ok_or(Error::BoundsFailure)? = to()?;
}
_ => {}
}
Ok(())
}
fn create_gate(
&mut self,
sa: F,
@ -46,18 +65,18 @@ impl<C: CurveAffine> SRS<C> {
}
}
let mut meta = MetaCircuit::default();
let config = ConcreteCircuit::configure(&mut meta);
let mut assembly: Assembly<C::Scalar> = Assembly {
sa: vec![],
sb: vec![],
sc: vec![],
sd: vec![],
sm: vec![],
fixed: vec![vec![C::Scalar::zero(); params.n as usize]; meta.num_fixed_wires],
};
let mut meta = MetaCircuit::default();
let config = ConcreteCircuit::configure(&mut meta);
// Synthesize the circuit to obtain SRS
circuit.synthesize(&mut assembly, config)?;
@ -84,6 +103,12 @@ impl<C: CurveAffine> SRS<C> {
.commit_lagrange(&assembly.sm, C::Scalar::one())
.to_affine();
let fixed_commitments = assembly
.fixed
.iter()
.map(|poly| params.commit_lagrange(poly, C::Scalar::one()).to_affine())
.collect();
let domain = EvaluationDomain::new(GATE_DEGREE, params.k);
let sa = domain.obtain_coset(assembly.sa);
@ -92,6 +117,12 @@ impl<C: CurveAffine> SRS<C> {
let sd = domain.obtain_coset(assembly.sd);
let sm = domain.obtain_coset(assembly.sm);
let fixed_polys = assembly
.fixed
.into_iter()
.map(|poly| domain.obtain_coset(poly))
.collect();
Ok(SRS {
sa,
sb,
@ -104,6 +135,10 @@ impl<C: CurveAffine> SRS<C> {
sd_commitment,
sm_commitment,
domain,
fixed_commitments,
fixed_polys,
meta,
})
}
}

View file

@ -22,6 +22,11 @@ impl<C: CurveAffine> Proof<C> {
hash_point(&mut transcript, &self.d_commitment)
.expect("proof cannot contain points at infinity");
for commitment in &self.advice_commitments {
hash_point(&mut transcript, commitment)
.expect("proof cannot contain points at infinity");
}
for c in &self.h_commitments {
hash_point(&mut transcript, c).expect("proof cannot contain points at infinity");
}