arnaucube
arnaucube/plonky2-ecdsaPublic Self-hosted repository
plonky2-ecdsa/src/curve/curve_adds.rs
src/curve/curve_adds.rsRaw
  1use core::ops::Add;
  2
  3use plonky2::field::ops::Square;
  4use plonky2::field::types::Field;
  5
  6use crate::curve::curve_types::{AffinePoint, Curve, ProjectivePoint};
  7
  8impl<C: Curve> Add<ProjectivePoint<C>> for ProjectivePoint<C> {
  9    type Output = ProjectivePoint<C>;
 10
 11    fn add(self, rhs: ProjectivePoint<C>) -> Self::Output {
 12        let ProjectivePoint {
 13            x: x1,
 14            y: y1,
 15            z: z1,
 16        } = self;
 17        let ProjectivePoint {
 18            x: x2,
 19            y: y2,
 20            z: z2,
 21        } = rhs;
 22
 23        if z1 == C::BaseField::ZERO {
 24            return rhs;
 25        }
 26        if z2 == C::BaseField::ZERO {
 27            return self;
 28        }
 29
 30        let x1z2 = x1 * z2;
 31        let y1z2 = y1 * z2;
 32        let x2z1 = x2 * z1;
 33        let y2z1 = y2 * z1;
 34
 35        // Check if we're doubling or adding inverses.
 36        if x1z2 == x2z1 {
 37            if y1z2 == y2z1 {
 38                // TODO: inline to avoid redundant muls.
 39                return self.double();
 40            }
 41            if y1z2 == -y2z1 {
 42                return ProjectivePoint::ZERO;
 43            }
 44        }
 45
 46        // From https://www.hyperelliptic.org/EFD/g1p/data/shortw/projective/addition/add-1998-cmo-2
 47        let z1z2 = z1 * z2;
 48        let u = y2z1 - y1z2;
 49        let uu = u.square();
 50        let v = x2z1 - x1z2;
 51        let vv = v.square();
 52        let vvv = v * vv;
 53        let r = vv * x1z2;
 54        let a = uu * z1z2 - vvv - r.double();
 55        let x3 = v * a;
 56        let y3 = u * (r - a) - vvv * y1z2;
 57        let z3 = vvv * z1z2;
 58        ProjectivePoint::nonzero(x3, y3, z3)
 59    }
 60}
 61
 62impl<C: Curve> Add<AffinePoint<C>> for ProjectivePoint<C> {
 63    type Output = ProjectivePoint<C>;
 64
 65    fn add(self, rhs: AffinePoint<C>) -> Self::Output {
 66        let ProjectivePoint {
 67            x: x1,
 68            y: y1,
 69            z: z1,
 70        } = self;
 71        let AffinePoint {
 72            x: x2,
 73            y: y2,
 74            zero: zero2,
 75        } = rhs;
 76
 77        if z1 == C::BaseField::ZERO {
 78            return rhs.to_projective();
 79        }
 80        if zero2 {
 81            return self;
 82        }
 83
 84        let x2z1 = x2 * z1;
 85        let y2z1 = y2 * z1;
 86
 87        // Check if we're doubling or adding inverses.
 88        if x1 == x2z1 {
 89            if y1 == y2z1 {
 90                // TODO: inline to avoid redundant muls.
 91                return self.double();
 92            }
 93            if y1 == -y2z1 {
 94                return ProjectivePoint::ZERO;
 95            }
 96        }
 97
 98        // From https://www.hyperelliptic.org/EFD/g1p/data/shortw/projective/addition/madd-1998-cmo
 99        let u = y2z1 - y1;
100        let uu = u.square();
101        let v = x2z1 - x1;
102        let vv = v.square();
103        let vvv = v * vv;
104        let r = vv * x1;
105        let a = uu * z1 - vvv - r.double();
106        let x3 = v * a;
107        let y3 = u * (r - a) - vvv * y1;
108        let z3 = vvv * z1;
109        ProjectivePoint::nonzero(x3, y3, z3)
110    }
111}
112
113impl<C: Curve> Add<AffinePoint<C>> for AffinePoint<C> {
114    type Output = ProjectivePoint<C>;
115
116    fn add(self, rhs: AffinePoint<C>) -> Self::Output {
117        let AffinePoint {
118            x: x1,
119            y: y1,
120            zero: zero1,
121        } = self;
122        let AffinePoint {
123            x: x2,
124            y: y2,
125            zero: zero2,
126        } = rhs;
127
128        if zero1 {
129            return rhs.to_projective();
130        }
131        if zero2 {
132            return self.to_projective();
133        }
134
135        // Check if we're doubling or adding inverses.
136        if x1 == x2 {
137            if y1 == y2 {
138                return self.to_projective().double();
139            }
140            if y1 == -y2 {
141                return ProjectivePoint::ZERO;
142            }
143        }
144
145        // From https://www.hyperelliptic.org/EFD/g1p/data/shortw/projective/addition/mmadd-1998-cmo
146        let u = y2 - y1;
147        let uu = u.square();
148        let v = x2 - x1;
149        let vv = v.square();
150        let vvv = v * vv;
151        let r = vv * x1;
152        let a = uu - vvv - r.double();
153        let x3 = v * a;
154        let y3 = u * (r - a) - vvv * y1;
155        let z3 = vvv;
156        ProjectivePoint::nonzero(x3, y3, z3)
157    }
158}