Skip to content

Commit be5cb8c

Browse files
authored
Merge pull request #1576 from ethereum/py-ecc-upgrade
Upgrade py-ecc past a buggy release, to 1.4.6
2 parents 10d62b5 + 371cb17 commit be5cb8c

File tree

4 files changed

+41
-17
lines changed

4 files changed

+41
-17
lines changed

eth/precompiles/ecpairing.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
from eth.utils.bn128 import (
2323
validate_point,
24+
FQP_point_to_FQ2_point,
2425
)
2526
from eth.utils.padding import (
2627
pad32,
@@ -31,7 +32,7 @@
3132
)
3233

3334

34-
ZERO = (bn128.FQ2.one(), bn128.FQ2.one(), bn128.FQ2.zero())
35+
ZERO = bn128.Z2
3536
EXPONENT = bn128.FQ12.one()
3637

3738

@@ -74,7 +75,7 @@ def _ecpairing(data: bytes) -> bool:
7475

7576

7677
@curry
77-
def _process_point(data_buffer: bytes, exponent: int) -> int:
78+
def _process_point(data_buffer: bytes, exponent: int) -> bn128.FQP:
7879
x1, y1, x2_i, x2_r, y2_i, y2_r = _extract_point(data_buffer)
7980
p1 = validate_point(x1, y1)
8081

@@ -85,17 +86,16 @@ def _process_point(data_buffer: bytes, exponent: int) -> int:
8586
fq2_x = bn128.FQ2([x2_r, x2_i])
8687
fq2_y = bn128.FQ2([y2_r, y2_i])
8788

89+
p2 = ZERO
8890
if (fq2_x, fq2_y) != (bn128.FQ2.zero(), bn128.FQ2.zero()):
8991
p2 = (fq2_x, fq2_y, bn128.FQ2.one())
9092
if not bn128.is_on_curve(p2, bn128.b2):
9193
raise ValidationError("point is not on curve")
92-
else:
93-
p2 = ZERO
9494

9595
if bn128.multiply(p2, bn128.curve_order)[-1] != bn128.FQ2.zero():
9696
raise ValidationError("TODO: what case is this?????")
9797

98-
return exponent * bn128.pairing(p2, p1, final_exponentiate=False)
98+
return exponent * bn128.pairing(FQP_point_to_FQ2_point(p2), p1, final_exponentiate=False)
9999

100100

101101
def _extract_point(data_slice: bytes) -> Tuple[int, int, int, int, int, int]:

eth/utils/bls.py

+20-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Dict,
33
Iterable,
44
Tuple,
5+
Union,
56
)
67

78

@@ -16,6 +17,7 @@
1617
FQ,
1718
FQ2,
1819
FQ12,
20+
FQP,
1921
pairing,
2022
normalize,
2123
field_modulus,
@@ -26,6 +28,9 @@
2628
final_exponentiate
2729
)
2830
from eth.utils.blake import blake
31+
from eth.utils.bn128 import (
32+
FQP_point_to_FQ2_point,
33+
)
2934

3035

3136
CACHE = {} # type: Dict[bytes, Tuple[FQ2, FQ2, FQ2]]
@@ -38,7 +43,7 @@
3843
assert HEX_ROOT ** 16 == FQ2([1, 0])
3944

4045

41-
def compress_G1(pt: Tuple[FQ2, FQ2, FQ2]) -> int:
46+
def compress_G1(pt: Tuple[FQ, FQ, FQ]) -> int:
4247
x, y = normalize(pt)
4348
return x.n + 2**255 * (y.n % 2)
4449

@@ -55,11 +60,11 @@ def decompress_G1(p: int) -> Tuple[FQ, FQ, FQ]:
5560
return (FQ(x), FQ(y), FQ(1))
5661

5762

