@@ -1272,7 +1272,7 @@ class PointEdwards(AbstractPoint):
1272
1272
x*y = T / Z
1273
1273
"""
1274
1274
1275
- def __init__ (self , curve , x , y , z , t , order = None ):
1275
+ def __init__ (self , curve , x , y , z , t , order = None , generator = False ):
1276
1276
"""
1277
1277
Initialise a point that uses the extended coordinates interanlly.
1278
1278
"""
@@ -1284,6 +1284,8 @@ def __init__(self, curve, x, y, z, t, order=None):
1284
1284
else : # pragma: no branch
1285
1285
self .__coords = (x , y , z , t )
1286
1286
self .__order = order
1287
+ self .__generator = generator
1288
+ self .__precompute = []
1287
1289
1288
1290
@classmethod
1289
1291
def from_bytes (
@@ -1311,8 +1313,9 @@ def from_bytes(
1311
1313
supported
1312
1314
:param int order: the point order, must be non zero when using
1313
1315
generator=True
1314
- :param bool generator: Ignored, may be used in the future
1315
- to precompute point multiplication table.
1316
+ :param bool generator: Flag to mark the point as a curve generator,
1317
+ this will cause the library to pre-compute some values to
1318
+ make repeated usages of the point much faster
1316
1319
1317
1320
:raises MalformedPointError: if the public point does not lay on the
1318
1321
curve or the encoding is invalid
@@ -1324,8 +1327,41 @@ def from_bytes(
1324
1327
curve , data , validate_encoding , valid_encodings
1325
1328
)
1326
1329
return PointEdwards (
1327
- curve , coord_x , coord_y , 1 , coord_x * coord_y , order
1330
+ curve , coord_x , coord_y , 1 , coord_x * coord_y , order , generator
1331
+ )
1332
+
1333
+ def _maybe_precompute (self ):
1334
+ if not self .__generator or self .__precompute :
1335
+ return
1336
+
1337
+ # since this code will execute just once, and it's fully deterministic,
1338
+ # depend on atomicity of the last assignment to switch from empty
1339
+ # self.__precompute to filled one and just ignore the unlikely
1340
+ # situation when two threads execute it at the same time (as it won't
1341
+ # lead to inconsistent __precompute)
1342
+ order = self .__order
1343
+ assert order
1344
+ precompute = []
1345
+ i = 1
1346
+ order *= 2
1347
+ coord_x , coord_y , coord_z , coord_t = self .__coords
1348
+ prime = self .__curve .p ()
1349
+ doubler = PointEdwards (
1350
+ self .__curve , coord_x , coord_y , coord_z , coord_t , order
1328
1351
)
1352
+ order *= 2
1353
+ coord_x , coord_y = doubler .x (), doubler .y ()
1354
+ coord_t = coord_x * coord_y % prime
1355
+ precompute .append ((coord_x , coord_y , coord_t ))
1356
+
1357
+ while i < order :
1358
+ i *= 2
1359
+ doubler = doubler .double ().scale ()
1360
+ coord_x , coord_y = doubler .x (), doubler .y ()
1361
+ coord_t = coord_x * coord_y % prime
1362
+ precompute .append ((coord_x , coord_y , coord_t ))
1363
+
1364
+ self .__precompute = precompute
1329
1365
1330
1366
def x (self ):
1331
1367
"""Return affine x coordinate."""
@@ -1482,6 +1518,28 @@ def __rmul__(self, other):
1482
1518
"""Multiply point by an integer."""
1483
1519
return self * other
1484
1520
1521
+ def _mul_precompute (self , other ):
1522
+ """Multiply point by integer with precomputation table."""
1523
+ X3 , Y3 , Z3 , T3 , p , a = 0 , 1 , 1 , 0 , self .__curve .p (), self .__curve .a ()
1524
+ _add = self ._add
1525
+ for X2 , Y2 , T2 in self .__precompute :
1526
+ if other % 2 :
1527
+ if other % 4 >= 2 :
1528
+ other = (other + 1 ) // 2
1529
+ X3 , Y3 , Z3 , T3 = _add (
1530
+ X3 , Y3 , Z3 , T3 , - X2 , Y2 , 1 , - T2 , p , a
1531
+ )
1532
+ else :
1533
+ other = (other - 1 ) // 2
1534
+ X3 , Y3 , Z3 , T3 = _add (X3 , Y3 , Z3 , T3 , X2 , Y2 , 1 , T2 , p , a )
1535
+ else :
1536
+ other //= 2
1537
+
1538
+ if not X3 or not T3 :
1539
+ return INFINITY
1540
+
1541
+ return PointEdwards (self .__curve , X3 , Y3 , Z3 , T3 , self .__order )
1542
+
1485
1543
def __mul__ (self , other ):
1486
1544
"""Multiply point by an integer."""
1487
1545
X2 , Y2 , Z2 , T2 = self .__coords
@@ -1492,6 +1550,9 @@ def __mul__(self, other):
1492
1550
if self .__order :
1493
1551
# order*2 as a protection for Minerva
1494
1552
other = other % (self .__order * 2 )
1553
+ self ._maybe_precompute ()
1554
+ if self .__precompute :
1555
+ return self ._mul_precompute (other )
1495
1556
1496
1557
X3 , Y3 , Z3 , T3 = 0 , 1 , 1 , 0 # INFINITY in extended coordinates
1497
1558
p , a = self .__curve .p (), self .__curve .a ()
0 commit comments