network: fix bug in best_effort_reliable
self.interface might get set to None after decorator checks it but before func gets scheduled:
125.04 | E | asyncio | Task exception was never retrieved
future: <Task finished name='Task-408' coro=<Transaction.add_info_from_network.<locals>.add_info_to_txin() done, defined at ...\electrum\electrum\transaction.py:976> exception=AttributeError("'NoneType' object has no attribute 'get_transaction'")>
Traceback (most recent call last):
File "...\electrum\electrum\transaction.py", line 980, in add_info_to_txin
await txin.add_info_from_network(network=network, ignore_network_issues=ignore_network_issues)
File "...\electrum\electrum\transaction.py", line 375, in add_info_from_network
self.utxo = await fetch_from_network(txid=self.prevout.txid.hex())
File "...\electrum\electrum\transaction.py", line 362, in fetch_from_network
raw_tx = await network.get_transaction(txid, timeout=10)
File "...\electrum\electrum\network.py", line 866, in make_reliable_wrapper
async with OldTaskGroup(wait=any) as group:
File "...\aiorpcX\aiorpcx\curio.py", line 304, in __aexit__
await self.join()
File "...\electrum\electrum\util.py", line 1410, in join
self.completed.result()
File "...\electrum\electrum\network.py", line 889, in wrapper
return await func(self, *args, **kwargs)
File "...\electrum\electrum\network.py", line 1114, in get_transaction
return await self.interface.get_transaction(tx_hash=tx_hash, timeout=timeout)
AttributeError: 'NoneType' object has no attribute 'get_transaction'
This commit is contained in:
@@ -894,10 +894,14 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
||||
@best_effort_reliable
|
||||
@catch_server_exceptions
|
||||
async def get_merkle_for_transaction(self, tx_hash: str, tx_height: int) -> dict:
|
||||
if self.interface is None: # handled by best_effort_reliable
|
||||
raise RequestTimedOut()
|
||||
return await self.interface.get_merkle_for_transaction(tx_hash=tx_hash, tx_height=tx_height)
|
||||
|
||||
@best_effort_reliable
|
||||
async def broadcast_transaction(self, tx: 'Transaction', *, timeout=None) -> None:
|
||||
if self.interface is None: # handled by best_effort_reliable
|
||||
raise RequestTimedOut()
|
||||
if timeout is None:
|
||||
timeout = self.get_network_timeout_seconds(NetworkTimeout.Urgent)
|
||||
try:
|
||||
@@ -1106,31 +1110,43 @@ class Network(Logger, NetworkRetryManager[ServerAddr]):
|
||||
@best_effort_reliable
|
||||
@catch_server_exceptions
|
||||
async def request_chunk(self, height: int, tip=None, *, can_return_early=False):
|
||||
if self.interface is None: # handled by best_effort_reliable
|
||||
raise RequestTimedOut()
|
||||
return await self.interface.request_chunk(height, tip=tip, can_return_early=can_return_early)
|
||||
|
||||
@best_effort_reliable
|
||||
@catch_server_exceptions
|
||||
async def get_transaction(self, tx_hash: str, *, timeout=None) -> str:
|
||||
if self.interface is None: # handled by best_effort_reliable
|
||||
raise RequestTimedOut()
|
||||
return await self.interface.get_transaction(tx_hash=tx_hash, timeout=timeout)
|
||||
|
||||
@best_effort_reliable
|
||||
@catch_server_exceptions
|
||||
async def get_history_for_scripthash(self, sh: str) -> List[dict]:
|
||||
if self.interface is None: # handled by best_effort_reliable
|
||||
raise RequestTimedOut()
|
||||
return await self.interface.get_history_for_scripthash(sh)
|
||||
|
||||
@best_effort_reliable
|
||||
@catch_server_exceptions
|
||||
async def listunspent_for_scripthash(self, sh: str) -> List[dict]:
|
||||
if self.interface is None: # handled by best_effort_reliable
|
||||
raise RequestTimedOut()
|
||||
return await self.interface.listunspent_for_scripthash(sh)
|
||||
|
||||
@best_effort_reliable
|
||||
@catch_server_exceptions
|
||||
async def get_balance_for_scripthash(self, sh: str) -> dict:
|
||||
if self.interface is None: # handled by best_effort_reliable
|
||||
raise RequestTimedOut()
|
||||
return await self.interface.get_balance_for_scripthash(sh)
|
||||
|
||||
@best_effort_reliable
|
||||
@catch_server_exceptions
|
||||
async def get_txid_from_txpos(self, tx_height, tx_pos, merkle):
|
||||
if self.interface is None: # handled by best_effort_reliable
|
||||
raise RequestTimedOut()
|
||||
return await self.interface.get_txid_from_txpos(tx_height, tx_pos, merkle)
|
||||
|
||||
def blockchain(self) -> Blockchain:
|
||||
|
||||
Reference in New Issue
Block a user