Browse Source

Convert PROTOCOL_MIN, PROTOCOL_MAX to tuples

patch-2
Neil Booth 7 years ago
parent
commit
739bb687fc
  1. 20
      electrumx/lib/util.py
  2. 5
      electrumx/server/controller.py
  3. 22
      electrumx/server/session.py
  4. 26
      tests/lib/test_util.py
  5. 1
      tests/server/test_api.py

20
electrumx/lib/util.py

@ -304,7 +304,7 @@ def version_string(ptuple):
return '.'.join(str(p) for p in ptuple) return '.'.join(str(p) for p in ptuple)
def protocol_version(client_req, server_min, server_max): def protocol_version(client_req, min_tuple, max_tuple):
'''Given a client's protocol version string, return a pair of '''Given a client's protocol version string, return a pair of
protocol tuples: protocol tuples:
@ -312,27 +312,19 @@ def protocol_version(client_req, server_min, server_max):
If the request is unsupported, the negotiated protocol tuple is If the request is unsupported, the negotiated protocol tuple is
None. None.
'''
'''Given a client protocol request, return the protocol version
to use as a tuple.
If a mutually acceptable protocol version does not exist, return None.
''' '''
if client_req is None:
client_min = client_max = min_tuple
else:
if isinstance(client_req, list) and len(client_req) == 2: if isinstance(client_req, list) and len(client_req) == 2:
client_min, client_max = client_req client_min, client_max = client_req
elif client_req is None:
client_min = client_max = server_min
else: else:
client_min = client_max = client_req client_min = client_max = client_req
client_min = protocol_tuple(client_min) client_min = protocol_tuple(client_min)
client_max = protocol_tuple(client_max) client_max = protocol_tuple(client_max)
server_min = protocol_tuple(server_min)
server_max = protocol_tuple(server_max)
result = min(client_max, server_max) result = min(client_max, max_tuple)
if result < max(client_min, server_min) or result == (0, ): if result < max(client_min, min_tuple) or result == (0, ):
result = None result = None
return result, client_min return result, client_min

5
electrumx/server/controller.py

@ -61,11 +61,10 @@ class Controller(ServerBase):
raise RuntimeError('ElectrumX requires aiorpcX >= ' raise RuntimeError('ElectrumX requires aiorpcX >= '
f'{version_string(self.AIORPCX_MIN)}') f'{version_string(self.AIORPCX_MIN)}')
sclass = env.coin.SESSIONCLS min_str, max_str = env.coin.SESSIONCLS.protocol_min_max_strings()
self.logger.info(f'software version: {electrumx.version}') self.logger.info(f'software version: {electrumx.version}')
self.logger.info(f'aiorpcX version: {version_string(aiorpcx_version)}') self.logger.info(f'aiorpcX version: {version_string(aiorpcx_version)}')
self.logger.info(f'supported protocol versions: ' self.logger.info(f'supported protocol versions: {min_str}-{max_str}')
f'{sclass.PROTOCOL_MIN}-{sclass.PROTOCOL_MAX}')
self.logger.info(f'event loop policy: {env.loop_policy}') self.logger.info(f'event loop policy: {env.loop_policy}')
self.coin = env.coin self.coin = env.coin

22
electrumx/server/session.py

