Skip to content

Commit

Permalink
Redefine LinComb to be + c, not - c
Browse files Browse the repository at this point in the history
This is simpler to work with. It will require a negation before being used in a
BP constraint, yet that'll be fine to so convert then.
  • Loading branch information
kayabaNerve committed May 2, 2024
1 parent f67de59 commit 7ff4349
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 30 deletions.
14 changes: 5 additions & 9 deletions crypto/fcmps/src/gadgets/interactive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub(crate) struct ClaimedPointWithDlog<F: Field> {
generator: (F, F),
divisor: Divisor,
pub(crate) dlog: Vec<Variable>,
point: (Variable, Variable),
point: (Variable, Variable)
}

impl<C: Ciphersuite> Circuit<C> {
Expand Down Expand Up @@ -77,7 +77,7 @@ impl<C: Ciphersuite> Circuit<C> {

fn divisor_challenge_invert(&mut self, scalar: C::F) -> C::F {
let res = Option::from(scalar.invert());
// If somehow, we are trying to invert zero, push a constraint requiring -1 = 0
// If somehow, we are trying to invert zero, push a constraint requiring 1 = 0
// This will cause the proof to fail to verify
// TODO: Properly propagate this error
if res.is_none() {
Expand Down Expand Up @@ -119,8 +119,7 @@ impl<C: Ciphersuite> Circuit<C> {
// The evaluation of the divisor differentiated by x
let p_0_n_2 = {
// The coefficient for x**1 is 1, so 1 becomes the new zero coefficient
// Since the constant is subtracted, we use -1 for the constant (making it +1)
let mut p_0_n_2 = LinComb::empty().constant(-C::F::ONE);
let mut p_0_n_2 = LinComb::empty().constant(C::F::ONE);

// Handle the new y coefficient
p_0_n_2 = p_0_n_2.term(c_y, divisor.yx[0]);
Expand Down Expand Up @@ -180,10 +179,8 @@ impl<C: Ciphersuite> Circuit<C> {
c_x_eval *= c_x;
}

// We add -c_x to c so this evaluates as `+ c_x` (since c is subtracted from the linear
// combination)
// Adding c_x effectively adds a `1 x` term, ensuring the divisor isn't 0
p_0_d.term(C::F::ONE, divisor.zero).constant(-c_x)
p_0_d.term(C::F::ONE, divisor.zero).constant(c_x)
};

let p_1_n = two_c_y;
Expand Down Expand Up @@ -301,9 +298,8 @@ impl<C: Ciphersuite> Circuit<C> {
// intercept - (y - (slope * x))
// intercept - y + (slope * x))
// -y + (slope * x)) + intercept
// We use -intercept since constants are subtracted
let output_interpolation =
LinComb::empty().constant(-intercept).term(-C::F::ONE, point.y).term(slope, point.x);
LinComb::empty().constant(intercept).term(-C::F::ONE, point.y).term(slope, point.x);
let output_interpolation_eval = self.eval(&output_interpolation);
let (_output_interpolation, inverse) =
self.inverse(Some(output_interpolation), output_interpolation_eval);
Expand Down
24 changes: 10 additions & 14 deletions crypto/fcmps/src/gadgets/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl<C: Ciphersuite> Circuit<C> {
let (l, r, o) = self.mul(a, None, witness.map(|f| (f, f.invert().unwrap())));
// The output of a value multiplied by its inverse is 1
// Constrain `1 o - 1 = 0`
self.constraints.push(LinComb::from(o).constant(C::F::ONE));
self.constraints.push(LinComb::from(o).constant(-C::F::ONE));
(l, r)
}

Expand Down Expand Up @@ -91,17 +91,13 @@ impl<C: Ciphersuite> Circuit<C> {
}

/// Constrain an x and y coordinate as being on curve to a towered elliptic curve.
pub(crate) fn on_curve(
&mut self,
curve: &CurveSpec<C::F>,
(x, y): (Variable, Variable),
) -> OnCurve {
pub(crate) fn on_curve(&mut self, curve: &CurveSpec<C::F>, (x, y): (Variable, Variable)) -> OnCurve {
let x_eval = self.eval(&LinComb::from(x));
let (_x, _x_2, x2) =
self.mul(Some(LinComb::from(x)), Some(LinComb::from(x)), x_eval.map(|x| (x, x)));
let (_x, _x_2, x3) =
self.mul(Some(LinComb::from(x2)), Some(LinComb::from(x)), x_eval.map(|x| (x * x, x)));
let expected_y2 = LinComb::from(x3).term(curve.a, x).constant(-curve.b);
let expected_y2 = LinComb::from(x3).term(curve.a, x).constant(curve.b);

let y_eval = self.eval(&LinComb::from(y));
let (_y, _y_2, y2) =
Expand All @@ -119,7 +115,7 @@ impl<C: Ciphersuite> Circuit<C> {
{
let bx_lincomb = LinComb::from(b.x);
let bx_eval = self.eval(&bx_lincomb);
self.inequality(bx_lincomb, &LinComb::empty().constant(-a.0), bx_eval.map(|bx| (bx, a.0)));
self.inequality(bx_lincomb, &LinComb::empty().constant(a.0), bx_eval.map(|bx| (bx, a.0)));
}

let (x0, y0) = (a.0, a.1);
Expand All @@ -133,26 +129,26 @@ impl<C: Ciphersuite> Circuit<C> {
});

// slope * (x1 - x0) = y1 - y0
let x1_minus_x0 = LinComb::from(x1).constant(x0);
let x1_minus_x0 = LinComb::from(x1).constant(-x0);
let x1_minus_x0_eval = self.eval(&x1_minus_x0);
let (slope, _r, o) =
self.mul(None, Some(x1_minus_x0), slope_eval.map(|slope| (slope, x1_minus_x0_eval.unwrap())));
self.equality(LinComb::from(o), &LinComb::from(y1).constant(y0));
self.equality(LinComb::from(o), &LinComb::from(y1).constant(-y0));

// slope * (x2 - x0) = -y2 - y0
let x2_minus_x0 = LinComb::from(x2).constant(x0);
let x2_minus_x0 = LinComb::from(x2).constant(-x0);
let x2_minus_x0_eval = self.eval(&x2_minus_x0);
let (_slope, _x2_minus_x0, o) = self.mul(
Some(slope.into()),
Some(x2_minus_x0),
slope_eval.map(|slope| (slope, x2_minus_x0_eval.unwrap())),
);
self.equality(o.into(), &LinComb::empty().term(-C::F::ONE, y2).constant(y0));
self.equality(o.into(), &LinComb::empty().term(-C::F::ONE, y2).constant(-y0));

// slope * slope = x0 + x1 + x2
let (_slope, _slope_2, o) =
self.mul(Some(slope.into()), Some(slope.into()), slope_eval.map(|slope| (slope, slope)));
self.equality(o.into(), &LinComb::from(x1).term(C::F::ONE, x2).constant(-x0));
self.equality(o.into(), &LinComb::from(x1).term(C::F::ONE, x2).constant(x0));

OnCurve { x: x2, y: y2 }
}
Expand All @@ -162,7 +158,7 @@ impl<C: Ciphersuite> Circuit<C> {
/// Panics if the prover and the `y` coordinate isn't permissible.
pub(crate) fn permissible(&mut self, a: C::F, b: C::F, y: Variable) {
// a y - -b = ay + b
let p = LinComb::empty().term(a, y).constant(-b);
let p = LinComb::empty().term(a, y).constant(b);
let p_eval = self.eval(&p);
let p_eval_sqrt = p_eval.map(|p_eval| p_eval.sqrt().unwrap());

Expand Down
7 changes: 2 additions & 5 deletions crypto/fcmps/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl<C: Ciphersuite> Circuit<C> {
/// Returns None if not a prover.
fn eval(&self, constraint: &LinComb<C::F>) -> Option<C::F> {
self.prover.as_ref().map(|prover| {
let mut res = -constraint.c;
let mut res = constraint.c;
for (index, weight) in &constraint.WL {
res += prover.aL[*index] * weight;
}
Expand Down Expand Up @@ -122,10 +122,7 @@ impl<C: Ciphersuite> Circuit<C> {
// An honest verifier will generate the intended circuit (using a consistent set of variables)
// and still reject such proofs
// This check only exists for sanity/safety to ensure an honest verifier doesn't mis-call this
assert_eq!(
i_blind_u.dlog, i_blind_v.dlog,
"first layer passed differing variables for the dlog"
);
assert_eq!(i_blind_u.dlog, i_blind_v.dlog, "first layer passed differing variables for the dlog");

let i_blind_u = self.discrete_log(transcript, curve, i_blind_u);
let I = self.on_curve(curve, I);
Expand Down
4 changes: 2 additions & 2 deletions crypto/fcmps/src/lincomb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ pub(crate) enum Variable {

/// A linear combination.
///
/// Specifically, this is WL aL + WR aR + WO aO + WC C - c.
/// Specifically, this is WL aL + WR aR + WO aO + WC C + c.
// We don't model WV as we don't use Pedersen commitments
#[derive(Clone, PartialEq, Eq, Debug)]
#[must_use]
Expand Down Expand Up @@ -97,7 +97,7 @@ impl<F: Field> LinComb<F> {
self
}

/// Add to the constant c which is subtracted from the rest of the linear combination.
/// Add to the constant c, which is added to the rest of the linear combination.
pub(crate) fn constant(mut self, scalar: F) -> Self {
self.c += scalar;
self
Expand Down

0 comments on commit 7ff4349

Please sign in to comment.