commit ac749f3a19ec10ee6f826c88d670e6cebab9aa17
parent 34e3e48ba5942614a1d1c44f57f7e9a4da3d701f
Author: SomberNight <somber.night@protonmail.com>
Date: Tue, 14 Apr 2020 19:58:22 +0200
network: introduce NUM_STICKY_SERVERS
Diffstat:
1 file changed, 18 insertions(+), 10 deletions(-)
diff --git a/electrum/network.py b/electrum/network.py
@@ -72,6 +72,7 @@ _logger = get_logger(__name__)
NUM_TARGET_CONNECTED_SERVERS = 10
+NUM_STICKY_SERVERS = 4
NUM_RECENT_SERVERS = 20
MAX_RETRY_DELAY_FOR_SERVERS = 600 # sec
INIT_RETRY_DELAY_FOR_SERVERS = 15 # sec
@@ -551,20 +552,27 @@ class Network(Logger):
def _get_next_server_to_try(self) -> Optional[ServerAddr]:
now = time.time()
with self.interfaces_lock:
- exclude_set = set(self.interfaces) | self.connecting
- # first try from recent servers
+ connected_servers = set(self.interfaces) | self.connecting
+ # First try from recent servers. (which are persisted)
+ # As these are servers we successfully connected to recently, they are
+ # most likely to work. This also makes servers "sticky".
+ # Note: with sticky servers, it is more difficult for an attacker to eclipse the client,
+ # however if they succeed, the eclipsing would persist. To try to balance this,
+ # we only give priority to recent_servers up to NUM_STICKY_SERVERS.
with self.recent_servers_lock:
recent_servers = list(self._recent_servers)
recent_servers = [s for s in recent_servers if s.protocol == self.protocol]
- for server in recent_servers:
- if server in exclude_set:
- continue
- if not self._can_retry_server(server, now=now):
- continue
- return server
- # try all servers we know about
+ if len(connected_servers & set(recent_servers)) < NUM_STICKY_SERVERS:
+ for server in recent_servers:
+ if server in connected_servers:
+ continue
+ if not self._can_retry_server(server, now=now):
+ continue
+ return server
+ # try all servers we know about, pick one at random
hostmap = self.get_servers()
- servers = set(filter_protocol(hostmap, self.protocol)) - exclude_set
+ servers = list(set(filter_protocol(hostmap, self.protocol)) - connected_servers)
+ random.shuffle(servers)
for server in servers:
if not self._can_retry_server(server, now=now):
continue