mirror of
https://github.com/LBRYFoundation/LBRY-Vault.git
synced 2025-08-23 17:47:31 +00:00
network.get_transaction: move some response validation logic from Synchronizer
This commit is contained in:
parent
94888739d3
commit
0b0139c676
3 changed files with 21 additions and 14 deletions
|
@ -181,6 +181,8 @@ class RequestTimedOut(GracefulDisconnect):
|
||||||
return _("Network request timed out.")
|
return _("Network request timed out.")
|
||||||
|
|
||||||
|
|
||||||
|
class RequestCorrupted(GracefulDisconnect): pass
|
||||||
|
|
||||||
class ErrorParsingSSLCert(Exception): pass
|
class ErrorParsingSSLCert(Exception): pass
|
||||||
class ErrorGettingSSLCertFromServer(Exception): pass
|
class ErrorGettingSSLCertFromServer(Exception): pass
|
||||||
class ConnectError(NetworkException): pass
|
class ConnectError(NetworkException): pass
|
||||||
|
@ -258,6 +260,9 @@ class Interface(Logger):
|
||||||
def diagnostic_name(self):
|
def diagnostic_name(self):
|
||||||
return str(NetAddress(self.host, self.port))
|
return str(NetAddress(self.host, self.port))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"<Interface {self.diagnostic_name()}>"
|
||||||
|
|
||||||
def _set_proxy(self, proxy: dict):
|
def _set_proxy(self, proxy: dict):
|
||||||
if proxy:
|
if proxy:
|
||||||
username, pw = proxy.get('user'), proxy.get('password')
|
username, pw = proxy.get('user'), proxy.get('password')
|
||||||
|
|
|
@ -53,10 +53,11 @@ from .bitcoin import COIN
|
||||||
from . import constants
|
from . import constants
|
||||||
from . import blockchain
|
from . import blockchain
|
||||||
from . import bitcoin
|
from . import bitcoin
|
||||||
|
from .transaction import Transaction
|
||||||
from .blockchain import Blockchain, HEADER_SIZE
|
from .blockchain import Blockchain, HEADER_SIZE
|
||||||
from .interface import (Interface, serialize_server, deserialize_server,
|
from .interface import (Interface, serialize_server, deserialize_server,
|
||||||
RequestTimedOut, NetworkTimeout, BUCKET_NAME_OF_ONION_SERVERS,
|
RequestTimedOut, NetworkTimeout, BUCKET_NAME_OF_ONION_SERVERS,
|
||||||
NetworkException)
|
NetworkException, RequestCorrupted)
|
||||||
from .version import PROTOCOL_VERSION
|
from .version import PROTOCOL_VERSION
|
||||||
from .simple_config import SimpleConfig
|
from .simple_config import SimpleConfig
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
|
@ -66,7 +67,6 @@ if TYPE_CHECKING:
|
||||||
from .channel_db import ChannelDB
|
from .channel_db import ChannelDB
|
||||||
from .lnworker import LNGossip
|
from .lnworker import LNGossip
|
||||||
from .lnwatcher import WatchTower
|
from .lnwatcher import WatchTower
|
||||||
from .transaction import Transaction
|
|
||||||
from .daemon import Daemon
|
from .daemon import Daemon
|
||||||
|
|
||||||
|
|
||||||
|
@ -871,7 +871,7 @@ class Network(Logger):
|
||||||
if success_fut.exception():
|
if success_fut.exception():
|
||||||
try:
|
try:
|
||||||
raise success_fut.exception()
|
raise success_fut.exception()
|
||||||
except RequestTimedOut:
|
except (RequestTimedOut, RequestCorrupted):
|
||||||
await iface.close()
|
await iface.close()
|
||||||
await iface.got_disconnected
|
await iface.got_disconnected
|
||||||
continue # try again
|
continue # try again
|
||||||
|
@ -1068,8 +1068,19 @@ class Network(Logger):
|
||||||
async def get_transaction(self, tx_hash: str, *, timeout=None) -> str:
|
async def get_transaction(self, tx_hash: str, *, timeout=None) -> str:
|
||||||
if not is_hash256_str(tx_hash):
|
if not is_hash256_str(tx_hash):
|
||||||
raise Exception(f"{repr(tx_hash)} is not a txid")
|
raise Exception(f"{repr(tx_hash)} is not a txid")
|
||||||
return await self.interface.session.send_request('blockchain.transaction.get', [tx_hash],
|
iface = self.interface
|
||||||
timeout=timeout)
|
raw = await iface.session.send_request('blockchain.transaction.get', [tx_hash], timeout=timeout)
|
||||||
|
# validate response
|
||||||
|
tx = Transaction(raw)
|
||||||
|
try:
|
||||||
|
tx.deserialize() # see if raises
|
||||||
|
except Exception as e:
|
||||||
|
self.logger.warning(f"cannot deserialize received transaction (txid {tx_hash}). from {str(iface)}")
|
||||||
|
raise RequestCorrupted() from e # TODO ban server?
|
||||||
|
if tx.txid() != tx_hash:
|
||||||
|
self.logger.warning(f"received tx does not match expected txid {tx_hash} (got {tx.txid()}). from {str(iface)}")
|
||||||
|
raise RequestCorrupted() # TODO ban server?
|
||||||
|
return raw
|
||||||
|
|
||||||
@best_effort_reliable
|
@best_effort_reliable
|
||||||
@catch_server_exceptions
|
@catch_server_exceptions
|
||||||
|
|
|
@ -221,15 +221,6 @@ class Synchronizer(SynchronizerBase):
|
||||||
finally:
|
finally:
|
||||||
self._requests_answered += 1
|
self._requests_answered += 1
|
||||||
tx = Transaction(raw_tx)
|
tx = Transaction(raw_tx)
|
||||||
try:
|
|
||||||
tx.deserialize() # see if raises
|
|
||||||
except Exception as e:
|
|
||||||
# possible scenarios:
|
|
||||||
# 1: server is sending garbage
|
|
||||||
# 2: there is a bug in the deserialization code
|
|
||||||
# 3: there was a segwit-like upgrade that changed the tx structure
|
|
||||||
# that we don't know about
|
|
||||||
raise SynchronizerFailure(f"cannot deserialize transaction {tx_hash}") from e
|
|
||||||
if tx_hash != tx.txid():
|
if tx_hash != tx.txid():
|
||||||
raise SynchronizerFailure(f"received tx does not match expected txid ({tx_hash} != {tx.txid()})")
|
raise SynchronizerFailure(f"received tx does not match expected txid ({tx_hash} != {tx.txid()})")
|
||||||
tx_height = self.requested_tx.pop(tx_hash)
|
tx_height = self.requested_tx.pop(tx_hash)
|
||||||
|
|
Loading…
Add table
Reference in a new issue