pub mod curve_addition;
pub mod scalar_mul;
use crate::constraint_system::{variable::Variable, StandardComposer};
use dusk_bls12_381::BlsScalar;
use dusk_jubjub::EDWARDS_D;
#[derive(Debug, Clone, Copy)]
pub struct Point {
x: Variable,
y: Variable,
}
impl Point {
pub fn x(&self) -> &Variable {
&self.x
}
pub fn y(&self) -> &Variable {
&self.y
}
pub fn identity(composer: &mut StandardComposer) -> Point {
let one = composer.add_witness_to_circuit_description(BlsScalar::one());
Point {
x: composer.zero_var,
y: one,
}
}
pub fn from_private_affine(
composer: &mut StandardComposer,
affine: dusk_jubjub::JubJubAffine,
) -> Point {
let x = composer.add_input(affine.get_x());
let y = composer.add_input(affine.get_y());
Point { x, y }
}
pub fn from_public_affine(
composer: &mut StandardComposer,
affine: dusk_jubjub::JubJubAffine,
) -> Point {
let point = Point::from_private_affine(composer, affine);
composer.constrain_to_constant(point.x, BlsScalar::zero(), -affine.get_x());
composer.constrain_to_constant(point.y, BlsScalar::zero(), -affine.get_y());
point
}
pub fn conditional_select(
&self,
composer: &mut StandardComposer,
bit: Variable,
point_b: Point,
) -> Point {
let x = composer.conditional_select(bit, *self.x(), *point_b.x());
let y = composer.conditional_select(bit, *self.y(), *point_b.y());
Point { x, y }
}
}
#[derive(Debug, Clone, Copy)]
pub struct PointScalar {
point: Point,
scalar: Variable,
}
impl PointScalar {
pub fn point(&self) -> &Point {
&self.point
}
pub fn scalar(&self) -> &Variable {
&self.scalar
}
}
impl From<PointScalar> for Point {
fn from(ps: PointScalar) -> Point {
ps.point
}
}
impl Point {
pub fn add(&self, composer: &mut StandardComposer, point_b: Point) -> Point {
self.fast_add(composer, point_b)
}
pub fn slow_add(&self, composer: &mut StandardComposer, point_b: Point) -> Point {
let x1 = self.x;
let y1 = self.y;
let x2 = point_b.x;
let y2 = point_b.y;
let x1_y2 = composer.mul(
BlsScalar::one(),
x1,
y2,
BlsScalar::zero(),
BlsScalar::zero(),
);
let y1_x2 = composer.mul(
BlsScalar::one(),
y1,
x2,
BlsScalar::zero(),
BlsScalar::zero(),
);
let y1_y2 = composer.mul(
BlsScalar::one(),
y1,
y2,
BlsScalar::zero(),
BlsScalar::zero(),
);
let x1_x2 = composer.mul(
BlsScalar::one(),
x1,
x2,
BlsScalar::zero(),
BlsScalar::zero(),
);
let d_x1_x2_y1_y2 = composer.mul(
EDWARDS_D,
x1_x2,
y1_y2,
BlsScalar::zero(),
BlsScalar::zero(),
);
let x_numerator = composer.add(
(BlsScalar::one(), x1_y2),
(BlsScalar::one(), y1_x2),
BlsScalar::zero(),
BlsScalar::zero(),
);
let y_numerator = composer.add(
(BlsScalar::one(), y1_y2),
(BlsScalar::one(), x1_x2),
BlsScalar::zero(),
BlsScalar::zero(),
);
let x_denominator = composer.add(
(BlsScalar::one(), d_x1_x2_y1_y2),
(BlsScalar::zero(), composer.zero_var),
BlsScalar::one(),
BlsScalar::zero(),
);
let inv_x_denom = composer
.variables
.get(&x_denominator)
.unwrap()
.invert()
.unwrap();
let inv_x_denom = composer.add_input(inv_x_denom);
composer.mul_gate(
x_denominator,
inv_x_denom,
composer.zero_var,
BlsScalar::one(),
BlsScalar::zero(),
-BlsScalar::one(),
BlsScalar::zero(),
);
let y_denominator = composer.add(
(-BlsScalar::one(), d_x1_x2_y1_y2),
(BlsScalar::zero(), composer.zero_var),
BlsScalar::one(),
BlsScalar::zero(),
);
let inv_y_denom = composer
.variables
.get(&y_denominator)
.unwrap()
.invert()
.unwrap();
let inv_y_denom = composer.add_input(inv_y_denom);
composer.mul_gate(
y_denominator,
inv_y_denom,
composer.zero_var,
BlsScalar::one(),
BlsScalar::zero(),
-BlsScalar::one(),
BlsScalar::zero(),
);
let x_3 = composer.mul(
BlsScalar::one(),
inv_x_denom,
x_numerator,
BlsScalar::zero(),
BlsScalar::zero(),
);
let y_3 = composer.mul(
BlsScalar::one(),
inv_y_denom,
y_numerator,
BlsScalar::zero(),
BlsScalar::zero(),
);
Point { x: x_3, y: y_3 }
}
}
impl StandardComposer {
pub fn assert_equal_public_point(
&mut self,
point: Point,
public_point: dusk_jubjub::JubJubAffine,
) {
self.constrain_to_constant(point.x, BlsScalar::zero(), -public_point.get_x());
self.constrain_to_constant(point.y, BlsScalar::zero(), -public_point.get_y());
}
pub fn assert_equal_point(&mut self, point_a: Point, point_b: Point) {
self.assert_equal(point_a.x, point_b.x);
self.assert_equal(point_b.y, point_b.y);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::constraint_system::helper::*;
#[test]
fn test_conditional_select_point() {
let res = gadget_tester(
|composer| {
let bit_1 = composer.add_input(BlsScalar::one());
let bit_0 = composer.add_input(BlsScalar::zero());
let point_a = Point::identity(composer);
let point_b = Point {
x: composer.add_input(BlsScalar::from(10u64)),
y: composer.add_input(BlsScalar::from(20u64)),
};
let choice = point_a.conditional_select(composer, bit_1, point_b);
composer.assert_equal_point(point_a, choice);
let choice = point_a.conditional_select(composer, bit_0, point_b);
composer.assert_equal_point(point_b, choice);
},
32,
);
assert!(res.is_ok());
}
}