@ -133,8 +133,8 @@ class SessionBase(ServerSession):
class ElectrumX(SessionBase): class ElectrumX(SessionBase):
'''A TCP server that handles incoming Electrum connections.''' '''A TCP server that handles incoming Electrum connections.'''
PROTOCOL_MIN = '1.1' PROTOCOL_MIN = (1, 1)
PROTOCOL_MAX = '1.4' PROTOCOL_MAX = (1, 4)
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -146,17 +146,23 @@ class ElectrumX(SessionBase):
self.hashX_subs = {} self.hashX_subs = {}
self.sv_seen = False self.sv_seen = False
self.mempool_statuses = {} self.mempool_statuses = {}
self.set_protocol_handlers(util.protocol_tuple(self.PROTOCOL_MIN)) self.set_protocol_handlers(self.PROTOCOL_MIN)
@classmethod
def protocol_min_max_strings(cls):
return [util.version_string(ver)
for ver in (cls.PROTOCOL_MIN, cls.PROTOCOL_MAX)]
@classmethod @classmethod
def server_features(cls, env): def server_features(cls, env):
'''Return the server features dictionary.''' '''Return the server features dictionary.'''
min_str, max_str = cls.protocol_min_max_strings()
return { return {
'hosts': env.hosts_dict(), 'hosts': env.hosts_dict(),
'pruning': None, 'pruning': None,
'server_version': electrumx.version, 'server_version': electrumx.version,
'protocol_min': cls.PROTOCOL_MIN, 'protocol_min': min_str,
'protocol_max': cls.PROTOCOL_MAX, 'protocol_max': max_str,
'genesis_hash': env.coin.GENESIS_HASH, 'genesis_hash': env.coin.GENESIS_HASH,
'hash_function': 'sha256', 'hash_function': 'sha256',
} }
@ -164,7 +170,7 @@ class ElectrumX(SessionBase):
@classmethod @classmethod
def server_version_args(cls): def server_version_args(cls):
'''The arguments to a server.version RPC call to a peer.''' '''The arguments to a server.version RPC call to a peer.'''
return [electrumx.version, [cls.PROTOCOL_MIN, cls.PROTOCOL_MAX]] return [electrumx.version, cls.protocol_min_max_strings()]
def protocol_version_string(self): def protocol_version_string(self):
return util.version_string(self.protocol_tuple) return util.version_string(self.protocol_tuple)
@ -463,9 +469,9 @@ class ElectrumX(SessionBase):
ptuple, client_min = util.protocol_version( ptuple, client_min = util.protocol_version(
protocol_version, self.PROTOCOL_MIN, self.PROTOCOL_MAX) protocol_version, self.PROTOCOL_MIN, self.PROTOCOL_MAX)
if ptuple is None: if ptuple is None:
if client_min > util.protocol_tuple(self.PROTOCOL_MIN): if client_min > self.PROTOCOL_MIN:
self.logger.info(f'client requested future protocol version ' self.logger.info(f'client requested future protocol version '
f'{version_string(client_min)} ' f'{util.version_string(client_min)} '
f'- is your software out of date?') f'- is your software out of date?')
self.close_after_send = True self.close_after_send = True
raise RPCError(BAD_REQUEST, raise RPCError(BAD_REQUEST,

26
tests/lib/test_util.py

@ -183,26 +183,26 @@ def test_version_string():
assert util.version_string((1, 3, 2)) == "1.3.2" assert util.version_string((1, 3, 2)) == "1.3.2"
def test_protocol_version(): def test_protocol_version():
assert util.protocol_version(None, "1.0", "1.0") == ((1, 0), (1, 0)) assert util.protocol_version(None, (1, 0), (1, 0)) == ((1, 0), (1, 0))
assert util.protocol_version("0.10", "0.10", "1.1") == ((0, 10), (0, 10)) assert util.protocol_version("0.10", (0, 1), (1, 1)) == ((0, 10), (0, 10))
assert util.protocol_version("1.0", "1.0", "1.0") == ((1, 0), (1, 0)) assert util.protocol_version("1.0", (1, 0), (1, 0)) == ((1, 0), (1, 0))
assert util.protocol_version("1.0", "1.0", "1.1") == ((1, 0), (1, 0)) assert util.protocol_version("1.0", (1, 0), (1, 1)) == ((1, 0), (1, 0))
assert util.protocol_version("1.1", "1.0", "1.1") == ((1, 1), (1, 1)) assert util.protocol_version("1.1", (1, 0), (1, 1)) == ((1, 1), (1, 1))
assert util.protocol_version("1.2", "1.0", "1.1") == (None, (1, 2)) assert util.protocol_version("1.2", (1, 0), (1, 1)) == (None, (1, 2))
assert util.protocol_version("0.9", "1.0", "1.1") == (None, (0, 9)) assert util.protocol_version("0.9", (1, 0), (1, 1)) == (None, (0, 9))
assert util.protocol_version(["0.9", "1.0"], "1.0", "1.1") \ assert util.protocol_version(["0.9", "1.0"], (1, 0), (1, 1)) \
== ((1, 0), (0, 9)) == ((1, 0), (0, 9))
assert util.protocol_version(["0.9", "1.1"], "1.0", "1.1") \ assert util.protocol_version(["0.9", "1.1"], (1, 0), (1, 1)) \
== ((1, 1), (0,9)) == ((1, 1), (0,9))
assert util.protocol_version(["1.1", "0.9"], "1.0", "1.1") \ assert util.protocol_version(["1.1", "0.9"], (1, 0), (1, 1)) \
== (None, (1, 1)) == (None, (1, 1))
assert util.protocol_version(["0.8", "0.9"], "1.0", "1.1") \ assert util.protocol_version(["0.8", "0.9"], (1, 0), (1, 1)) \
== (None, (0, 8)) == (None, (0, 8))
assert util.protocol_version(["1.1", "1.2"], "1.0", "1.1") \ assert util.protocol_version(["1.1", "1.2"], (1, 0), (1, 1)) \
== ((1, 1), (1, 1)) == ((1, 1), (1, 1))
assert util.protocol_version(["1.2", "1.3"], "1.0", "1.1") \ assert util.protocol_version(["1.2", "1.3"], (1, 0), (1, 1)) \
== (None, (1, 2)) == (None, (1, 2))

1
tests/server/test_api.py

@ -10,6 +10,7 @@ loop = asyncio.get_event_loop()
def set_env(): def set_env():
env = mock.create_autospec(Env) env = mock.create_autospec(Env)
env.coin = mock.Mock() env.coin = mock.Mock()
env.coin.SESSIONCLS.protocol_min_max_strings = lambda : ["1.1", "1.4"]
env.loop_policy = None env.loop_policy = None
env.max_sessions = 0 env.max_sessions = 0
env.max_subs = 0 env.max_subs = 0

Loading…
Cancel
Save