Skip to content

Commit 73f3d3e

Browse files
authored
add code to lazily precompute multiplication tables (#212)
add code to lazily precompute multiplication tables
1 parent f27b20f commit 73f3d3e

File tree

3 files changed

+39
-12
lines changed

3 files changed

+39
-12
lines changed

Diff for: .gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,5 @@ t/
4949
# Backup files
5050
*.swp
5151
*~
52+
.idea
53+
.cache

Diff for: src/ecdsa/ellipticcurve.py

+36-11
Original file line numberDiff line numberDiff line change
@@ -174,20 +174,42 @@ def __init__(self, curve, x, y, z, order=None, generator=False):
174174
self.__y = y
175175
self.__z = z
176176
self.__order = order
177+
self.__generator = generator
177178
self.__precompute = []
178-
if generator:
179-
assert order
180-
i = 1
181-
order *= 2
182-
doubler = PointJacobi(curve, x, y, z, order)
183-
order *= 2
184-
self.__precompute.append((doubler.x(), doubler.y()))
185-
186-
while i < order:
187-
i *= 2
188-
doubler = doubler.double().scale()
179+
180+
def _maybe_precompute(self):
181+
if self.__generator:
182+
# since we lack promotion of read-locks to write-locks, we do a
183+
# "acquire-read-lock check, acquire-write-lock plus recheck" cycle
184+
try:
185+
self._scale_lock.reader_acquire()
186+
if self.__precompute:
187+
return
188+
finally:
189+
self._scale_lock.reader_release()
190+
191+
try:
192+
self._scale_lock.writer_acquire()
193+
if self.__precompute:
194+
return
195+
order = self.__order
196+
assert order
197+
i = 1
198+
order *= 2
199+
doubler = PointJacobi(
200+
self.__curve, self.__x, self.__y, self.__z, order
201+
)
202+
order *= 2
189203
self.__precompute.append((doubler.x(), doubler.y()))
190204

205+
while i < order:
206+
i *= 2
207+
doubler = doubler.double().scale()
208+
self.__precompute.append((doubler.x(), doubler.y()))
209+
210+
finally:
211+
self._scale_lock.writer_release()
212+
191213
def __getstate__(self):
192214
try:
193215
self._scale_lock.reader_acquire()
@@ -574,6 +596,7 @@ def __mul__(self, other):
574596
if self.__order:
575597
# order*2 as a protection for Minerva
576598
other = other % (self.__order * 2)
599+
self._maybe_precompute()
577600
if self.__precompute:
578601
return self._mul_precompute(other)
579602

@@ -621,6 +644,8 @@ def mul_add(self, self_mul, other, other_mul):
621644
other = PointJacobi.from_affine(other)
622645
# when the points have precomputed answers, then multiplying them alone
623646
# is faster (as it uses NAF)
647+
self._maybe_precompute()
648+
other._maybe_precompute()
624649
if self.__precompute and other.__precompute:
625650
return self * self_mul + other * other_mul
626651

Diff for: tox.ini

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

22
[tox]
3-
envlist = py26, py27, py33, py34, py35, py36, py37, py38, py, pypy, pypy3, gmpy2py27, gmpy2py38, gmpypy27, gmpypy38
3+
envlist = py26, py27, py33, py34, py35, py36, py37, py38, py, pypy, pypy3, gmpy2py27, gmpy2py38, gmpypy27, gmpypy38, codechecks
44

55
[testenv]
66
deps =

0 commit comments

Comments
 (0)