Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combine coefficient polynomials #168

Merged
merged 17 commits into from
Oct 12, 2021
26 changes: 18 additions & 8 deletions circuits/plonk-15-wires/src/gates/generic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ use crate::wires::{GateWires, COLUMNS, GENERICS};
use ark_ff::FftField;
use array_init::array_init;

pub const MUL_COEFF: usize = GENERICS;
pub const CONSTANT_COEFF: usize = GENERICS + 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is great. Also "index" more than "coeff" no?


impl<F: FftField> CircuitGate<F> {
// TODO(mimoo): why qw is length 15 if the polynomial side only uses 3?
pub fn create_generic(row: usize, wires: GateWires, qw: [F; COLUMNS], qm: F, qc: F) -> Self {
pub fn create_generic(row: usize, wires: GateWires, qw: [F; GENERICS], qm: F, qc: F) -> Self {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had meant to look into why it was set to the full columns, thanks for fixing that!

let mut c = qw.to_vec();
c.push(qm);
c.push(qc);
Expand All @@ -28,7 +30,7 @@ impl<F: FftField> CircuitGate<F> {
pub fn create_generic_add(row: usize, wires: GateWires) -> Self {
let on = F::one();
let off = F::zero();
let qw: [F; COLUMNS] = array_init(|col| {
let qw: [F; GENERICS] = array_init(|col| {
if col < 2 {
on
Copy link
Contributor

@mimoo mimoo Oct 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw this function is missing the fact that you can scale the operand freely, which I didn't think about back when I wrote that.

} else if col == 2 {
Expand All @@ -44,23 +46,23 @@ impl<F: FftField> CircuitGate<F> {
pub fn create_generic_mul(row: usize, wires: GateWires) -> Self {
let on = F::one();
let off = F::zero();
let qw: [F; COLUMNS] = array_init(|col| if col == 2 { on } else { off });
let qw: [F; GENERICS] = array_init(|col| if col == 2 { on } else { off });
Self::create_generic(row, wires, qw, -on, off)
}

/// creates a constant gate
pub fn create_generic_const(row: usize, wires: GateWires, constant: F) -> Self {
let on = F::one();
let off = F::zero();
let qw: [F; COLUMNS] = array_init(|col| if col == 0 { on } else { off });
let qw: [F; GENERICS] = array_init(|col| if col == 0 { on } else { off });
Self::create_generic(row, wires, qw, off, -constant)
}

/// creates a public input gate
pub fn create_generic_public(row: usize, wires: GateWires) -> Self {
let on = F::one();
let off = F::zero();
let qw: [F; COLUMNS] = array_init(|col| if col == 0 { on } else { off });
let qw: [F; GENERICS] = array_init(|col| if col == 0 { on } else { off });
Self::create_generic(row, wires, qw, off, off)
}

Expand All @@ -73,8 +75,8 @@ impl<F: FftField> CircuitGate<F> {
let right = this[1];

// selector vectors
let mul_selector = self.c[COLUMNS];
let constant_selector = self.c[COLUMNS + 1];
let mul_selector = self.c[MUL_COEFF];
let constant_selector = self.c[CONSTANT_COEFF];

// constants
let zero = F::zero();
Expand Down Expand Up @@ -102,4 +104,12 @@ impl<F: FftField> CircuitGate<F> {
// all good
return Ok(());
}

pub fn generic(&self) -> F {
if self.typ == GateType::Generic {
F::one()
} else {
F::zero()
}
}
}
117 changes: 34 additions & 83 deletions circuits/plonk-15-wires/src/nolookup/constraints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ This source file implements Plonk circuit constraint primitive.
*****************************************************************************************************************/

use crate::domains::EvaluationDomains;
use crate::gate::{CircuitGate, GateType};
use crate::gates::poseidon::*;
use crate::gate::CircuitGate;
pub use crate::polynomial::{WitnessEvals, WitnessOverDomains, WitnessShifts};
use crate::wires::*;
use ark_ff::{FftField, SquareRootField, Zero};
Expand Down Expand Up @@ -45,23 +44,23 @@ pub struct ConstraintSystem<F: FftField> {
#[serde_as(as = "o1_utils::serialization::SerdeAs")]
pub zkpm: DP<F>,

// Coefficient polynomials. These define constant that gates can use as they like.
// ---------------------------------------

/// coefficients polynomials in coefficient form
#[serde_as(as = "[o1_utils::serialization::SerdeAs; COLUMNS]")]
pub coefficientsm: [DP<F>; COLUMNS],
/// coefficients polynomials in evaluation form
#[serde_as(as = "[o1_utils::serialization::SerdeAs; COLUMNS]")]
pub coefficients4: [E<F, D<F>>; COLUMNS],

// Generic constraint selector polynomials
// ---------------------------------------
/// linear wire constraint polynomial
#[serde_as(as = "[o1_utils::serialization::SerdeAs; GENERICS]")]
pub qwm: [DP<F>; GENERICS],
/// multiplication polynomial
#[serde_as(as = "o1_utils::serialization::SerdeAs")]
pub qmm: DP<F>,
/// constant wire polynomial
#[serde_as(as = "o1_utils::serialization::SerdeAs")]
pub qc: DP<F>,
pub genericm: DP<F>,

// Poseidon selector polynomials
// -----------------------------
/// round constant polynomials
#[serde_as(as = "[[o1_utils::serialization::SerdeAs; SPONGE_WIDTH]; ROUNDS_PER_ROW]")]
pub rcm: [[DP<F>; SPONGE_WIDTH]; ROUNDS_PER_ROW],
/// poseidon constraint selector polynomial
#[serde_as(as = "o1_utils::serialization::SerdeAs")]
pub psm: DP<F>,
Expand All @@ -87,12 +86,9 @@ pub struct ConstraintSystem<F: FftField> {

// Generic constraint selector polynomials
// ---------------------------------------
/// left input wire polynomial over domain.d4
#[serde_as(as = "[o1_utils::serialization::SerdeAs; GENERICS]")]
pub qwl: [E<F, D<F>>; GENERICS],
/// multiplication evaluations over domain.d4
#[serde_as(as = "o1_utils::serialization::SerdeAs")]
pub qml: E<F, D<F>>,
pub generic4: E<F, D<F>>,

// permutation polynomials
// -----------------------
Expand Down Expand Up @@ -265,36 +261,6 @@ impl<F: FftField + SquareRootField> ConstraintSystem<F> {
let zkpm = zk_polynomial(domain.d1);

// compute generic constraint polynomials
let qwm: [DP<F>; GENERICS] = array_init(|i| {
E::<F, D<F>>::from_vec_and_domain(
gates
.iter()
.map(|gate| {
if gate.typ == GateType::Generic {
gate.c[WIRES[i]]
} else {
F::zero()
}
})
.collect(),
domain.d1,
)
.interpolate()
});
let qmm = E::<F, D<F>>::from_vec_and_domain(
gates
.iter()
.map(|gate| {
if gate.typ == GateType::Generic {
gate.c[COLUMNS]
} else {
F::zero()
}
})
.collect(),
domain.d1,
)
.interpolate();

// compute poseidon constraint polynomials
let psm = E::<F, D<F>>::from_vec_and_domain(
Expand Down Expand Up @@ -328,42 +294,29 @@ impl<F: FftField + SquareRootField> ConstraintSystem<F> {
let sigmal8 = array_init(|i| sigmam[i].evaluate_over_domain_by_ref(domain.d8));

// generic constraint polynomials
let qwl = array_init(|i| qwm[i].evaluate_over_domain_by_ref(domain.d4));
let qml = qmm.evaluate_over_domain_by_ref(domain.d4);
let qc = E::<F, D<F>>::from_vec_and_domain(
gates
.iter()
.map(|gate| {
if gate.typ == GateType::Generic {
gate.c[COLUMNS + 1]
} else {
F::zero()
}
})
.collect(),

let genericm = E::<F, D<F>>::from_vec_and_domain(
gates.iter().map(|gate| gate.generic()).collect(),
domain.d1,
)
.interpolate();
let generic4 = genericm.evaluate_over_domain_by_ref(domain.d4);

// poseidon constraint polynomials
let rcm = array_init(|round| {
array_init(|col| {
let coefficientsm: [_; COLUMNS] =
array_init(|i| {
E::<F, D<F>>::from_vec_and_domain(
gates
.iter()
.map(|gate| {
if gate.typ == GateType::Poseidon {
gate.rc()[round][col]
} else {
F::zero()
}
})
.collect(),
domain.d1,
)
gates.iter().map(|gate| {
if i < gate.c.len() {
gate.c[i]
} else {
F::zero()
}
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one-liner:

gate.c.get(i).unwrap_or(F::zero())

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting, maybe it'd be good to document somewhere that if you need static coefficients for your gate, you should use the coefficient polynomials/commitments

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually the one liner doesn't work because you get a borrow from get. I guess you could make it work by mapping but seemed kind more awkward than this to me

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gate.c.get(i).copied().unwrap_or(F::zero()) ?

.collect(),
domain.d1)
.interpolate()
})
});
});
let coefficients4 = array_init(|i| coefficientsm[i].evaluate_over_domain_by_ref(domain.d4));

let ps4 = psm.evaluate_over_domain_by_ref(domain.d4);
let ps8 = psm.evaluate_over_domain_by_ref(domain.d8);
Expand Down Expand Up @@ -400,12 +353,10 @@ impl<F: FftField + SquareRootField> ConstraintSystem<F> {
sigmal1,
sigmal8,
sigmam,
qwl,
qml,
qwm,
qmm,
qc,
rcm,
genericm,
generic4,
coefficientsm,
coefficients4,
ps4,
ps8,
psm,
Expand Down
6 changes: 6 additions & 0 deletions circuits/plonk-15-wires/src/nolookup/scalars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ pub struct ProofEvaluations<Field> {
/// permutation polynomials
/// (PERMUTS-1 evaluations because the last permutation is only used in commitment form)
pub s: [Field; PERMUTS - 1],
/// evaluation of the generic selector polynomial
pub generic_selector: Field,
/// evaluation of the poseidon selector polynomial
pub poseidon_selector: Field,
}

impl<F: FftField> ProofEvaluations<Vec<F>> {
Expand All @@ -29,6 +33,8 @@ impl<F: FftField> ProofEvaluations<Vec<F>> {
s: array_init(|i| DensePolynomial::eval_polynomial(&self.s[i], pt)),
w: array_init(|i| DensePolynomial::eval_polynomial(&self.w[i], pt)),
z: DensePolynomial::eval_polynomial(&self.z, pt),
generic_selector: DensePolynomial::eval_polynomial(&self.generic_selector, pt),
poseidon_selector: DensePolynomial::eval_polynomial(&self.poseidon_selector, pt),
}
}
}
Expand Down
Loading