From e0fd64d29af1d99bb7e09dba7b8b05391861d5ad Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Wed, 22 Mar 2017 07:57:15 +0900 Subject: [PATCH] Rate-limit add_peer calls randomly Prepare 1.0.1 --- README.rst | 10 ++++++++++ server/controller.py | 11 +++++++++++ server/session.py | 6 ++---- server/version.py | 2 +- 4 files changed, 24 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index 10b97d1..3a71dd0 100644 --- a/README.rst +++ b/README.rst @@ -127,6 +127,16 @@ Roadmap ChangeLog ========= +Version 1.0.1 +------------- + +* Rate-limit add_peer calls in a random way +* Fix discovery of base height in reorgs +* Don't permit common but invalid REPORT_HOST values +* Set reorg limit to 8000 blocks on testnet +* dogecoin / litecoin parameter fixes (erasmospunk, pooler) +* minor doc tweaks + Version 1.0 ----------- diff --git a/server/controller.py b/server/controller.py index c0cbf6b..a8d4d43 100644 --- a/server/controller.py +++ b/server/controller.py @@ -9,6 +9,7 @@ import asyncio import json import os import ssl +import random import time import traceback import warnings @@ -47,6 +48,7 @@ class Controller(util.LoggedClass): self.executor = ThreadPoolExecutor() self.loop.set_default_executor(self.executor) self.start_time = time.time() + self.next_add_peer_time = self.start_time self.coin = env.coin self.daemon = Daemon(env.coin.daemon_urls(env.daemon_url)) self.bp = BlockProcessor(env, self, self.daemon) @@ -133,6 +135,15 @@ class Controller(util.LoggedClass): def is_deprioritized(self, session): return self.session_priority(session) > self.BANDS + def permit_add_peer(self): + '''To prevent lots of add_peer requests filling up the peer + table, accept only one per random time interval.''' + now = time.time() + if now < self.next_add_peer_time: + return False + self.next_add_peer_time = now + random.randrange(0, 1800) + return True + async def run_in_executor(self, func, *args): '''Wait whilst running func in the executor.''' return await self.loop.run_in_executor(None, func, *args) diff --git a/server/session.py b/server/session.py index ee0466f..6ae9d66 100644 --- a/server/session.py +++ b/server/session.py @@ -45,7 +45,6 @@ class SessionBase(JSONSession): self.bw_time = self.start_time self.bw_interval = 3600 self.bw_used = 0 - self.peer_added = False def close_connection(self): '''Call this to close the connection.''' @@ -196,13 +195,12 @@ class ElectrumX(SessionBase): def add_peer(self, features): '''Add a peer.''' - if self.peer_added: + if not self.controller.permit_add_peer(): return False peer_mgr = self.controller.peer_mgr peer_info = self.peer_info() source = peer_info[0] if peer_info else 'unknown' - self.peer_added = peer_mgr.on_add_peer(features, source) - return self.peer_added + return peer_mgr.on_add_peer(features, source) def peers_subscribe(self): '''Return the server peers as a list of (ip, host, details) tuples.''' diff --git a/server/version.py b/server/version.py index 334e721..e9146f2 100644 --- a/server/version.py +++ b/server/version.py @@ -1,5 +1,5 @@ # Server name and protocol versions -VERSION = 'ElectrumX 1.0' +VERSION = 'ElectrumX 1.0.1' PROTOCOL_MIN = '1.0' PROTOCOL_MAX = '1.0'