Skip to content

Commit

Permalink
[SECP256K1] Convert Sage code to Python 3 (as used by Sage >= 9)
Browse files Browse the repository at this point in the history
Summary: Backport of [[bitcoin-core/secp256k1#849 | secp256k1#849]]

Test Plan:
Run from the sage dir
  sage group_prover.sage
  sage weierstrass_prover.sage

Reviewers: #bitcoin_abc, PiRK

Reviewed By: #bitcoin_abc, PiRK

Differential Revision: https://reviews.bitcoinabc.org/D9374
  • Loading branch information
fchapoton authored and Fabcien committed Apr 8, 2021
1 parent e250d10 commit 70b41f3
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 24 deletions.
21 changes: 13 additions & 8 deletions sage/group_prover.sage
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class fastfrac:
return self.top in I and self.bot not in I

def reduce(self,assumeZero):
zero = self.R.ideal(map(numerator, assumeZero))
zero = self.R.ideal(list(map(numerator, assumeZero)))
return fastfrac(self.R, zero.reduce(self.top)) / fastfrac(self.R, zero.reduce(self.bot))

def __add__(self,other):
Expand Down Expand Up @@ -100,14 +100,19 @@ class fastfrac:
"""Multiply something else with a fraction."""
return self.__mul__(other)

def __div__(self,other):
def __truediv__(self,other):
"""Divide two fractions."""
if parent(other) == ZZ:
return fastfrac(self.R,self.top,self.bot * other)
if other.__class__ == fastfrac:
return fastfrac(self.R,self.top * other.bot,self.bot * other.top)
return NotImplemented

# Compatibility wrapper for Sage versions based on Python 2
def __div__(self,other):
"""Divide two fractions."""
return self.__truediv__(other)

def __pow__(self,other):
"""Compute a power of a fraction."""
if parent(other) == ZZ:
Expand Down Expand Up @@ -175,7 +180,7 @@ class constraints:

def conflicts(R, con):
"""Check whether any of the passed non-zero assumptions is implied by the zero assumptions"""
zero = R.ideal(map(numerator, con.zero))
zero = R.ideal(list(map(numerator, con.zero)))
if 1 in zero:
return True
# First a cheap check whether any of the individual nonzero terms conflict on
Expand All @@ -195,7 +200,7 @@ def conflicts(R, con):

def get_nonzero_set(R, assume):
"""Calculate a simple set of nonzero expressions"""
zero = R.ideal(map(numerator, assume.zero))
zero = R.ideal(list(map(numerator, assume.zero)))
nonzero = set()
for nz in map(numerator, assume.nonzero):
for (f,n) in nz.factor():
Expand All @@ -208,7 +213,7 @@ def get_nonzero_set(R, assume):

def prove_nonzero(R, exprs, assume):
"""Check whether an expression is provably nonzero, given assumptions"""
zero = R.ideal(map(numerator, assume.zero))
zero = R.ideal(list(map(numerator, assume.zero)))
nonzero = get_nonzero_set(R, assume)
expl = set()
ok = True
Expand Down Expand Up @@ -250,7 +255,7 @@ def prove_zero(R, exprs, assume):
r, e = prove_nonzero(R, dict(map(lambda x: (fastfrac(R, x.bot, 1), exprs[x]), exprs)), assume)
if not r:
return (False, map(lambda x: "Possibly zero denominator: %s" % x, e))
zero = R.ideal(map(numerator, assume.zero))
zero = R.ideal(list(map(numerator, assume.zero)))
nonzero = prod(x for x in assume.nonzero)
expl = []
for expr in exprs:
Expand All @@ -265,8 +270,8 @@ def describe_extra(R, assume, assumeExtra):
"""Describe what assumptions are added, given existing assumptions"""
zerox = assume.zero.copy()
zerox.update(assumeExtra.zero)
zero = R.ideal(map(numerator, assume.zero))
zeroextra = R.ideal(map(numerator, zerox))
zero = R.ideal(list(map(numerator, assume.zero)))
zeroextra = R.ideal(list(map(numerator, zerox)))
nonzero = get_nonzero_set(R, assume)
ret = set()
# Iterate over the extra zero expressions
Expand Down
32 changes: 16 additions & 16 deletions sage/weierstrass_prover.sage
Original file line number Diff line number Diff line change
Expand Up @@ -175,24 +175,24 @@ laws_jacobian_weierstrass = {
def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p):
"""Verify an implementation of addition of Jacobian points on a Weierstrass curve, by executing and validating the result for every possible addition in a prime field"""
F = Integers(p)
print "Formula %s on Z%i:" % (name, p)
print("Formula %s on Z%i:" % (name, p))
points = []
for x in xrange(0, p):
for y in xrange(0, p):
for x in range(0, p):
for y in range(0, p):
point = affinepoint(F(x), F(y))
r, e = concrete_verify(on_weierstrass_curve(A, B, point))
if r:
points.append(point)

for za in xrange(1, p):
for zb in xrange(1, p):
for za in range(1, p):
for zb in range(1, p):
for pa in points:
for pb in points:
for ia in xrange(2):
for ib in xrange(2):
for ia in range(2):
for ib in range(2):
pA = jacobianpoint(pa.x * F(za)^2, pa.y * F(za)^3, F(za), ia)
pB = jacobianpoint(pb.x * F(zb)^2, pb.y * F(zb)^3, F(zb), ib)
for branch in xrange(0, branches):
for branch in range(0, branches):
assumeAssert, assumeBranch, pC = formula(branch, pA, pB)
pC.X = F(pC.X)
pC.Y = F(pC.Y)
Expand All @@ -206,13 +206,13 @@ def check_exhaustive_jacobian_weierstrass(name, A, B, branches, formula, p):
r, e = concrete_verify(assumeLaw)
if r:
if match:
print " multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity)
print(" multiple branches for (%s,%s,%s,%s) + (%s,%s,%s,%s)" % (pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity))
else:
match = True
r, e = concrete_verify(require)
if not r:
print " failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e)
print
print(" failure in branch %i for (%s,%s,%s,%s) + (%s,%s,%s,%s) = (%s,%s,%s,%s): %s" % (branch, pA.X, pA.Y, pA.Z, pA.Infinity, pB.X, pB.Y, pB.Z, pB.Infinity, pC.X, pC.Y, pC.Z, pC.Infinity, e))
print()


def check_symbolic_function(R, assumeAssert, assumeBranch, f, A, B, pa, pb, pA, pB, pC):
Expand Down Expand Up @@ -242,9 +242,9 @@ def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula):
for key in laws_jacobian_weierstrass:
res[key] = []

print ("Formula " + name + ":")
print("Formula " + name + ":")
count = 0
for branch in xrange(branches):
for branch in range(branches):
assumeFormula, assumeBranch, pC = formula(branch, pA, pB)
pC.X = lift(pC.X)
pC.Y = lift(pC.Y)
Expand All @@ -255,10 +255,10 @@ def check_symbolic_jacobian_weierstrass(name, A, B, branches, formula):
res[key].append((check_symbolic_function(R, assumeFormula, assumeBranch, laws_jacobian_weierstrass[key], A, B, pa, pb, pA, pB, pC), branch))

for key in res:
print " %s:" % key
print(" %s:" % key)
val = res[key]
for x in val:
if x[0] is not None:
print " branch %i: %s" % (x[1], x[0])
print(" branch %i: %s" % (x[1], x[0]))

print
print()

0 comments on commit 70b41f3

Please sign in to comment.