use crate::field::{Field, FieldStorage};
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct Affine {
pub x: Field,
pub y: Field,
pub infinity: bool,
}
#[derive(Debug, Clone, Copy)]
pub struct Jacobian {
pub x: Field,
pub y: Field,
pub z: Field,
pub infinity: bool,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub struct AffineStorage {
pub x: FieldStorage,
pub y: FieldStorage,
}
impl Default for Affine {
fn default() -> Affine {
Affine {
x: Field::default(),
y: Field::default(),
infinity: false,
}
}
}
impl Default for Jacobian {
fn default() -> Jacobian {
Jacobian {
x: Field::default(),
y: Field::default(),
z: Field::default(),
infinity: false,
}
}
}
impl Default for AffineStorage {
fn default() -> AffineStorage {
AffineStorage {
x: FieldStorage::default(),
y: FieldStorage::default(),
}
}
}
pub static AFFINE_INFINITY: Affine = Affine {
x: Field::new(0, 0, 0, 0, 0, 0, 0, 0),
y: Field::new(0, 0, 0, 0, 0, 0, 0, 0),
infinity: true,
};
pub static JACOBIAN_INFINITY: Jacobian = Jacobian {
x: Field::new(0, 0, 0, 0, 0, 0, 0, 0),
y: Field::new(0, 0, 0, 0, 0, 0, 0, 0),
z: Field::new(0, 0, 0, 0, 0, 0, 0, 0),
infinity: true,
};
pub static AFFINE_G: Affine = Affine::new(
Field::new(
0x79BE667E, 0xF9DCBBAC, 0x55A06295, 0xCE870B07, 0x029BFCDB, 0x2DCE28D9, 0x59F2815B,
0x16F81798,
),
Field::new(
0x483ADA77, 0x26A3C465, 0x5DA4FBFC, 0x0E1108A8, 0xFD17B448, 0xA6855419, 0x9C47D08F,
0xFB10D4B8,
),
);
pub const CURVE_B: u32 = 7;
impl Affine {
pub const fn new(x: Field, y: Field) -> Self {
Self {
x,
y,
infinity: false,
}
}
pub fn set_xy(&mut self, x: &Field, y: &Field) {
self.infinity = false;
self.x = *x;
self.y = *y;
}
pub fn set_xquad(&mut self, x: &Field) -> bool {
self.x = *x;
let x2 = x.sqr();
let x3 = *x * x2;
self.infinity = false;
let mut c = Field::default();
c.set_int(CURVE_B);
c += x3;
let (v, ret) = c.sqrt();
self.y = v;
ret
}
pub fn set_xo_var(&mut self, x: &Field, odd: bool) -> bool {
if !self.set_xquad(x) {
return false;
}
self.y.normalize_var();
if self.y.is_odd() != odd {
self.y = self.y.neg(1);
}
true
}
pub fn is_infinity(&self) -> bool {
self.infinity
}
pub fn is_valid_var(&self) -> bool {
if self.is_infinity() {
return false;
}
let y2 = self.y.sqr();
let mut x3 = self.x.sqr();
x3 *= &self.x;
let mut c = Field::default();
c.set_int(CURVE_B);
x3 += &c;
x3.normalize_weak();
y2.eq_var(&x3)
}
pub fn neg_in_place(&mut self, other: &Affine) {
*self = *other;
self.y.normalize_weak();
self.y = self.y.neg(1);
}
pub fn neg(&self) -> Affine {
let mut ret = Affine::default();
ret.neg_in_place(self);
ret
}
pub fn set_gej(&mut self, a: &Jacobian) {
self.infinity = a.infinity;
let mut a = *a;
a.z = a.z.inv();
let z2 = a.z.sqr();
let z3 = a.z * z2;
a.x *= z2;
a.y *= z3;
a.z.set_int(1);
self.x = a.x;
self.y = a.y;
}
pub fn from_gej(a: &Jacobian) -> Self {
let mut ge = Self::default();
ge.set_gej(a);
ge
}
pub fn set_gej_var(&mut self, a: &Jacobian) {
let mut a = *a;
self.infinity = a.infinity;
if a.is_infinity() {
return;
}
a.z = a.z.inv_var();
let z2 = a.z.sqr();
let z3 = a.z * z2;
a.x *= &z2;
a.y *= &z3;
a.z.set_int(1);
self.x = a.x;
self.y = a.y;
}
pub fn set_gej_zinv(&mut self, a: &Jacobian, zi: &Field) {
let zi2 = zi.sqr();
let zi3 = zi2 * *zi;
self.x = a.x * zi2;
self.y = a.y * zi3;
self.infinity = a.infinity;
}
pub fn clear(&mut self) {
self.infinity = false;
self.x.clear();
self.y.clear();
}
}
pub fn set_table_gej_var(r: &mut [Affine], a: &[Jacobian], zr: &[Field]) {
debug_assert!(r.len() == a.len());
let mut i = r.len() - 1;
let mut zi: Field;
if !r.is_empty() {
zi = a[i].z.inv();
r[i].set_gej_zinv(&a[i], &zi);
while i > 0 {
zi *= &zr[i];
i -= 1;
r[i].set_gej_zinv(&a[i], &zi);
}
}
}
pub fn globalz_set_table_gej(r: &mut [Affine], globalz: &mut Field, a: &[Jacobian], zr: &[Field]) {
debug_assert!(r.len() == a.len() && a.len() == zr.len());
let mut i = r.len() - 1;
let mut zs: Field;
if !r.is_empty() {
r[i].x = a[i].x;
r[i].y = a[i].y;
*globalz = a[i].z;
r[i].infinity = false;
zs = zr[i];
while i > 0 {
if i != r.len() - 1 {
zs *= zr[i];
}
i -= 1;
r[i].set_gej_zinv(&a[i], &zs);
}
}
}
impl Jacobian {
pub const fn new(x: Field, y: Field) -> Self {
Self {
x,
y,
infinity: false,
z: Field::new(0, 0, 0, 0, 0, 0, 0, 1),
}
}
pub fn set_infinity(&mut self) {
self.infinity = true;
self.x.clear();
self.y.clear();
self.z.clear();
}
pub fn set_ge(&mut self, a: &Affine) {
self.infinity = a.infinity;
self.x = a.x;
self.y = a.y;
self.z.set_int(1);
}
pub fn from_ge(a: &Affine) -> Self {
let mut gej = Self::default();
gej.set_ge(a);
gej
}
pub fn eq_x_var(&self, x: &Field) -> bool {
debug_assert!(!self.is_infinity());
let mut r = self.z.sqr();
r *= x;
let mut r2 = self.x;
r2.normalize_weak();
r.eq_var(&r2)
}
pub fn neg_in_place(&mut self, a: &Jacobian) {
self.infinity = a.infinity;
self.x = a.x;
self.y = a.y;
self.z = a.z;
self.y.normalize_weak();
self.y = self.y.neg(1);
}
pub fn neg(&self) -> Jacobian {
let mut ret = Jacobian::default();
ret.neg_in_place(self);
ret
}
pub fn is_infinity(&self) -> bool {
self.infinity
}
pub fn has_quad_y_var(&self) -> bool {
if self.infinity {
return false;
}
let yz = self.y * self.z;
yz.is_quad_var()
}
pub fn double_nonzero_in_place(&mut self, a: &Jacobian, rzr: Option<&mut Field>) {
debug_assert!(!self.is_infinity());
self.double_var_in_place(a, rzr);
}
pub fn double_var_in_place(&mut self, a: &Jacobian, rzr: Option<&mut Field>) {
self.infinity = a.infinity;
if self.infinity {
if let Some(rzr) = rzr {
rzr.set_int(1);
}
return;
}
if let Some(rzr) = rzr {
*rzr = a.y;
rzr.normalize_weak();
rzr.mul_int(2);
}
self.z = a.z * a.y;
self.z.mul_int(2);
let mut t1 = a.x.sqr();
t1.mul_int(3);
let mut t2 = t1.sqr();
let mut t3 = a.y.sqr();
t3.mul_int(2);
let mut t4 = t3.sqr();
t4.mul_int(2);
t3 *= &a.x;
self.x = t3;
self.x.mul_int(4);
self.x = self.x.neg(4);
self.x += &t2;
t2 = t2.neg(1);
t3.mul_int(6);
t3 += &t2;
self.y = t1 * t3;
t2 = t4.neg(2);
self.y += t2;
}
pub fn double_var(&self, rzr: Option<&mut Field>) -> Jacobian {
let mut ret = Jacobian::default();
ret.double_var_in_place(&self, rzr);
ret
}
pub fn add_var_in_place(&mut self, a: &Jacobian, b: &Jacobian, rzr: Option<&mut Field>) {
if a.is_infinity() {
debug_assert!(rzr.is_none());
*self = *b;
return;
}
if b.is_infinity() {
if let Some(rzr) = rzr {
rzr.set_int(1);
}
*self = *a;
return;
}
self.infinity = false;
let z22 = b.z.sqr();
let z12 = a.z.sqr();
let u1 = a.x * z22;
let u2 = b.x * z12;
let mut s1 = a.y * z22;
s1 *= b.z;
let mut s2 = b.y * z12;
s2 *= a.z;
let mut h = u1.neg(1);
h += u2;
let mut i = s1.neg(1);
i += s2;
if h.normalizes_to_zero_var() {
if i.normalizes_to_zero_var() {
self.double_var_in_place(a, rzr);
} else {
if let Some(rzr) = rzr {
rzr.set_int(0);
}
self.infinity = true;
}
return;
}
let i2 = i.sqr();
let h2 = h.sqr();
let mut h3 = h * h2;
h *= b.z;
if let Some(rzr) = rzr {
*rzr = h;
}
self.z = a.z * h;
let t = u1 * h2;
self.x = t;
self.x.mul_int(2);
self.x += h3;
self.x = self.x.neg(3);
self.x += i2;
self.y = self.x.neg(5);
self.y += t;
self.y *= i;
h3 *= s1;
h3 = h3.neg(1);
self.y += h3;
}
pub fn add_var(&self, b: &Jacobian, rzr: Option<&mut Field>) -> Jacobian {
let mut ret = Jacobian::default();
ret.add_var_in_place(self, b, rzr);
ret
}
pub fn add_ge_in_place(&mut self, a: &Jacobian, b: &Affine) {
const FE1: Field = Field::new(0, 0, 0, 0, 0, 0, 0, 1);
debug_assert!(!b.infinity);
let zz = a.z.sqr();
let mut u1 = a.x;
u1.normalize_weak();
let u2 = b.x * zz;
let mut s1 = a.y;
s1.normalize_weak();
let mut s2 = b.y * zz;
s2 *= a.z;
let mut t = u1;
t += u2;
let mut m = s1;
m += s2;
let mut rr = t.sqr();
let mut m_alt = u2.neg(1);
let tt = u1 * m_alt;
rr += tt;
let degenerate = m.normalizes_to_zero() && rr.normalizes_to_zero();
let mut rr_alt = s1;
rr_alt.mul_int(2);
m_alt += u1;
rr_alt.cmov(&rr, !degenerate);
m_alt.cmov(&m, !degenerate);
let mut n = m_alt.sqr();
let mut q = n * t;
n = n.sqr();
n.cmov(&m, degenerate);
t = rr_alt.sqr();
self.z = a.z * m_alt;
let infinity = {
let p = self.z.normalizes_to_zero();
let q = a.infinity;
match (p, q) {
(true, true) => false,
(true, false) => true,
(false, true) => false,
(false, false) => false,
}
};
self.z.mul_int(2);
q = q.neg(1);
t += q;
t.normalize_weak();
self.x = t;
t.mul_int(2);
t += q;
t *= rr_alt;
t += n;
self.y = t.neg(3);
self.y.normalize_weak();
self.x.mul_int(4);
self.y.mul_int(4);
self.x.cmov(&b.x, a.infinity);
self.y.cmov(&b.y, a.infinity);
self.z.cmov(&FE1, a.infinity);
self.infinity = infinity;
}
pub fn add_ge(&self, b: &Affine) -> Jacobian {
let mut ret = Jacobian::default();
ret.add_ge_in_place(self, b);
ret
}
pub fn add_ge_var_in_place(&mut self, a: &Jacobian, b: &Affine, rzr: Option<&mut Field>) {
if a.is_infinity() {
debug_assert!(rzr.is_none());
self.set_ge(b);
return;
}
if b.is_infinity() {
if let Some(rzr) = rzr {
rzr.set_int(1);
}
*self = *a;
return;
}
self.infinity = false;
let z12 = a.z.sqr();
let mut u1 = a.x;
u1.normalize_weak();
let u2 = b.x * z12;
let mut s1 = a.y;
s1.normalize_weak();
let mut s2 = b.y * z12;
s2 *= a.z;
let mut h = u1.neg(1);
h += u2;
let mut i = s1.neg(1);
i += s2;
if h.normalizes_to_zero_var() {
if i.normalizes_to_zero_var() {
self.double_var_in_place(a, rzr);
} else {
if let Some(rzr) = rzr {
rzr.set_int(0);
}
self.infinity = true;
}
return;
}
let i2 = i.sqr();
let h2 = h.sqr();
let mut h3 = h * h2;
if let Some(rzr) = rzr {
*rzr = h;
}
self.z = a.z * h;
let t = u1 * h2;
self.x = t;
self.x.mul_int(2);
self.x += h3;
self.x = self.x.neg(3);
self.x += i2;
self.y = self.x.neg(5);
self.y += t;
self.y *= i;
h3 *= s1;
h3 = h3.neg(1);
self.y += h3;
}
pub fn add_ge_var(&self, b: &Affine, rzr: Option<&mut Field>) -> Jacobian {
let mut ret = Jacobian::default();
ret.add_ge_var_in_place(&self, b, rzr);
ret
}
pub fn add_zinv_var_in_place(&mut self, a: &Jacobian, b: &Affine, bzinv: &Field) {
if b.is_infinity() {
*self = *a;
return;
}
if a.is_infinity() {
self.infinity = b.infinity;
let bzinv2 = bzinv.sqr();
let bzinv3 = &bzinv2 * bzinv;
self.x = b.x * bzinv2;
self.y = b.y * bzinv3;
self.z.set_int(1);
return;
}
self.infinity = false;
let az = a.z * *bzinv;
let z12 = az.sqr();
let mut u1 = a.x;
u1.normalize_weak();
let u2 = b.x * z12;
let mut s1 = a.y;
s1.normalize_weak();
let mut s2 = b.y * z12;
s2 *= &az;
let mut h = u1.neg(1);
h += &u2;
let mut i = s1.neg(1);
i += &s2;
if h.normalizes_to_zero_var() {
if i.normalizes_to_zero_var() {
self.double_var_in_place(a, None);
} else {
self.infinity = true;
}
return;
}
let i2 = i.sqr();
let h2 = h.sqr();
let mut h3 = h * h2;
self.z = a.z;
self.z *= h;
let t = u1 * h2;
self.x = t;
self.x.mul_int(2);
self.x += h3;
self.x = self.x.neg(3);
self.x += i2;
self.y = self.x.neg(5);
self.y += t;
self.y *= i;
h3 *= s1;
h3 = h3.neg(1);
self.y += h3;
}
pub fn add_zinv_var(&mut self, b: &Affine, bzinv: &Field) -> Jacobian {
let mut ret = Jacobian::default();
ret.add_zinv_var_in_place(&self, b, bzinv);
ret
}
pub fn clear(&mut self) {
self.infinity = false;
self.x.clear();
self.y.clear();
self.z.clear();
}
pub fn rescale(&mut self, s: &Field) {
debug_assert!(!s.is_zero());
let zz = s.sqr();
self.x *= &zz;
self.y *= &zz;
self.y *= s;
self.z *= s;
}
}
impl From<AffineStorage> for Affine {
fn from(a: AffineStorage) -> Affine {
Affine::new(a.x.into(), a.y.into())
}
}
impl Into<AffineStorage> for Affine {
fn into(mut self) -> AffineStorage {
debug_assert!(!self.is_infinity());
self.x.normalize();
self.y.normalize();
AffineStorage::new(self.x.into(), self.y.into())
}
}
impl AffineStorage {
pub const fn new(x: FieldStorage, y: FieldStorage) -> Self {
Self { x, y }
}
pub fn cmov(&mut self, a: &AffineStorage, flag: bool) {
self.x.cmov(&a.x, flag);
self.y.cmov(&a.y, flag);
}
}