From 03d263fd407edccf063982465399dc51c78167cb Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Fri, 8 Feb 2019 10:40:02 +0800 Subject: [PATCH] Follow-up prior - remove sybils member and old sybil detection - make BLACKLIST_URL a coin default - tweak logging --- docs/environment.rst | 3 ++- electrumx/lib/coins.py | 2 ++ electrumx/server/env.py | 5 +---- electrumx/server/peers.py | 37 ++++++++++++------------------------- 4 files changed, 17 insertions(+), 30 deletions(-) diff --git a/docs/environment.rst b/docs/environment.rst index ff06b75..d7aa6ba 100644 --- a/docs/environment.rst +++ b/docs/environment.rst @@ -347,7 +347,8 @@ some of this. .. envvar:: BLACKLIST_URL - URL to retrieve a list of blacklisted peers. + URL to retrieve a list of blacklisted peers. If not set, a coin- + specific default is used. diff --git a/electrumx/lib/coins.py b/electrumx/lib/coins.py index c78336b..9d6da4f 100644 --- a/electrumx/lib/coins.py +++ b/electrumx/lib/coins.py @@ -84,6 +84,7 @@ class Coin(object): # Peer discovery PEER_DEFAULT_PORTS = {'t': '50001', 's': '50002'} PEERS = [] + BLACKLIST_URL = None @classmethod def lookup_coin_class(cls, name, net): @@ -422,6 +423,7 @@ class BitcoinSegwit(BitcoinMixin, Coin): TX_COUNT = 318337769 TX_COUNT_HEIGHT = 524213 TX_PER_BLOCK = 1400 + BLACKLIST_URL = 'https://electrum.org/blacklist.json' PEERS = [ 'btc.smsys.me s995', 'E-X.not.fyi s t', diff --git a/electrumx/server/env.py b/electrumx/server/env.py index 40b6f9f..b2fdc85 100644 --- a/electrumx/server/env.py +++ b/electrumx/server/env.py @@ -75,10 +75,7 @@ class Env(EnvBase): self.bandwidth_limit = self.integer('BANDWIDTH_LIMIT', 2000000) self.session_timeout = self.integer('SESSION_TIMEOUT', 600) self.drop_client = self.custom("DROP_CLIENT", None, re.compile) - self.blacklist_url = self.default('BLACKLIST_URL', None) - # temporary default - if self.blacklist_url is None and self.coin.NAME == 'BitcoinSegwit': - self.blacklist_url = 'https://electrum.org/blacklist.json' + self.blacklist_url = self.default('BLACKLIST_URL', self.coin.BLACKLIST_URL) # Identities clearnet_identity = self.clearnet_identity() diff --git a/electrumx/server/peers.py b/electrumx/server/peers.py index 8f6923a..3d4aced 100644 --- a/electrumx/server/peers.py +++ b/electrumx/server/peers.py @@ -79,7 +79,6 @@ class PeerManager(object): self.group = TaskGroup() # refreshed self.blacklist = set() - self.sybils = set() def _my_clearnet_peer(self): '''Returns the clearnet peer representing this server, if any.''' @@ -134,27 +133,19 @@ class PeerManager(object): for real_name in self.env.coin.PEERS) await self._note_peers(imported_peers, limit=None) - def _is_allowed(self, peer): - if peer.host in self.blacklist: - return False - if '*.' + '.'.join(peer.host.split('.')[-2:]) in self.blacklist: - return False - return True - async def _refresh_blacklist(self): - session = aiohttp.ClientSession() url = self.env.blacklist_url - if url is None: + if not url: return while True: + session = aiohttp.ClientSession() try: async with session.get(url) as response: r = await response.text() - self.blacklist = set(json.loads(r)) - self.logger.info('blacklist retrieved from "%s": %d' - % (url, len(self.blacklist))) + self.blacklist = set(json.loads(r)) + self.logger.info(f'blacklist from {url} has {len(self.blacklist)} entries') except Exception as e: - self.logger.info('could not retrieve blacklist, "%s"' % url) + self.logger.error(f'could not retrieve blacklist from {url}: {e}') await sleep(600) async def _detect_proxy(self): @@ -180,8 +171,7 @@ class PeerManager(object): self.logger.info('no proxy detected, will try later') await sleep(900) - async def _note_peers(self, peers, limit=2, check_ports=False, check_matches=False, - source=None): + async def _note_peers(self, peers, limit=2, check_ports=False, source=None): '''Add a limited number of peers that are not already present.''' new_peers = [] known = [] @@ -200,9 +190,6 @@ class PeerManager(object): else: new_peers.append(peer) - if check_matches and len(self.peers) >= 6 and len(known) <= len(self.peers) // 2: - return False - if new_peers: source = source or new_peers[0].source if limit: @@ -335,8 +322,7 @@ class PeerManager(object): # Process reported peers if remote peer is good peers = peers_task.result() - if await self._note_peers(peers, check_matches=not peer.is_tor): - self.sybils.add(peer.host) + await self._note_peers(peers) features = self._features_to_register(peer, peers) if features: @@ -506,11 +492,12 @@ class PeerManager(object): not peer.bad and peer.is_public] onion_peers = [] + def is_blacklisted(host): + return any(item in self.blacklist + for item in (host, '*.' + '.'.join(host.split('.')[-2:]))) + if not is_peer: - recent = filter(self._is_allowed, recent) - recent = [peer for peer in self.peers - if self._is_allowed(peer) - and peer.host in self.sybils] + recent = [peer for peer in recent if not is_blacklisted(peer.host)] # Always report ourselves if valid (even if not public) peers = set(myself for myself in self.myselves