Repository: ethereum/py_ecc

Issue:
secp256k1.py fails on Python 3.4
Error test:

```python
import binascii
import rlp
# sha3 from module `pysha3` not `ssh3`
import sha3
from py_ecc.secp256k1 import ecdsa_raw_recover

n = 0
p = 20000000000
g = 100000
v = 1000
Tn = ''
Tp = p.to_bytes((p.bit_length()//8) + 1,byteorder='big')
Tg = g.to_bytes((g.bit_length()//8) + 1,byteorder='big')
Tt = binascii.unhexlify("687422eEA2cB73B5d3e242bA5456b782919AFc85")
Tv = v.to_bytes((v.bit_length()//8) + 1,byteorder='big')
Td = binascii.unhexlify("c0de")
transaction = [Tn, Tp, Tg, Tt, Tv, Td]
rlp_data=rlp.encode(transaction)
unsigned_message=sha3.keccak_256(rlp_data).hexdigest()
v = 28
r = int("5897c2c7c7412b0a555fb6f053ddb6047c59666bbebc6f5573134e074992d841",16)
s = int("1c71d1c62b74caff8695a186e2a24dd701070ba9946748318135e3ac0950b1d4",16)
ecdsa_raw_recover(unsigned_message, (v, r, s))
```

Error message:

> Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/apalau/python3.4/lib64/python3.4/site-packages/py_ecc/secp256k1/secp256k1.py", line 132, in ecdsa_raw_recover
    z = bytes_to_int(msghash)
  File "/home/apalau/python3.4/lib64/python3.4/site-packages/py_ecc/secp256k1/secp256k1.py", line 21, in bytes_to_int
    o = (o << 8) + safe_ord(b)
TypeError: unsupported operand type(s) for +: 'int' and 'str'

On Python 2.7 the same `ecdsa_raw_recover(unsigned_message, (v, r, s))` works well.

Python version:

> python --version
> Python 3.4.5


Discussion:

Patch:
diff --git a/py_ecc/secp256k1/secp256k1.py b/py_ecc/secp256k1/secp256k1.py
index 68f1ca1..db93ee5 100644
--- a/py_ecc/secp256k1/secp256k1.py
+++ b/py_ecc/secp256k1/secp256k1.py
@@ -6,8 +6,11 @@ import sys
 if sys.version_info.major == 2:
     safe_ord = ord
 else:
-    def safe_ord(x):
-        return x
+    def safe_ord(value):
+        if isinstance(value, int):
+            return value
+        else:
+            return ord(value)
 
 
 # Elliptic curve parameters (secp256k1)


Test patch:
diff --git a/tests/test_secp256k1.py b/tests/test_secp256k1.py
index c7fbe23..a56bba1 100644
--- a/tests/test_secp256k1.py
+++ b/tests/test_secp256k1.py
@@ -12,3 +12,11 @@ def test_privtopub():
 def test_ecdsa_raw_sign():
     v, r, s = ecdsa_raw_sign(b'\x35' * 32, priv)
     assert ecdsa_raw_recover(b'\x35' * 32, (v, r, s)) == pub
+
+
+def test_issue_4_bug():
+    unsigned_message = '6a74f15f29c3227c5d1d2e27894da58d417a484ef53bc7aa57ee323b42ded656'
+    v = 28
+    r = int("5897c2c7c7412b0a555fb6f053ddb6047c59666bbebc6f5573134e074992d841", 16)
+    s = int("1c71d1c62b74caff8695a186e2a24dd701070ba9946748318135e3ac0950b1d4", 16)
+    ecdsa_raw_recover(unsigned_message, (v, r, s))