From c790fd567c5eddc13f8543641ea31268c5b7bfd2 Mon Sep 17 00:00:00 2001 From: Neil Booth Date: Tue, 17 Jul 2018 09:04:19 +0800 Subject: [PATCH] Move things from Controller to session class which better belong there: - PROTOCOL_MIN, PROTOCOL_MAX - server_features() - server_version_args() - inline protocol_tuple() --- electrumx/server/controller.py | 34 +++------------------------------- electrumx/server/peers.py | 7 ++++--- electrumx/server/session.py | 33 +++++++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 38 deletions(-) diff --git a/electrumx/server/controller.py b/electrumx/server/controller.py index 5327724..4bf3509 100644 --- a/electrumx/server/controller.py +++ b/electrumx/server/controller.py @@ -51,21 +51,21 @@ class Controller(ServerBase): ''' CATCHING_UP, LISTENING, PAUSED, SHUTTING_DOWN = range(4) - PROTOCOL_MIN = '1.1' - PROTOCOL_MAX = '1.4' AIORPCX_MIN = (0, 5, 6) def __init__(self, env): '''Initialize everything that doesn't require the event loop.''' super().__init__(env) + if aiorpcx_version < self.AIORPCX_MIN: raise RuntimeError('ElectrumX requires aiorpcX >= ' f'{version_string(self.AIORPCX_MIN)}') + sclass = env.coin.SESSIONCLS self.logger.info(f'software version: {electrumx.version}') self.logger.info(f'aiorpcX version: {version_string(aiorpcx_version)}') self.logger.info(f'supported protocol versions: ' - f'{self.PROTOCOL_MIN}-{self.PROTOCOL_MAX}') + f'{sclass.PROTOCOL_MIN}-{sclass.PROTOCOL_MAX}') self.logger.info(f'event loop policy: {env.loop_policy}') self.coin = env.coin @@ -106,34 +106,6 @@ class Controller(ServerBase): # Event triggered when electrumx is listening for incoming requests. self.server_listening = asyncio.Event() - def server_features(self): - '''Return the server features dictionary.''' - return { - 'hosts': self.env.hosts_dict(), - 'pruning': None, - 'server_version': electrumx.version, - 'protocol_min': self.PROTOCOL_MIN, - 'protocol_max': self.PROTOCOL_MAX, - 'genesis_hash': self.coin.GENESIS_HASH, - 'hash_function': 'sha256', - } - - def server_version_args(self): - '''The arguments to a server.version RPC call to a peer.''' - return [electrumx.version, [self.PROTOCOL_MIN, self.PROTOCOL_MAX]] - - def protocol_tuple(self, request): - '''Given a client's protocol version request, return the negotiated - protocol tuple. If the request is unsupported return None. - ''' - ptuple, client_min = util.protocol_version(request, self.PROTOCOL_MIN, - self.PROTOCOL_MAX) - if not ptuple and client_min > util.protocol_tuple(self.PROTOCOL_MIN): - version = version_string(client_min) - self.logger.info(f'client requested future protocol version ' - f'{version} - is your software out of date?') - return ptuple - async def start_servers(self): '''Start the RPC server and schedule the external servers to be started once the block processor has caught up. diff --git a/electrumx/server/peers.py b/electrumx/server/peers.py index 7eb1b0b..0d12ad1 100644 --- a/electrumx/server/peers.py +++ b/electrumx/server/peers.py @@ -51,8 +51,7 @@ class PeerSession(ClientSession): self.peer.ip_addr = address[0] # Send server.version first - controller = self.peer_mgr.controller - self.send_request('server.version', controller.server_version_args(), + self.send_request('server.version', self.peer_mgr.server_version_args, self.on_version, timeout=self.timeout) def connection_lost(self, exc): @@ -232,8 +231,10 @@ class PeerManager(object): self.loop = controller.loop # Our clearnet and Tor Peers, if any - self.myselves = [Peer(ident.host, controller.server_features(), 'env') + sclass = env.coin.SESSIONCLS + self.myselves = [Peer(ident.host, sclass.server_features(env), 'env') for ident in env.identities] + self.server_version_args = sclass.server_version_args() self.retry_event = asyncio.Event() # Peers have one entry per hostname. Once connected, the # ip_addr property is either None, an onion peer, or the diff --git a/electrumx/server/session.py b/electrumx/server/session.py index af60975..1485749 100644 --- a/electrumx/server/session.py +++ b/electrumx/server/session.py @@ -133,6 +133,9 @@ class SessionBase(ServerSession): class ElectrumX(SessionBase): '''A TCP server that handles incoming Electrum connections.''' + PROTOCOL_MIN = '1.1' + PROTOCOL_MAX = '1.4' + def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.subscribe_headers = False @@ -143,8 +146,25 @@ class ElectrumX(SessionBase): self.hashX_subs = {} self.sv_seen = False self.mempool_statuses = {} - self.set_protocol_handlers(util.protocol_tuple( - self.controller.PROTOCOL_MIN)) + self.set_protocol_handlers(util.protocol_tuple(self.PROTOCOL_MIN)) + + @classmethod + def server_features(cls, env): + '''Return the server features dictionary.''' + return { + 'hosts': env.hosts_dict(), + 'pruning': None, + 'server_version': electrumx.version, + 'protocol_min': cls.PROTOCOL_MIN, + 'protocol_max': cls.PROTOCOL_MAX, + 'genesis_hash': env.coin.GENESIS_HASH, + 'hash_function': 'sha256', + } + + @classmethod + def server_version_args(cls): + '''The arguments to a server.version RPC call to a peer.''' + return [electrumx.version, [cls.PROTOCOL_MIN, cls.PROTOCOL_MAX]] def protocol_version_string(self): return util.version_string(self.protocol_tuple) @@ -440,8 +460,13 @@ class ElectrumX(SessionBase): # Find the highest common protocol version. Disconnect if # that protocol version in unsupported. - ptuple = self.controller.protocol_tuple(protocol_version) + ptuple, client_min = util.protocol_version( + protocol_version, self.PROTOCOL_MIN, self.PROTOCOL_MAX) if ptuple is None: + if client_min > util.protocol_tuple(self.PROTOCOL_MIN): + self.logger.info(f'client requested future protocol version ' + f'{version_string(client_min)} ' + f'- is your software out of date?') self.close_after_send = True raise RPCError(BAD_REQUEST, f'unsupported protocol version: {protocol_version}') @@ -492,7 +517,7 @@ class ElectrumX(SessionBase): 'server.add_peer': self.add_peer, 'server.banner': self.banner, 'server.donation_address': self.donation_address, - 'server.features': self.controller.server_features, + 'server.features': partial(self.server_features, self.env), 'server.peers.subscribe': self.peers_subscribe, 'server.version': self.server_version, }