Browse Source

Prepare 1.7.1

patch-2
Neil Booth 7 years ago
parent
commit
0b4f6b3d6d
  1. 13
      docs/changelog.rst
  2. 2
      docs/conf.py
  3. 2
      electrumx/__init__.py
  4. 86
      electrumx/server/peers.py
  5. 4
      setup.py

13
docs/changelog.rst

@ -7,6 +7,18 @@
and memory consumption whilst serving clients. Those problems and memory consumption whilst serving clients. Those problems
should not occur with Python 3.7. should not occur with Python 3.7.
Version 1.7.1 (28 Jul 2018)
============================
* switch to aiorpcX 0.5.8 which implements some curio task management
primitives on top of asyncio that make writing correct async code
much easier, as well as making it simpler to reason about
* use those primitives to restructure the peer manager, which is now
fully concurrent again, as well as the block processor and
controller
* fix `#534`_ introduced in 1.7
* minor coin tweaks (ghost43, cipig)
Version 1.7 (25 Jul 2018) Version 1.7 (25 Jul 2018)
========================== ==========================
@ -160,3 +172,4 @@ bitcoincash:qzxpdlt8ehu9ehftw6rqsy2jgfq4nsltxvhrdmdfpn
.. _#506: https://github.com/kyuupichan/electrumx/issues/506 .. _#506: https://github.com/kyuupichan/electrumx/issues/506
.. _#519: https://github.com/kyuupichan/electrumx/issues/519 .. _#519: https://github.com/kyuupichan/electrumx/issues/519
.. _#523: https://github.com/kyuupichan/electrumx/issues/523 .. _#523: https://github.com/kyuupichan/electrumx/issues/523
.. _#534: https://github.com/kyuupichan/electrumx/issues/534

2
docs/conf.py

@ -15,7 +15,7 @@
import os import os
import sys import sys
sys.path.insert(0, os.path.abspath('..')) sys.path.insert(0, os.path.abspath('..'))
VERSION="ElectrumX 1.7" VERSION="ElectrumX 1.7.1"
# -- Project information ----------------------------------------------------- # -- Project information -----------------------------------------------------

2
electrumx/__init__.py

@ -1,4 +1,4 @@
version = 'ElectrumX 1.7' version = 'ElectrumX 1.7.1'
version_short = version.split()[-1] version_short = version.split()[-1]
from electrumx.server.controller import Controller from electrumx.server.controller import Controller

86
electrumx/server/peers.py

