Skip to content

Commit

Permalink
Merge 76b1656 into 603823d
Browse files Browse the repository at this point in the history
  • Loading branch information
ulope committed Feb 5, 2016
2 parents 603823d + 76b1656 commit 928730f
Show file tree
Hide file tree
Showing 12 changed files with 90 additions and 65 deletions.
31 changes: 23 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,34 @@
# Config file for automatic testing at travis-ci.org

language: python

python:
#- "3.4"
- "2.7"
#- "pypy"
#- "3.4"
- "pypy"
#- "pypy3"

# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
cache:
directories:
- $HOME/.cache/pip

install:
- pip install -r requirements.txt
- pip install coveralls
- |
if [ "$TRAVIS_PYTHON_VERSION" = "pypy" ]; then
export PYENV_ROOT="$HOME/.pyenv"
if [ -f "$PYENV_ROOT/bin/pyenv" ]; then
pushd "$PYENV_ROOT" && git pull && popd
else
rm -rf "$PYENV_ROOT" && git clone --depth 1 https://github.com/yyuu/pyenv.git "$PYENV_ROOT"
fi
export PYPY_VERSION="4.0.1"
"$PYENV_ROOT/bin/pyenv" install --skip-existing "pypy-$PYPY_VERSION"
virtualenv --python="$PYENV_ROOT/versions/pypy-$PYPY_VERSION/bin/python" "$HOME/virtualenvs/pypy-$PYPY_VERSION"
source "$HOME/virtualenvs/pypy-$PYPY_VERSION/bin/activate"
fi
- pip install -U pip
- pip uninstall -y py pytest
- pip install -r requirements.txt
- pip install coveralls

# command to run tests, e.g. python setup.py test
script:
- coverage run --source devp2p setup.py test

Expand Down
9 changes: 7 additions & 2 deletions devp2p/app_helper.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import random

from devp2p import peermanager
from devp2p.service import BaseService
from devp2p.discovery import NodeDiscovery
Expand Down Expand Up @@ -67,9 +69,12 @@ def serve_until_stopped(apps):
app.stop()


def run(app_class, service_class, num_nodes=3, seed=0, min_peers=2, max_peers=2):
def run(app_class, service_class, num_nodes=3, seed=0, min_peers=2, max_peers=2, random_port=False):
gevent.get_hub().SYSTEM_ERROR = BaseException
base_port = 29870
if random_port:
base_port = random.randint(10000, 60000)
else:
base_port = 29870

# get bootstrap node (node0) enode
bootstrap_node_privkey = mk_privkey('%d:udp:%d' % (seed, 0))
Expand Down
43 changes: 25 additions & 18 deletions devp2p/crypto.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,7 @@
sha3_256 = lambda x: keccak.new(digest_bits=256, data=x)
from hashlib import sha256
import struct
try:
if '__pypy__' in sys.builtin_module_names:
warnings.warn('c_secp256k1 not yet supported for pypy, fallback to bitcointools')
raise ImportError
from c_secp256k1 import ecdsa_sign_raw, ecdsa_recover_raw, ecdsa_verify_raw
except ImportError:
warnings.warn('could not import c_secp256k1, fallback to bitcointools')
from bitcoin import ecdsa_raw_sign as ecdsa_sign_raw
from bitcoin import ecdsa_raw_recover as ecdsa_recover_raw
from bitcoin import ecdsa_raw_verify as ecdsa_verify_raw
from secp256k1 import PrivateKey, PublicKey, ALL_FLAGS


hmac_sha256 = pyelliptic.hmac_sha256
Expand Down Expand Up @@ -242,25 +233,41 @@ def _decode_sig(sig):
def ecdsa_verify(pubkey, signature, message):
assert len(signature) == 65
assert len(pubkey) == 64
return ecdsa_verify_raw(message, _decode_sig(signature), pubkey)
pk = PublicKey('\04' + pubkey, raw=True)
return pk.ecdsa_verify(
message,
pk.ecdsa_recoverable_convert(
pk.ecdsa_recoverable_deserialize(
signature[:64],
ord(signature[64]))),
raw=True
)
verify = ecdsa_verify


def ecdsa_sign(msghash, privkey):
assert len(msghash) == 32
s = _encode_sig(*ecdsa_sign_raw(msghash, privkey))
return s
pk = PrivateKey(privkey, raw=True)
signature = pk.ecdsa_recoverable_serialize(
pk.ecdsa_sign_recoverable(
msghash, raw=True))
new = signature[0] + chr(signature[1])
return new

sign = ecdsa_sign


def ecdsa_recover(message, signature):
assert len(signature) == 65
pub = ecdsa_recover_raw(message, _decode_sig(signature))
assert pub, 'pubkey could not be recovered'
pub = bitcoin.encode_pubkey(pub, 'bin_electrum')
assert len(pub) == 64
return pub
pk = PublicKey(flags=ALL_FLAGS)
pk.public_key = pk.ecdsa_recover(
message,
pk.ecdsa_recoverable_deserialize(
signature[:64],
ord(signature[64])),
raw=True
)
return pk.serialize(compressed=False)[1:]
recover = ecdsa_recover


Expand Down
10 changes: 8 additions & 2 deletions devp2p/tests/test_full_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,14 @@ class TestDriver(object):

ExampleServiceIncCounter.testdriver = TestDriver()

app_helper.run(ExampleApp, ExampleServiceIncCounter,
num_nodes=num_nodes, min_peers=num_nodes-1, max_peers=num_nodes-1)
app_helper.run(
ExampleApp,
ExampleServiceIncCounter,
num_nodes=num_nodes,
min_peers=num_nodes-1,
max_peers=num_nodes-1,
random_port=True # Use a random port to avoid 'Address already in use' errors
)


