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}