1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
use std::marker::PhantomData;

use crate::{BooleanExpression, Element, Expression, Field, GadgetBuilder, WireValues};

pub trait Curve<F: Field> {}

pub trait CurvePoint<F: Field, C: Curve<F>> {}

/// An embedded twisted Edwards curve defined over the same base field
/// as the field used in the constraint system
pub trait EdwardsCurve<F: Field> {
    fn a() -> Element<F>;
    fn d() -> Element<F>;
    fn subgroup_generator() -> (Element<F>, Element<F>);
}

/// An embedded Edwards curve point defined over the same base field
/// as the field used in the constraint system, with affine coordinates as
/// expressions.
pub struct EdwardsPointExpression<F: Field, C: EdwardsCurve<F>> {
    x: Expression<F>,
    y: Expression<F>,
    phantom: PhantomData<*const C>,
}

impl<F: Field, C: EdwardsCurve<F>> Clone for EdwardsPointExpression<F, C> {
    fn clone(&self) -> Self {
        EdwardsPointExpression {
            x: self.x.clone(),
            y: self.y.clone(),
            phantom: PhantomData,
        }
    }
}

/// An embedded Edwards curve point defined over the same base field as
/// the constraint system, with affine coordinates as elements.
pub struct EdwardsPoint<F: Field, C: EdwardsCurve<F>> {
    x: Element<F>,
    y: Element<F>,
    phantom: PhantomData<*const C>,
}

impl<F: Field, C: EdwardsCurve<F>> Clone for EdwardsPoint<F, C> {
    fn clone(&self) -> Self {
        EdwardsPoint {
            x: self.x.clone(),
            y: self.y.clone(),
            phantom: PhantomData,
        }
    }
}


/// An embedded Montgomery curve point defined over the same base field
/// as the field used in the constraint system, with affine coordinates as
/// expressions.
pub struct MontgomeryPointExpression<F: Field> {
    x: Expression<F>,
    y: Expression<F>,
}

/// An embedded Weierstrass curve point defined over the same base field
/// as the field used in the constraint system, with affine coordinates as
/// expressions.
pub struct WeierstrassPointExpression<F: Field> {
    x: Expression<F>,
    y: Expression<F>,
}

/// An embedded Weierstrass curve point defined over the same base field
/// as the field used in the constraint system, with projective coordinates
/// as expressions.
pub struct ProjWeierstrassPointExpression<F: Field> {
    x: Expression<F>,
    y: Expression<F>,
    z: Expression<F>,
}

impl<F: Field, C: EdwardsCurve<F>> EdwardsPoint<F, C> {
    /// Like `scalar_mult`, but actually evaluates the compression function rather than just adding it
    /// to a `GadgetBuilder`.
    pub fn scalar_mult_evaluate(&self, scalar: &Element<F>) -> EdwardsPoint<F, C> {
        let mut builder = GadgetBuilder::new();
        let new_point = EdwardsPointExpression::scalar_mult(
            &mut builder,
            &EdwardsPointExpression::from_edwards_point(self.clone()),
            &Expression::from(scalar),
        );
        let mut values = WireValues::new();
        builder.build().execute(&mut values);
        new_point.evaluate(&values)
    }

    /// Given an `x` and `y` coordinate, checks that they constitute a point on the curve
    /// and returns an `EdwardsPoint`
    pub fn from_elements(x: Element<F>, y: Element<F>) -> EdwardsPoint<F, C> {
        assert!(C::a() * &x * &x + &y * &y == Element::one() + C::d() * &x * &x * &y * &y,
                "Point must be contained on the curve.");
        EdwardsPoint { x, y, phantom: PhantomData }
    }

    /// Returns the Y coordinate of an `EdwardsPoint`
    pub fn compressed(&self) -> &Element<F> {
        &self.y
    }
}


impl<F: Field, C: EdwardsCurve<F>> EdwardsPointExpression<F, C> {
    /// Returns the Y coordinate of an `EdwardsPointExpression`
    pub fn compressed(&self) -> &Expression<F> {
        &self.y
    }

    /// Assumes that the `EdwardsPointExpressions` are known to be contained on the curve
    /// (and omits a membership check), so the non-deterministic inversion method is valid.
    // TODO: improve the constraint count by using an improved addition algorithm
    pub fn add(
        builder: &mut GadgetBuilder<F>,
        point_1: &EdwardsPointExpression<F, C>,
        point_2: &EdwardsPointExpression<F, C>,
    ) -> EdwardsPointExpression<F, C> {
        let d = C::d();
        let a = C::a();
        // TODO: better method for specifying variables
        let EdwardsPointExpression { x: x1, y: y1, phantom: _ } = point_1;
        let EdwardsPointExpression { x: x2, y: y2, phantom: _ } = point_2;
        let x1y2 = builder.product(&x1, &y2);
        let x2y1 = builder.product(&y1, &x2);
        let x1x2 = builder.product(&x1, &x2);
        let x1x2y1y2 = builder.product(&x1y2, &x2y1);
        let y1y2 = builder.product(&y1, &y2);
        let x3 = builder.quotient(&(x1y2 + x2y1), &(&x1x2y1y2 * &d + Expression::one()));
        let y3 = builder.quotient(&(y1y2 - &x1x2 * &a), &(&x1x2y1y2 * -&d + Expression::one()));
        EdwardsPointExpression::from_expressions_unsafe(x3, y3)
    }