58-
def sqrt_fq2(x: FQ2) -> FQ2:
63+
def sqrt_fq2(x: FQP) -> FQ2:
5964
y = x ** ((field_modulus ** 2 + 15) // 32)
6065
while y**2 != x:
6166
y *= HEX_ROOT
62-
return y
67+
return FQ2(y.coeffs)
6368

6469

6570
def hash_to_G2(m: bytes) -> Tuple[FQ2, FQ2, FQ2]:
@@ -79,18 +84,22 @@ def hash_to_G2(m: bytes) -> Tuple[FQ2, FQ2, FQ2]:
7984
if xcb ** ((field_modulus ** 2 - 1) // 2) == FQ2([1, 0]):
8085
break
8186
y = sqrt_fq2(xcb)
82-
o = multiply((x, y, FQ2([1, 0])), 2 * field_modulus - curve_order)
87+
88+
o = FQP_point_to_FQ2_point(multiply((x, y, FQ2([1, 0])), 2 * field_modulus - curve_order))
8389
CACHE[m] = o
8490
return o
8591

8692

87-
def compress_G2(pt: Tuple[FQ2, FQ2, FQ2]) -> Tuple[int, int]:
93+
def compress_G2(pt: Tuple[FQP, FQP, FQP]) -> Tuple[int, int]:
8894
assert is_on_curve(pt, b2)
8995
x, y = normalize(pt)
90-
return (x.coeffs[0] + 2**255 * (y.coeffs[0] % 2), x.coeffs[1])
96+
return (
97+
int(x.coeffs[0] + 2**255 * (y.coeffs[0] % 2)),
98+
int(x.coeffs[1])
99+
)
91100

92101

93-
def decompress_G2(p: bytes) -> Tuple[FQ2, FQ2, FQ2]:
102+
def decompress_G2(p: bytes) -> Tuple[FQP, FQP, FQP]:
94103
x1 = p[0] % 2**255
95104
y1_mod_2 = p[0] // 2**255
96105
x2 = p[1]
@@ -99,7 +108,7 @@ def decompress_G2(p: bytes) -> Tuple[FQ2, FQ2, FQ2]:
99108
return FQ2([1, 0]), FQ2([1, 0]), FQ2([0, 0])
100109
y = sqrt_fq2(x**3 + b2)
101110
if y.coeffs[0] % 2 != y1_mod_2:
102-
y = y * -1
111+
y = FQ2((y * -1).coeffs)
103112
assert is_on_curve((x, y, FQ2([1, 0])), b2)
104113
return x, y, FQ2([1, 0])
105114

@@ -114,16 +123,16 @@ def privtopub(k: int) -> int:
114123

115124
def verify(m: bytes, pub: int, sig: bytes) -> bool:
116125
final_exponentiation = final_exponentiate(
117-
pairing(decompress_G2(sig), G1, False) *
118-
pairing(hash_to_G2(m), neg(decompress_G1(pub)), False)
126+
pairing(FQP_point_to_FQ2_point(decompress_G2(sig)), G1, False) *
127+
pairing(FQP_point_to_FQ2_point(hash_to_G2(m)), neg(decompress_G1(pub)), False)
119128
)
120129
return final_exponentiation == FQ12.one()
121130

122131

123132
def aggregate_sigs(sigs: Iterable[bytes]) -> Tuple[int, int]:
124133
o = Z2
125134
for s in sigs:
126-
o = add(o, decompress_G2(s))
135+
o = FQP_point_to_FQ2_point(add(o, decompress_G2(s)))
127136
return compress_G2(o)
128137

129138

eth/utils/bn128.py

+15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from py_ecc import (
22
optimized_bn128 as bn128,
33
)
4+
from py_ecc.optimized_bn128 import (
5+
FQP,
6+
FQ2,
7+
)
48

59
from eth_utils import (
610
ValidationError,
@@ -25,3 +29,14 @@ def validate_point(x: int, y: int) -> Tuple[bn128.FQ, bn128.FQ, bn128.FQ]:
2529
p1 = (FQ(1), FQ(1), FQ(0))
2630

2731
return p1
32+
33+
34+
def FQP_point_to_FQ2_point(pt: Tuple[FQP, FQP, FQP]) -> Tuple[FQ2, FQ2, FQ2]:
35+
"""
36+
Transform FQP to FQ2 for type hinting.
37+
"""
38+
return (
39+
FQ2(pt[0].coeffs),
40+
FQ2(pt[1].coeffs),
41+
FQ2(pt[2].coeffs),
42+
)

setup.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"eth-utils>=1.3.0b0,<2.0.0",
1414
"lru-dict>=1.1.6",
1515
"mypy_extensions>=0.4.1,<1.0.0",
16-
"py-ecc==1.4.3",
16+
"py-ecc>=1.4.7,<2.0.0",
1717
"pyethash>=0.1.27,<1.0.0",
1818
"rlp>=1.0.3,<2.0.0",
1919
"trie>=1.3.5,<2.0.0",

0 commit comments

Comments
 (0)