@pytest.mark.timeout(10)
Expand Down
1 change: 1 addition & 0 deletions devp2p/tests/test_kademlia_protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ def test_eviction_timeout():
assert node not in proto.routing.bucket_by_node(node).replacement_cache


@pytest.mark.timeout(15)
def test_eviction_node_active():
"""
active nodes (replying in time) should not be evicted
Expand Down
6 changes: 3 additions & 3 deletions devp2p/tests/test_peer.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@


def get_connected_apps():
a_config = dict(p2p=dict(listen_host='127.0.0.1', listen_port=3000),
a_config = dict(p2p=dict(listen_host='127.0.0.1', listen_port=3005),
node=dict(privkey_hex=crypto.sha3('a').encode('hex')))
b_config = copy.deepcopy(a_config)
b_config['p2p']['listen_port'] = 3001
b_config['p2p']['listen_port'] = 3006
b_config['node']['privkey_hex'] = crypto.sha3('b').encode('hex')

a_app = BaseApp(a_config)
Expand Down Expand Up @@ -110,7 +110,7 @@ def mock_receive_hello(self, proto, version, client_version_string,


def connect_go():
a_config = dict(p2p=dict(listen_host='127.0.0.1', listen_port=3000),
a_config = dict(p2p=dict(listen_host='127.0.0.1', listen_port=3010),
node=dict(privkey_hex=crypto.sha3('a').encode('hex')))

a_app = BaseApp(a_config)
Expand Down
2 changes: 1 addition & 1 deletion devp2p/tests/test_peermanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def try_tcp_connect(addr):


def test_app_restart():
host, port = '127.0.0.1', 3000
host, port = '127.0.0.1', 3020

a_config = dict(p2p=dict(listen_host=host, listen_port=port),
node=dict(privkey_hex=crypto.sha3('a').encode('hex')))
Expand Down
9 changes: 6 additions & 3 deletions devp2p/tests/test_slogging.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@ def setUp(self):
def tearDown(self):
self.log.removeHandler(self.handler)

def expect_log(self, msg):
def expect_log(self, msg, *parts):
self.handler.flush()
# FIXME: slogging adds unnecessary space in the end in some cases.
# Workaround with rstrip().
self.assertEqual(self.stream.getvalue().rstrip(), msg.rstrip())
log_messages = self.stream.getvalue().rstrip()
self.assertTrue(log_messages.startswith(msg.rstrip()))
for part in parts:
self.assertIn(part, log_messages)


class LoggingPatchTest(LoggingTest):
Expand Down Expand Up @@ -52,4 +55,4 @@ def test_slogging(self):
def test_slogging_kwargs(self):
"""Test patched kwargs support"""
self.log.info("Test kwargs:", number=1, f=2.3, comment='works!')
self.expect_log("Test kwargs: comment=works! number=1 f=2.3\n")
self.expect_log("Test kwargs:", "comment=works!", "number=1", "f=2.3")
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
pyelliptic
wheel
gevent==1.1b3
gevent==1.1rc3
tinyrpc
bitcoin
ipaddress
coverage
tox
c_secp256k1>=0.0.7
git+https://github.com/ulope/secp256k1-py#egg=secp256k1
pycryptodome>=3.3.1
rlp==0.4.4
2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ search = version = "{current_version}"
[wheel]
universal = 1

[aliases]
test = pytest
34 changes: 10 additions & 24 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,20 @@
except ImportError:
from distutils.core import setup

from setuptools.command.test import test as TestCommand


class PyTest(TestCommand):

# problem w/ test_kademlia_protocol.py
# user_options = [('timeout=', '5', "timeout tests after 5 seconds")]

def finalize_options(self):
TestCommand.finalize_options(self)
self.test_args = []
self.test_suite = True

def run_tests(self):
# import here, cause outside the eggs aren't loaded
import pytest
errno = pytest.main(self.test_args)
raise SystemExit(errno)


readme = open('README.rst').read()
history = open('HISTORY.rst').read().replace('.. :changelog:', '')

install_requires = set(x.strip() for x in open('requirements.txt'))
install_requires_replacements = {}
install_requires_replacements = {
'git+https://github.com/ulope/secp256k1-py#egg=secp256k1': 'secp256k1'
}
install_requires = [install_requires_replacements.get(r, r) for r in install_requires]

test_requirements = [
'pytest',
'pytest-catchlog==1.1',
'pytest-timeout==0.5'
'pytest==2.8.7',
'pytest-catchlog==1.2.2',
'pytest-timeout==1.0'
]

# *IMPORTANT*: Don't manually change the version here. Use the 'bumpversion' utility.
Expand All @@ -56,6 +39,9 @@ def run_tests(self):
package_dir={'devp2p': 'devp2p'},
include_package_data=True,
install_requires=install_requires,
dependency_links=[
"https://github.com/ulope/secp256k1-py/archive/master.zip#egg=secp256k1-0.11.1"
],
license="MIT",
zip_safe=False,
keywords='devp2p',
Expand All @@ -70,6 +56,6 @@ def run_tests(self):
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
],
cmdclass={'test': PyTest},
setup_requires=['pytest-runner>2.0,<3'],
tests_require=test_requirements
)
4 changes: 2 additions & 2 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
[tox]
envlist = py27
envlist = py27,pypy

[testenv]
setenv =
PYTHONPATH = {toxinidir}:{toxinidir}/pydevp2p
commands = python setup.py test
commands = python setup.py test --addopts "{posargs:devp2p/tests}"
deps =
-r{toxinidir}/requirements.txt

0 comments on commit 928730f

Please sign in to comment.