mirror of https://github.com/zcash/pasta.git
Updates for Pallas/Vesta.
Use `sage amicable.sage --sequential --requireisos --sortpq --ignoretwist --nearpowerof2 255 32` to generate the Pallas/Vesta cycle. Signed-off-by: Daira Hopwood <daira@jacaranda.org>
This commit is contained in:
parent
491beffc2c
commit
a35294b64f
|
@ -4,8 +4,8 @@
|
||||||
import sys
|
import sys
|
||||||
from multiprocessing import Pool, cpu_count
|
from multiprocessing import Pool, cpu_count
|
||||||
from traceback import print_exc
|
from traceback import print_exc
|
||||||
from math import ceil
|
|
||||||
from itertools import combinations
|
from itertools import combinations
|
||||||
|
from string import maketrans
|
||||||
|
|
||||||
if sys.version_info[0] == 2: range = xrange
|
if sys.version_info[0] == 2: range = xrange
|
||||||
|
|
||||||
|
@ -22,8 +22,9 @@ COEFFICIENT_RANGE = (5,)
|
||||||
|
|
||||||
GCD_PRIMES = (5, 7, 11, 13, 17)
|
GCD_PRIMES = (5, 7, 11, 13, 17)
|
||||||
|
|
||||||
ISOGENY_DEGREE_PRIMES = 40
|
# Set to a prime, or 0 to disable searching for isogenies.
|
||||||
ISOGENY_DEGREE_MAX = list(primes(ISOGENY_DEGREE_PRIMES))[-1]
|
ISOGENY_DEGREE_MAX = 3
|
||||||
|
#ISOGENY_DEGREE_MAX = 37
|
||||||
|
|
||||||
DEFAULT_TWIST_SECURITY = 120
|
DEFAULT_TWIST_SECURITY = 120
|
||||||
REQUIRE_PRIMITIVE = True
|
REQUIRE_PRIMITIVE = True
|
||||||
|
@ -100,7 +101,9 @@ def symmetric_range(n, base=0, step=1):
|
||||||
yield -i
|
yield -i
|
||||||
yield i+1
|
yield i+1
|
||||||
|
|
||||||
def find_nice_curves(strategy, L, twoadicity, stretch, isogenies, twistsec, wid, processes):
|
SWAP_SIGNS = maketrans("+-", "-+")
|
||||||
|
|
||||||
|
def find_nice_curves(strategy, L, twoadicity, stretch, requireisos, sortpq, twistsec, wid, processes):
|
||||||
for (p, T, V) in strategy(L, max(0, twoadicity-stretch), wid, processes):
|
for (p, T, V) in strategy(L, max(0, twoadicity-stretch), wid, processes):
|
||||||
if p % (1<<twoadicity) != 1:
|
if p % (1<<twoadicity) != 1:
|
||||||
continue
|
continue
|
||||||
|
@ -114,6 +117,10 @@ def find_nice_curves(strategy, L, twoadicity, stretch, isogenies, twistsec, wid,
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if q not in (p, p+1, p-1) and q > 1<<(L-1) and q % 6 == 1 and q % (1<<twoadicity) == 1 and is_prime(q) and is_prime(p):
|
if q not in (p, p+1, p-1) and q > 1<<(L-1) and q % 6 == 1 and q % (1<<twoadicity) == 1 and is_prime(q) and is_prime(p):
|
||||||
|
if sortpq and q < p:
|
||||||
|
(p, q) = (q, p)
|
||||||
|
qdesc = qdesc.translate(SWAP_SIGNS)
|
||||||
|
|
||||||
(Ep, bp) = find_curve(p, q)
|
(Ep, bp) = find_curve(p, q)
|
||||||
if bp == None: continue
|
if bp == None: continue
|
||||||
(Eq, bq) = find_curve(q, p, (bp,))
|
(Eq, bq) = find_curve(q, p, (bp,))
|
||||||
|
@ -155,11 +162,13 @@ def find_nice_curves(strategy, L, twoadicity, stretch, isogenies, twistsec, wid,
|
||||||
twembeddivp = (2*p + 1 - q)/twembedp
|
twembeddivp = (2*p + 1 - q)/twembedp
|
||||||
twembeddivq = (2*q + 1 - p)/twembedq
|
twembeddivq = (2*q + 1 - p)/twembedq
|
||||||
|
|
||||||
iso_Ep = find_iso(Ep) if isogenies else None
|
iso_Ep = find_iso(Ep)
|
||||||
iso_Eq = find_iso(Eq) if isogenies else None
|
iso_Eq = find_iso(Eq)
|
||||||
|
if requireisos and (iso_Ep is None or iso_Eq is None):
|
||||||
|
continue
|
||||||
|
|
||||||
yield (p, q, bp, bq, zetap, zetaq, qdesc, primp, primq, secp, secq, twsecp, twsecq,
|
yield (p, q, bp, bq, zetap, zetaq, qdesc, primp, primq, secp, secq, twsecp, twsecq,
|
||||||
embeddivp, embeddivq, twembeddivp, twembeddivq, iso_Ep, iso_Eq, isogenies)
|
embeddivp, embeddivq, twembeddivp, twembeddivq, iso_Ep, iso_Eq)
|
||||||
|
|
||||||
def endo(E, zeta, P):
|
def endo(E, zeta, P):
|
||||||
(xp, yp) = P.xy()
|
(xp, yp) = P.xy()
|
||||||
|
@ -204,7 +213,7 @@ def embedding_degree(p, r):
|
||||||
def find_iso(E):
|
def find_iso(E):
|
||||||
# Based on <https://eprint.iacr.org/2019/403.pdf> Appendix A.
|
# Based on <https://eprint.iacr.org/2019/403.pdf> Appendix A.
|
||||||
# Look for isogenous curves having j-invariant not in {0, 1728}.
|
# Look for isogenous curves having j-invariant not in {0, 1728}.
|
||||||
for degree in primes(ISOGENY_DEGREE_PRIMES):
|
for degree in primes(ISOGENY_DEGREE_MAX+1):
|
||||||
sys.stdout.write('~')
|
sys.stdout.write('~')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
for iso in E.isogenies_prime_degree(degree):
|
for iso in E.isogenies_prime_degree(degree):
|
||||||
|
@ -232,17 +241,19 @@ def main():
|
||||||
processes = 1 if "--sequential" in args else cpu_count()
|
processes = 1 if "--sequential" in args else cpu_count()
|
||||||
if processes >= 6:
|
if processes >= 6:
|
||||||
processes -= 2
|
processes -= 2
|
||||||
isogenies = "--isogenies" in args
|
requireisos = "--requireisos" in args
|
||||||
|
sortpq = "--sortpq" in args
|
||||||
twistsec = 0 if "--ignoretwist" in args else DEFAULT_TWIST_SECURITY
|
twistsec = 0 if "--ignoretwist" in args else DEFAULT_TWIST_SECURITY
|
||||||
args = [arg for arg in args if not arg.startswith("--")]
|
args = [arg for arg in args if not arg.startswith("--")]
|
||||||
|
|
||||||
if len(args) < 1:
|
if len(args) < 1:
|
||||||
print("""
|
print("""
|
||||||
Usage: sage amicable.sage [--sequential] [--isogenies] [--nearpowerof2] <min-bitlength> [<min-2adicity> [<stretch]]
|
Usage: sage amicable.sage [--sequential] [--requireisos] [--sortpq] [--ignoretwist] [--nearpowerof2] <min-bitlength> [<min-2adicity> [<stretch]]
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
--sequential Use only one thread, avoiding non-determinism in the output order.
|
--sequential Use only one thread, avoiding non-determinism in the output order.
|
||||||
--isogenies Search for and print isogenies useful for a "simplified SWU" hash to curve.
|
--requireisos Require isogenies useful for a "simplified SWU" hash to curve.
|
||||||
|
--sortpq Sort p smaller than q.
|
||||||
--ignoretwist Ignore twist security.
|
--ignoretwist Ignore twist security.
|
||||||
--nearpowerof2 Search for primes near a power of 2, rather than with low Hamming weight.
|
--nearpowerof2 Search for primes near a power of 2, rather than with low Hamming weight.
|
||||||
<min-bitlength> Both primes should have this minimum bit length.
|
<min-bitlength> Both primes should have this minimum bit length.
|
||||||
|
@ -260,7 +271,7 @@ Arguments:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for wid in range(processes):
|
for wid in range(processes):
|
||||||
pool.apply_async(worker, (strategy, L, twoadicity, stretch, isogenies, twistsec, wid, processes))
|
pool.apply_async(worker, (strategy, L, twoadicity, stretch, requireisos, sortpq, twistsec, wid, processes))
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
sleep(1000)
|
sleep(1000)
|
||||||
|
@ -279,7 +290,7 @@ def worker(*args):
|
||||||
|
|
||||||
def real_worker(*args):
|
def real_worker(*args):
|
||||||
for (p, q, bp, bq, zetap, zetaq, qdesc, primp, primq, secp, secq, twsecp, twsecq,
|
for (p, q, bp, bq, zetap, zetaq, qdesc, primp, primq, secp, secq, twsecp, twsecq,
|
||||||
embeddivp, embeddivq, twembeddivp, twembeddivq, iso_Ep, iso_Eq, isogenies) in find_nice_curves(*args):
|
embeddivp, embeddivq, twembeddivp, twembeddivq, iso_Ep, iso_Eq) in find_nice_curves(*args):
|
||||||
output = "\n"
|
output = "\n"
|
||||||
output += "p = %s\n" % format_weight(p)
|
output += "p = %s\n" % format_weight(p)
|
||||||
output += "q = %s\n" % format_weight(q)
|
output += "q = %s\n" % format_weight(q)
|
||||||
|
@ -305,13 +316,13 @@ def real_worker(*args):
|
||||||
if iso_Ep is not None:
|
if iso_Ep is not None:
|
||||||
output += "iso_Ep = %r\n" % (iso_Ep,)
|
output += "iso_Ep = %r\n" % (iso_Ep,)
|
||||||
output += "iso_Ep maps = %r\n" % (iso_Ep.rational_maps(),)
|
output += "iso_Ep maps = %r\n" % (iso_Ep.rational_maps(),)
|
||||||
elif isogenies:
|
elif ISOGENY_DEGREE_MAX > 0:
|
||||||
output += "No Ep isogenies for simplified SWU with degree ≤ %d\n" % (ISOGENY_DEGREE_MAX,)
|
output += "No Ep isogenies for simplified SWU with degree ≤ %d\n" % (ISOGENY_DEGREE_MAX,)
|
||||||
|
|
||||||
if iso_Eq is not None:
|
if iso_Eq is not None:
|
||||||
output += "iso_Eq = %r\n" % (iso_Eq,)
|
output += "iso_Eq = %r\n" % (iso_Eq,)
|
||||||
output += "iso_Eq maps = %r\n" % (iso_Eq.rational_maps(),)
|
output += "iso_Eq maps = %r\n" % (iso_Eq.rational_maps(),)
|
||||||
elif isogenies:
|
elif ISOGENY_DEGREE_MAX > 0:
|
||||||
output += "No Eq isogenies for simplified SWU with degree ≤ %d\n" % (ISOGENY_DEGREE_MAX,)
|
output += "No Eq isogenies for simplified SWU with degree ≤ %d\n" % (ISOGENY_DEGREE_MAX,)
|
||||||
|
|
||||||
print(output) # one syscall to minimize tearing
|
print(output) # one syscall to minimize tearing
|
||||||
|
|
Loading…
Reference in New Issue