@@ -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
0 commit comments