@@ -164,36 +164,37 @@ library P256 {
164
164
}
165
165
166
166
/**
167
- * @dev Point addition on the jacobian coordinates
167
+ * @dev Point addition on the jacobian coordinates.
168
+ *
169
+ * Computation is assisted by Solidity's memory. It takes x1 and y1 arguments from the scratch space
170
+ * and returns x' and y' to the scratch space.
171
+ *
168
172
* Reference: https://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#addition-add-1998-cmo-2
169
173
*/
170
- function _jAdd (
171
- uint256 x1 ,
172
- uint256 y1 ,
173
- uint256 z1 ,
174
- uint256 x2 ,
175
- uint256 y2 ,
176
- uint256 z2
177
- ) private pure returns (uint256 rx , uint256 ry , uint256 rz ) {
174
+ function _jAddMemoryAssisted (uint256 z1 , uint256 x2 , uint256 y2 , uint256 z2 ) private pure returns (uint256 rz ) {
178
175
assembly ("memory-safe" ) {
179
176
let p := P
177
+
180
178
let zz1 := mulmod (z1, z1, p) // zz1 = z1²
181
179
let zz2 := mulmod (z2, z2, p) // zz2 = z2²
182
- let u1 := mulmod (x1 , zz2, p) // u1 = x1*z2²
180
+ let u1 := mulmod (mload ( 0x00 ) , zz2, p) // u1 = x1*z2²
183
181
let u2 := mulmod (x2, zz1, p) // u2 = x2*z1²
184
- let s1 := mulmod (y1 , mulmod (zz2, z2, p), p) // s1 = y1*z2³
182
+ let s1 := mulmod (mload ( 0x20 ) , mulmod (zz2, z2, p), p) // s1 = y1*z2³
185
183
let s2 := mulmod (y2, mulmod (zz1, z1, p), p) // s2 = y2*z1³
186
184
let h := addmod (u2, sub (p, u1), p) // h = u2-u1
185
+ rz := mulmod (h, mulmod (z1, z2, p), p)
187
186
let hh := mulmod (h, h, p) // h²
188
187
let hhh := mulmod (h, hh, p) // h³
189
188
let r := addmod (s2, sub (p, s1), p) // r = s2-s1
190
189
191
190
// x' = r²-h³-2*u1*h²
192
- rx := addmod (addmod (mulmod (r, r, p), sub (p, hhh), p), sub (p, mulmod (2 , mulmod (u1, hh, p), p)), p)
191
+ mstore (0x00 , addmod (addmod (mulmod (r, r, p), sub (p, hhh), p), sub (p, mulmod (2 , mulmod (u1, hh, p), p)), p))
192
+
193
193
// y' = r*(u1*h²-x')-s1*h³
194
- ry := addmod (mulmod (r, addmod (mulmod (u1, hh, p), sub (p, rx), p), p), sub (p, mulmod (s1, hhh, p)), p)
195
- // z' = h*z1*z2
196
- rz := mulmod (h, mulmod (z1, z2, p), p)
194
+ mstore (
195
+ 0x20 ,
196
+ addmod (mulmod (r, addmod (mulmod (u1, hh, p), sub (p, mload (0 )), p), p), sub (p, mulmod (s1, hhh, p)), p)
197
+ )
197
198
}
198
199
}
199
200
@@ -244,7 +245,9 @@ library P256 {
244
245
if (z == 0 ) {
245
246
(x, y, z) = (points[pos].x, points[pos].y, points[pos].z);
246
247
} else {
247
- (x, y, z) = _jAdd (x, y, z, points[pos].x, points[pos].y, points[pos].z);
248
+ _toScratchMemory (x, y);
249
+ (z) = _jAddMemoryAssisted (z, points[pos].x, points[pos].y, points[pos].z);
250
+ (x, y) = _fromScratchMemory ();
248
251
}
249
252
}
250
253
u1 <<= 2 ;
@@ -287,12 +290,27 @@ library P256 {
287
290
}
288
291
289
292
function _jAddPoint (JPoint memory p1 , JPoint memory p2 ) private pure returns (JPoint memory ) {
290
- (uint256 x , uint256 y , uint256 z ) = _jAdd (p1.x, p1.y, p1.z, p2.x, p2.y, p2.z);
293
+ _toScratchMemory (p1.x, p1.y);
294
+ uint256 z = _jAddMemoryAssisted (p1.z, p2.x, p2.y, p2.z);
295
+ (uint256 x , uint256 y ) = _fromScratchMemory ();
291
296
return JPoint (x, y, z);
292
297
}
293
298
294
299
function _jDoublePoint (JPoint memory p ) private pure returns (JPoint memory ) {
295
300
(uint256 x , uint256 y , uint256 z ) = _jDouble (p.x, p.y, p.z);
296
301
return JPoint (x, y, z);
297
302
}
303
+
304
+ function _toScratchMemory (uint256 x , uint256 y ) private pure {
305
+ assembly ("memory-safe" ) {
306
+ mstore (0x00 , x)
307
+ mstore (0x20 , y)
308
+ }
309
+ }
310
+ function _fromScratchMemory () private pure returns (uint256 x , uint256 y ) {
311
+ assembly ("memory-safe" ) {
312
+ x := mload (0x00 )
313
+ y := mload (0x20 )
314
+ }
315
+ }
298
316
}
0 commit comments