Skip to content

Commit

Permalink
flake8, pytest, and ci
Browse files Browse the repository at this point in the history
  • Loading branch information
pipermerriam committed Nov 14, 2017
1 parent 3906885 commit 48e7620
Show file tree
Hide file tree
Showing 18 changed files with 625 additions and 110 deletions.
28 changes: 28 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
language: python
dist: trusty
env:
global:
- PYTEST_ADDOPTS="-n 3"
matrix:
include:
# lint
- python: "3.5"
env: TOX_ENV=flake8
# core
- python: "2.7"
env: TOX_ENV=py27
- python: "3.4"
env: TOX_ENV=py34
- python: "3.5"
env: TOX_ENV=py35
- python: "3.6"
env: TOX_ENV=py35
cache:
pip: true
install:
- "travis_retry pip install pip setuptools --upgrade"
- "travis_retry pip install tox"
script:
- tox -e $TOX_ENV
after_script:
- cat .tox/$TOX_ENV/log/*.log
8 changes: 5 additions & 3 deletions py_ecc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from . import secp256k1
from . import bn128
from . import optimized_bn128
from __future__ import absolute_import

from . import secp256k1 # noqa: F401
from . import bn128 # noqa: F401
from . import optimized_bn128 # noqa: F401
33 changes: 30 additions & 3 deletions py_ecc/bn128/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,30 @@
from .bn128_field_elements import field_modulus, FQ, FQP, FQ2, FQ12
from .bn128_curve import add, double, multiply, is_inf, is_on_curve, eq, neg, twist, b, b2, b12, curve_order, G1, G2, G12
from .bn128_pairing import pairing, final_exponentiate
from __future__ import absolute_import

from .bn128_field_elements import ( # noqa: F401
field_modulus,
FQ,
FQP,
FQ2,
FQ12,
)
from .bn128_curve import ( # noqa: F401
add,
double,
multiply,
is_inf,
is_on_curve,
eq,
neg,
twist,
b,
b2,
b12,
curve_order,
G1,
G2,
G12,
)
from .bn128_pairing import ( # noqa: F401
pairing,
final_exponentiate,
)
49 changes: 38 additions & 11 deletions py_ecc/bn128/bn128_curve.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
from .bn128_field_elements import field_modulus, FQ, FQ2, FQ12
from __future__ import absolute_import

from .bn128_field_elements import (
field_modulus,
FQ,
FQ2,
FQ12,
)


curve_order = 21888242871839275222246405745257275088548364400416034343698204186575808495617

Expand All @@ -17,31 +25,44 @@
# Generator for curve over FQ
G1 = (FQ(1), FQ(2))
# Generator for twisted curve over FQ2
G2 = (FQ2([10857046999023057135944570762232829481370756359578518086990519993285655852781, 11559732032986387107991004021392285783925812861821192530917403151452391805634]),
FQ2([8495653923123431417604973247489272438418190587263600148770280649306958101930, 4082367875863433681332203403145435568316851327593401208105741076214120093531]))
G2 = (
FQ2([
10857046999023057135944570762232829481370756359578518086990519993285655852781,
11559732032986387107991004021392285783925812861821192530917403151452391805634,
]),
FQ2([
8495653923123431417604973247489272438418190587263600148770280649306958101930,
4082367875863433681332203403145435568316851327593401208105741076214120093531,
]),
)


# Check if a point is the point at infinity
def is_inf(pt):
return pt is None


# Check that a point is on the curve defined by y**2 == x**3 + b
def is_on_curve(pt, b):
if is_inf(pt):
return True
x, y = pt
return y**2 - x**3 == b


assert is_on_curve(G1, b)
assert is_on_curve(G2, b2)


# Elliptic curve doubling
def double(pt):
x, y = pt
l = 3 * x**2 / (2 * y)
newx = l**2 - 2 * x
newy = -l * newx + l * x - y
v = 3 * x**2 / (2 * y)
newx = v**2 - 2 * x
newy = -v * newx + v * x - y
return newx, newy


# Elliptic curve addition
def add(p1, p2):
if p1 is None or p2 is None:
Expand All @@ -53,12 +74,13 @@ def add(p1, p2):
elif x2 == x1:
return None
else:
l = (y2 - y1) / (x2 - x1)
newx = l**2 - x1 - x2
newy = -l * newx + l * x1 - y1
assert newy == (-l * newx + l * x2 - y2)
v = (y2 - y1) / (x2 - x1)
newx = v**2 - x1 - x2
newy = -v * newx + v * x1 - y1
assert newy == (-v * newx + v * x2 - y2)
return (newx, newy)


# Elliptic curve point multiplication
def multiply(pt, n):
if n == 0:
Expand All @@ -70,19 +92,23 @@ def multiply(pt, n):
else:
return add(multiply(double(pt), int(n // 2)), pt)


def eq(p1, p2):
return p1 == p2


# "Twist" a point in E(FQ2) into a point in E(FQ12)
w = FQ12([0, 1] + [0] * 10)


# Convert P => -P
def neg(pt):
if pt is None:
return None
x, y = pt
return (x, -y)


def twist(pt):
if pt is None:
return None
Expand All @@ -95,7 +121,8 @@ def twist(pt):
nx = FQ12([xcoeffs[0]] + [0] * 5 + [xcoeffs[1]] + [0] * 5)
ny = FQ12([ycoeffs[0]] + [0] * 5 + [ycoeffs[1]] + [0] * 5)
# Divide x coord by w**2 and y coord by w**3
return (nx * w **2, ny * w**3)
return (nx * w ** 2, ny * w**3)


G12 = twist(G2)
# Check that the twist creates a point that is on the curve
Expand Down
60 changes: 39 additions & 21 deletions py_ecc/bn128/bn128_field_elements.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,26 @@
from __future__ import absolute_import

import sys


sys.setrecursionlimit(10000)


# python3 compatibility
try:
foo = long
except:
long = int
if sys.version_info.major == 2:
int_types = (int, long) # noqa: F821
else:
int_types = (int,)


# The prime modulus of the field
field_modulus = 21888242871839275222246405745257275088696311157297823662689037894645226208583
# See, it's prime!
assert pow(2, field_modulus, field_modulus) == 2

# The modulus of the polynomial in this representation of FQ12
FQ12_modulus_coeffs = [82, 0, 0, 0, 0, 0, -18, 0, 0, 0, 0, 0] # Implied + [1]
FQ12_modulus_coeffs = [82, 0, 0, 0, 0, 0, -18, 0, 0, 0, 0, 0] # Implied + [1]


# Extended euclidean algorithm to find modular inverses for
# integers
Expand All @@ -23,20 +30,21 @@ def inv(a, n):
lm, hm = 1, 0
low, high = a % n, n
while low > 1:
r = high//low
nm, new = hm-lm*r, high-low*r
r = high // low
nm, new = hm - lm * r, high - low * r
lm, low, hm, high = nm, new, lm, low
return lm % n


# A class for field elements in FQ. Wrap a number in this class,
# and it becomes a field element.
class FQ():
class FQ(object):
def __init__(self, n):
if isinstance(n, self.__class__):
self.n = n.n
else:
self.n = n % field_modulus
assert isinstance(self.n, (int, long))
assert isinstance(self.n, int_types)

def __add__(self, other):
on = other.n if isinstance(other, FQ) else other
Expand All @@ -62,15 +70,15 @@ def __sub__(self, other):

def __div__(self, other):
on = other.n if isinstance(other, FQ) else other
assert isinstance(on, (int, long))
assert isinstance(on, int_types)
return FQ(self.n * inv(on, field_modulus) % field_modulus)

def __truediv__(self, other):
return self.__div__(other)

def __rdiv__(self, other):
on = other.n if isinstance(other, FQ) else other
assert isinstance(on, (int, long)), on
assert isinstance(on, int_types), on
return FQ(inv(self.n, field_modulus) * on % field_modulus)

def __rtruediv__(self, other):
Expand Down Expand Up @@ -109,13 +117,15 @@ def one(cls):
def zero(cls):
return cls(0)


# Utility methods for polynomial math
def deg(p):
d = len(p) - 1
while p[d] == 0 and d:
d -= 1
return d


def poly_rounded_div(a, b):
dega = deg(a)
degb = deg(b)
Expand All @@ -125,11 +135,15 @@ def poly_rounded_div(a, b):
o[i] += temp[degb + i] / b[degb]
for c in range(degb + 1):
temp[c + i] -= o[c]
return o[:deg(o)+1]
return o[:deg(o) + 1]


int_types_or_FQ = (FQ,) + int_types


# A class for elements in polynomial extension fields
class FQP():
def __init__(self, coeffs, modulus_coeffs):
class FQP(object):
def __init__(self, coeffs, modulus_coeffs):
assert len(coeffs) == len(modulus_coeffs)
self.coeffs = [FQ(c) for c in coeffs]
# The coefficients of the modulus, without the leading [1]
Expand All @@ -139,14 +153,14 @@ def __init__(self, coeffs, modulus_coeffs):

def __add__(self, other):
assert isinstance(other, self.__class__)
return self.__class__([x+y for x,y in zip(self.coeffs, other.coeffs)])
return self.__class__([x + y for x, y in zip(self.coeffs, other.coeffs)])

def __sub__(self, other):
assert isinstance(other, self.__class__)
return self.__class__([x-y for x,y in zip(self.coeffs, other.coeffs)])
return self.__class__([x - y for x, y in zip(self.coeffs, other.coeffs)])

def __mul__(self, other):
if isinstance(other, (FQ, int, long)):
if isinstance(other, int_types_or_FQ):
return self.__class__([c * other for c in self.coeffs])
else:
assert isinstance(other, self.__class__)
Expand All @@ -164,7 +178,7 @@ def __rmul__(self, other):
return self * other

def __div__(self, other):
if isinstance(other, (FQ, int, long)):
if isinstance(other, int_types_or_FQ):
return self.__class__([c / other for c in self.coeffs])
else:
assert isinstance(other, self.__class__)
Expand Down Expand Up @@ -192,11 +206,13 @@ def inv(self):
r += [0] * (self.degree + 1 - len(r))
nm = [x for x in hm]
new = [x for x in high]
assert len(lm) == len(hm) == len(low) == len(high) == len(nm) == len(new) == self.degree + 1
assert len(set(
[len(lm), len(hm), len(low), len(high), len(nm), len(new), self.degree + 1]
)) == 1
for i in range(self.degree + 1):
for j in range(self.degree + 1 - i):
nm[i+j] -= lm[i] * r[j]
new[i+j] -= low[i] * r[j]
nm[i + j] -= lm[i] * r[j]
new[i + j] -= low[i] * r[j]
lm, low, hm, high = nm, new, lm, low
return self.__class__(lm[:self.degree]) / low[0]

Expand Down Expand Up @@ -224,6 +240,7 @@ def one(cls):
def zero(cls):
return cls([0] * cls.degree)


# The quadratic extension field
class FQ2(FQP):
def __init__(self, coeffs):
Expand All @@ -232,6 +249,7 @@ def __init__(self, coeffs):
self.degree = 2
self.__class__.degree = 2


# The 12th-degree extension field
class FQ12(FQP):
def __init__(self, coeffs):
Expand Down
Loading

0 comments on commit 48e7620

Please sign in to comment.