From 1bf51e855d35013feb8a079153a913e1965f52a9 Mon Sep 17 00:00:00 2001 From: Jack Robison Date: Wed, 15 Jan 2020 12:57:37 -0500 Subject: [PATCH] check minimum server version from wallet client --- lbry/error/README.md | 1 + lbry/error/__init__.py | 6 ++++++ lbry/wallet/network.py | 13 +++++++++++-- tests/integration/blockchain/test_network.py | 4 +++- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lbry/error/README.md b/lbry/error/README.md index 3411e40ad..2295ad8b9 100644 --- a/lbry/error/README.md +++ b/lbry/error/README.md @@ -55,6 +55,7 @@ Code | Name | Message 409 | ResolveTimeout | Failed to resolve '{url}' within the timeout. 410 | KeyFeeAboveMaxAllowed | {message} 411 | InvalidPassword | Password is invalid. +412 | IncompatibleWalletServer | '{server}:{port}' has an incompatibly old version. **5xx** | Blob | **Blobs** 500 | BlobNotFound | Blob not found. 501 | BlobPermissionDenied | Permission denied to read blob. diff --git a/lbry/error/__init__.py b/lbry/error/__init__.py index 9791de671..567b3cb17 100644 --- a/lbry/error/__init__.py +++ b/lbry/error/__init__.py @@ -209,6 +209,12 @@ class InvalidPasswordError(WalletError): super().__init__("Password is invalid.") +class IncompatibleWalletServerError(WalletError): + + def __init__(self, server, port): + super().__init__(f"'{server}:{port}' has an incompatibly old version.") + + class BlobError(BaseError): """ **Blobs** diff --git a/lbry/wallet/network.py b/lbry/wallet/network.py index 672b2938d..1b08c5a2a 100644 --- a/lbry/wallet/network.py +++ b/lbry/wallet/network.py @@ -5,6 +5,7 @@ from operator import itemgetter from typing import Dict, Optional, Tuple from lbry import __version__ +from lbry.error import IncompatibleWalletServerError from lbry.wallet.rpc import RPCSession as BaseClientSession, Connector, RPCError, ProtocolError from lbry.wallet.stream import StreamController @@ -97,8 +98,12 @@ class ClientSession(BaseClientSession): await self.ensure_server_version() retry_delay = default_delay except RPCError as e: - log.warning("Server error, ignoring for 1h: %s:%d -- %s", *self.server, e.message) + log.debug("Server error, ignoring for 1h: %s:%d -- %s", *self.server, e.message) retry_delay = 60 * 60 + except IncompatibleWalletServerError: + await self.close() + retry_delay = 60 * 60 + log.debug("Wallet server has an incompatible version, retrying in 1h: %s:%d", *self.server) except (asyncio.TimeoutError, OSError): await self.close() retry_delay = min(60, retry_delay * 2) @@ -112,9 +117,12 @@ class ClientSession(BaseClientSession): async def ensure_server_version(self, required=None, timeout=3): required = required or self.network.PROTOCOL_VERSION - return await asyncio.wait_for( + response = await asyncio.wait_for( self.send_request('server.version', [__version__, required]), timeout=timeout ) + if tuple(int(piece) for piece in response[0].split(".")) < self.network.MINIMUM_REQUIRED: + raise IncompatibleWalletServerError(*self.server) + return response async def create_connection(self, timeout=6): connector = Connector(lambda: self, *self.server) @@ -139,6 +147,7 @@ class ClientSession(BaseClientSession): class Network: PROTOCOL_VERSION = __version__ + MINIMUM_REQUIRED = (0, 53, 2) def __init__(self, ledger): self.ledger = ledger diff --git a/tests/integration/blockchain/test_network.py b/tests/integration/blockchain/test_network.py index 6b40fa5d7..a03a6beb4 100644 --- a/tests/integration/blockchain/test_network.py +++ b/tests/integration/blockchain/test_network.py @@ -145,7 +145,9 @@ class ServerPickingTestCase(AsyncioTestCase): class FakeSession(RPCSession): async def handle_request(self, request): await asyncio.sleep(latency) - return {"height": 1} + if request.method == 'server.version': + return tuple(request.args) + return {'height': 1} server = await self.loop.create_server(lambda: FakeSession(), host='127.0.0.1', port=port) self.addCleanup(server.close) return '127.0.0.1', port