@ -185,8 +185,8 @@ class PeerManager(object):
async def _monitor_peer(self, peer): async def _monitor_peer(self, peer):
# Stop monitoring if we were dropped (a duplicate peer) # Stop monitoring if we were dropped (a duplicate peer)
while peer in self.peers: while peer in self.peers:
is_good = await self._is_peer_good(peer) if await self._should_drop_peer(peer):
if self._should_drop_peer(peer, is_good): self.peers.discard(peer)
break break
# Figure out how long to sleep before retrying. Retry a # Figure out how long to sleep before retrying. Retry a
# good connection when it is about to turn stale, otherwise # good connection when it is about to turn stale, otherwise
@ -198,47 +198,9 @@ class PeerManager(object):
async with ignore_after(pause): async with ignore_after(pause):
await peer.retry_event.wait() await peer.retry_event.wait()
async def _should_drop_peer(self, peer, is_good): async def _should_drop_peer(self, peer):
now = time.time()
if self.env.force_proxy or peer.is_tor:
how = f'via {kind} over Tor'
else:
how = f'via {kind} at {peer.ip_addr}'
status = 'verified' if good else 'failed to verify'
elapsed = now - peer.last_try
self.logger.info(f'{status} {peer} {how} in {elapsed:.1f}s')
if good:
peer.try_count = 0
peer.last_good = now
peer.source = 'peer'
# At most 2 matches if we're a host name, potentially
# several if we're an IP address (several instances
# can share a NAT).
matches = peer.matches(self.peers)
for match in matches:
if match.ip_address:
if len(matches) > 1:
self.peers.remove(match)
# Force the peer's monitoring task to exit
match.retry_event.set()
elif peer.host in match.features['hosts']:
match.update_features_from_peer(peer)
else:
# Forget the peer if long-term unreachable
if peer.last_good and not peer.bad:
try_limit = 10
else:
try_limit = 3
if peer.try_count >= try_limit:
desc = 'bad' if peer.bad else 'unreachable'
self.logger.info(f'forgetting {desc} peer: {peer}')
self.peers.discard(peer)
return True
return False
async def _is_peer_good(self, peer):
peer.try_count += 1 peer.try_count += 1
is_good = False
for kind, port in peer.connection_port_pairs(): for kind, port in peer.connection_port_pairs():
peer.last_try = time.time() peer.last_try = time.time()
@ -263,7 +225,8 @@ class PeerManager(object):
try: try:
async with PeerSession(peer.host, port, **kwargs) as session: async with PeerSession(peer.host, port, **kwargs) as session:
await self._verify_peer(session, peer) await self._verify_peer(session, peer)
return True is_good = True
break
except BadPeerError as e: except BadPeerError as e:
self.logger.error(f'[{peer}] marking bad: ({e})') self.logger.error(f'[{peer}] marking bad: ({e})')
peer.mark_bad() peer.mark_bad()
@ -277,6 +240,43 @@ class PeerManager(object):
self.logger.info(f'[{peer}] {kind} connection to ' self.logger.info(f'[{peer}] {kind} connection to '
f'port {port} failed: {e}') f'port {port} failed: {e}')
now = time.time()
if self.env.force_proxy or peer.is_tor:
how = f'via {kind} over Tor'
else:
how = f'via {kind} at {peer.ip_addr}'
status = 'verified' if is_good else 'failed to verify'
elapsed = now - peer.last_try
self.logger.info(f'{status} {peer} {how} in {elapsed:.1f}s')
if is_good:
peer.try_count = 0
peer.last_good = now
peer.source = 'peer'
# At most 2 matches if we're a host name, potentially
# several if we're an IP address (several instances
# can share a NAT).
matches = peer.matches(self.peers)
for match in matches:
if match.ip_address:
if len(matches) > 1:
self.peers.remove(match)
# Force the peer's monitoring task to exit
match.retry_event.set()
elif peer.host in match.features['hosts']:
match.update_features_from_peer(peer)
else:
# Forget the peer if long-term unreachable
if peer.last_good and not peer.bad:
try_limit = 10
else:
try_limit = 3
if peer.try_count >= try_limit:
desc = 'bad' if peer.bad else 'unreachable'
self.logger.info(f'forgetting {desc} peer: {peer}')
return True
return False
async def _verify_peer(self, session, peer): async def _verify_peer(self, session, peer):
if not peer.is_tor: if not peer.is_tor:
address = session.peer_address() address = session.peer_address()

4
setup.py

@ -1,5 +1,5 @@
import setuptools import setuptools
version = '1.7' version = '1.7.1'
setuptools.setup( setuptools.setup(
name='electrumX', name='electrumX',
@ -11,7 +11,7 @@ setuptools.setup(
# "tribus_hash" package is required to sync Denarius network. # "tribus_hash" package is required to sync Denarius network.
# "blake256" package is required to sync Decred network. # "blake256" package is required to sync Decred network.
# "xevan_hash" package is required to sync Xuez network. # "xevan_hash" package is required to sync Xuez network.
install_requires=['aiorpcX == 0.5.6', 'attrs>=15', install_requires=['aiorpcX == 0.5.8', 'attrs>=15',
'plyvel', 'pylru', 'aiohttp >= 2'], 'plyvel', 'pylru', 'aiohttp >= 2'],
packages=setuptools.find_packages(include=('electrumx*',)), packages=setuptools.find_packages(include=('electrumx*',)),
description='ElectrumX Server', description='ElectrumX Server',

Loading…
Cancel
Save