    // TODO: improve constraint count
    /// Naive implementation of the doubling algorithm for twisted Edwards curves.
    ///
    /// Assuming that `EdwardsPointExpressions` are on the curve, so the non-deterministic
    /// division method is acceptable, as the denominator is non-zero.
    ///
    /// Note that this algorithm requires the point to be of odd order, which, in the case
    /// of prime-order subgroups of Edwards curves, is satisfied.
    pub fn double(
        builder: &mut GadgetBuilder<F>,
        point: &EdwardsPointExpression<F, C>,
    ) -> EdwardsPointExpression<F, C> {
        let EdwardsPointExpression { x, y, phantom: _ } = point;
        let a = C::a();

        let xy = builder.product(&x, &y);
        let xx = builder.product(&x, &x);
        let yy = builder.product(&y, &y);
        let x_2 = builder.quotient(&(&xy * Element::from(2u8)), &(&xx * &a + &yy));
        let y_2 = builder.quotient(&(&yy - &xx * &a),
                                   &(-&xx * &a - &yy + Expression::from(2u8)));

        EdwardsPointExpression::from_expressions_unsafe(x_2, y_2)
    }

    /// Multiplies an `EdwardsPointExpression` by a scalar using a naive approach consisting of
    /// multiplication by doubling.
    // TODO: implement Daira's algorithm from https://github.com/zcash/zcash/issues/3924
    pub fn scalar_mult(
        builder: &mut GadgetBuilder<F>,
        point: &EdwardsPointExpression<F, C>,
        scalar: &Expression<F>,
    ) -> EdwardsPointExpression<F, C> {
        let scalar_binary = builder.split_allowing_ambiguity(&scalar);

        let mut sum = Self::identity();
        let mut current = point.clone();
        for bit in scalar_binary.bits {
            let boolean_product = &Self::boolean_mult(builder, &current, &bit);
            sum = Self::add(builder, &sum, boolean_product);
            current = Self::double(builder, &current);
        }
        sum
    }

    /// Given a boolean element, return the given element if element is on, otherwise
    /// return the identity.
    fn boolean_mult(
        builder: &mut GadgetBuilder<F>,
        point: &EdwardsPointExpression<F, C>,
        boolean: &BooleanExpression<F>,
    ) -> EdwardsPointExpression<F, C> {
        let x = builder.selection(boolean, &point.x, &Expression::zero());
        let y = builder.selection(boolean, &point.y, &Expression::one());
        EdwardsPointExpression::from_expressions_unsafe(x, y)
    }

    /// Identity element for twisted Edwards Curve
    pub fn identity() -> EdwardsPointExpression<F, C> {
        EdwardsPointExpression::from_expressions_unsafe(Expression::zero(), Expression::one())
    }

    /// Takes two elements as coordinates, checks that they're on the curve without adding
    /// constraints, and then returns an EdwardsPointExpression
    pub fn from_elements(x: Element<F>, y: Element<F>) -> EdwardsPointExpression<F, C> {
        let p = EdwardsPoint::<F, C>::from_elements(x, y);
        EdwardsPointExpression::from_edwards_point(p)
    }

    /// Converts an EdwardsPoint into an EdwardsPointExpression. Assumes that the coordinates
    /// of the EdwardsPoint have already been verified on the curve
    pub fn from_edwards_point(p: EdwardsPoint<F, C>) -> EdwardsPointExpression<F, C> {
        EdwardsPointExpression::from_expressions_unsafe(Expression::from(p.x), Expression::from(p.y))
    }

    /// Takes two expressions as coordinates, adds constraints verifying that the coordinates
    /// are contained on the specified curve, and then returns an EdwardsPointExpression
    pub fn from_expressions(builder: &mut GadgetBuilder<F>, x: Expression<F>, y: Expression<F>) -> EdwardsPointExpression<F, C> {
        let x_squared = builder.product(&x, &x);
        let y_squared = builder.product(&y, &y);
        let x_squared_y_squared = builder.product(&x_squared, &y_squared);
        builder.assert_equal(&(&x_squared * C::a() + &y_squared),
                             &(&x_squared_y_squared * C::d() + Expression::one()));
        EdwardsPointExpression::from_expressions_unsafe(x, y)
    }

