synchronizer: allow server not finding txn sometimes
User has wallet file with history that includes some txid; corresponding raw tx is not in the "transactions" dict in the file however. When the synchronizer starts up, it requests this "missing" txn from the server... but what if the server does not know about it? Maybe it was reorged and is not in the new best chain, and not even in mempool. This was not handled previously. fix #5122
This commit is contained in:
parent
f60d1e7cb6
commit
7b8114f865
@ -780,7 +780,7 @@ class Network(PrintError):
|
||||
try:
|
||||
return await func(self, *args, **kwargs)
|
||||
except aiorpcx.jsonrpc.CodeMessageError as e:
|
||||
raise UntrustedServerReturnedError(original_exception=e)
|
||||
raise UntrustedServerReturnedError(original_exception=e) from e
|
||||
return wrapper
|
||||
|
||||
@best_effort_reliable
|
||||
|
||||
@ -32,6 +32,7 @@ from aiorpcx import TaskGroup, run_in_thread
|
||||
from .transaction import Transaction
|
||||
from .util import bh2u, make_aiohttp_session, NetworkJobOnDefaultServer
|
||||
from .bitcoin import address_to_scripthash, is_address
|
||||
from .network import UntrustedServerReturnedError
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .network import Network
|
||||
@ -165,7 +166,7 @@ class Synchronizer(SynchronizerBase):
|
||||
# Remove request; this allows up_to_date to be True
|
||||
self.requested_histories.pop(addr)
|
||||
|
||||
async def _request_missing_txs(self, hist):
|
||||
async def _request_missing_txs(self, hist, *, allow_server_not_finding_tx=False):
|
||||
# "hist" is a list of [tx_hash, tx_height] lists
|
||||
transaction_hashes = []
|
||||
for tx_hash, tx_height in hist:
|
||||
@ -179,10 +180,18 @@ class Synchronizer(SynchronizerBase):
|
||||
if not transaction_hashes: return
|
||||
async with TaskGroup() as group:
|
||||
for tx_hash in transaction_hashes:
|
||||
await group.spawn(self._get_transaction, tx_hash)
|
||||
await group.spawn(self._get_transaction(tx_hash, allow_server_not_finding_tx=allow_server_not_finding_tx))
|
||||
|
||||
async def _get_transaction(self, tx_hash):
|
||||
result = await self.network.get_transaction(tx_hash)
|
||||
async def _get_transaction(self, tx_hash, *, allow_server_not_finding_tx=False):
|
||||
try:
|
||||
result = await self.network.get_transaction(tx_hash)
|
||||
except UntrustedServerReturnedError as e:
|
||||
# most likely, "No such mempool or blockchain transaction"
|
||||
if allow_server_not_finding_tx:
|
||||
self.requested_tx.pop(tx_hash)
|
||||
return
|
||||
else:
|
||||
raise
|
||||
tx = Transaction(result)
|
||||
try:
|
||||
tx.deserialize()
|
||||
@ -207,7 +216,7 @@ class Synchronizer(SynchronizerBase):
|
||||
# Old electrum servers returned ['*'] when all history for the address
|
||||
# was pruned. This no longer happens but may remain in old wallets.
|
||||
if history == ['*']: continue
|
||||
await self._request_missing_txs(history)
|
||||
await self._request_missing_txs(history, allow_server_not_finding_tx=True)
|
||||
# add addresses to bootstrap
|
||||
for addr in self.wallet.get_addresses():
|
||||
await self._add_address(addr)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user