    /// Takes two expressions as coordinates, does not perform a check or add constraints
    /// to check that the coordinates are on the specified curve, and then returns an
    /// EdwardsPointExpression
    pub fn from_expressions_unsafe(x: Expression<F>, y: Expression<F>) -> EdwardsPointExpression<F, C> {
        EdwardsPointExpression { x, y, phantom: PhantomData }
    }

    /// Evaluates the EdwardsPointExpression by evaluating the expression in each coordinate
    pub fn evaluate(&self, values: &WireValues<F>) -> EdwardsPoint<F, C> {
        let x = self.x.evaluate(values);
        let y = self.y.evaluate(values);
        EdwardsPoint::from_elements(x, y)
    }
}

#[cfg(test)]
mod tests {
    use std::str::FromStr;

    use crate::{EdwardsPointExpression, Expression, GadgetBuilder, WireValues};
    use crate::embedded_curve::JubJub;
    use crate::field::{Bls12_381, Element};

    #[test]
    fn point_on_curve() {
        let x = Element::from_str(
            "11076627216317271660298050606127911965867021807910416450833192264015104452986"
        ).unwrap();
        let y = Element::from_str(
            "44412834903739585386157632289020980010620626017712148233229312325549216099227"
        ).unwrap();

        let x_exp = Expression::from(x);
        let y_exp = Expression::from(y);

        let mut builder = GadgetBuilder::<Bls12_381>::new();
        let p = EdwardsPointExpression::<Bls12_381, JubJub>::from_expressions(
            &mut builder, x_exp, y_exp);

        let gadget = builder.build();
        assert!(gadget.execute(&mut WireValues::new()));
    }

    #[test]
    fn point_not_on_curve_with_expressions() {
        let x = Element::from_str(
            "11076627216317271660298050606127911965867021807910416450833192264015104452986"
        ).unwrap();
        let y = Element::from_str(
            "44412834903739585386157632289020980010620626017712148233229312325549216099226"
        ).unwrap();

        let x_exp = Expression::from(x);
        let y_exp = Expression::from(y);

        let mut builder = GadgetBuilder::<Bls12_381>::new();
        let p = EdwardsPointExpression::<Bls12_381, JubJub>::from_expressions(
            &mut builder, x_exp, y_exp);

        let gadget = builder.build();
        assert!(!gadget.execute(&mut WireValues::new()));
    }

    #[test]
    #[should_panic]
    fn point_not_on_curve() {
        let x = Element::from_str(
            "11076627216317271660298050606127911965867021807910416450833192264015104452985"
        ).unwrap();

        let y = Element::from_str(
            "44412834903739585386157632289020980010620626017712148233229312325549216099227"
        ).unwrap();

        EdwardsPointExpression::<Bls12_381, JubJub>::from_elements(x, y);
    }

    #[test]
    fn add_and_negate() {
        let x1 = Element::<Bls12_381>::from_str(
            "11076627216317271660298050606127911965867021807910416450833192264015104452986"
        ).unwrap();
        let y1 = Element::<Bls12_381>::from_str(
            "44412834903739585386157632289020980010620626017712148233229312325549216099227"
        ).unwrap();

        let p1 = EdwardsPointExpression::<Bls12_381, JubJub>::from_elements(x1, y1);

        let p2 = EdwardsPointExpression::<Bls12_381, JubJub>::from_expressions_unsafe(-p1.x.clone(), p1.y.clone());

        let mut builder = GadgetBuilder::<Bls12_381>::new();
        let p3 = EdwardsPointExpression::<Bls12_381, JubJub>::add(&mut builder, &p1, &p2);
        let gadget = builder.build();
        let mut values = WireValues::new();
        gadget.execute(&mut values);
        assert_eq!(p3.x.evaluate(&values), Element::zero());
        assert_eq!(p3.y.evaluate(&values), Element::one());
    }

    #[test]
    fn scalar_mult() {
        let x1 = Element::<Bls12_381>::from_str(
            "11076627216317271660298050606127911965867021807910416450833192264015104452986"
        ).unwrap();
        let y1 = Element::<Bls12_381>::from_str(
            "44412834903739585386157632289020980010620626017712148233229312325549216099227"
        ).unwrap();

        let scalar = Expression::<Bls12_381>::from(
            Element::<Bls12_381>::from_str(
                "444128349033229312325549216099227444128349033229312325549216099220000000"
            ).unwrap()
        );

        let p1 = EdwardsPointExpression::<Bls12_381, JubJub>::from_elements(x1, y1);

        let mut builder = GadgetBuilder::<Bls12_381>::new();
        let p3 = EdwardsPointExpression::<Bls12_381, JubJub>::scalar_mult(
            &mut builder,
            &p1,
            &scalar,
        );
        let gadget = builder.build();
        let mut values = WireValues::new();
        gadget.execute(&mut values);

        // TODO: include assertion
    }
}