fix restriction rules, minor refactor, translate error from transaction not found into returning none

This commit is contained in:
Victor Shyba 2019-08-31 06:37:17 -03:00
parent d2cd0ece5f
commit 379144bcfe
6 changed files with 22 additions and 17 deletions

View file

@ -59,7 +59,7 @@ class ReconnectTests(IntegrationTestCase):
master_client = self.ledger.network.client
self.ledger.network.client.connection_lost(Exception())
with self.assertRaises(asyncio.TimeoutError):
await d
await d
self.assertIsNone(master_client.response_time) # response time unknown as it failed
# rich but offline? no way, no water, let's retry
with self.assertRaisesRegex(ConnectionError, 'connection is not available'):

View file

@ -138,6 +138,7 @@ class BasicTransactionTests(IntegrationTestCase):
address = await self.account.receiving.get_or_create_usable_address()
# evil trick: mempool is unsorted on real life, but same order between python instances. reproduce it
original_summary = self.conductor.spv_node.server.mempool.transaction_summaries
async def random_summary(*args, **kwargs):
summary = await original_summary(*args, **kwargs)
if summary and len(summary) > 2:
@ -174,3 +175,5 @@ class BasicTransactionTests(IntegrationTestCase):
self.assertTrue(await self.ledger.update_history(address, remote_status))
self.assertEqual(21, len((await self.ledger.get_local_status_and_history(address))[1]))
self.assertEqual(0, len(self.ledger._known_addresses_out_of_sync))
# should be another test, but it would be too much to setup just for that and it affects sync
self.assertIsNone(await self.ledger.network.get_transaction('1'*64))

View file

@ -29,7 +29,7 @@ class MockNetwork:
async def get_merkle(self, txid, height):
return {'merkle': ['abcd01'], 'pos': 1}
async def get_transaction(self, tx_hash):
async def get_transaction(self, tx_hash, _=None):
self.get_transaction_called.append(tx_hash)
return self.transaction[tx_hash]

View file

@ -220,7 +220,7 @@ class SQLiteMixin:
async def open(self):
log.info("connecting to database: %s", self._db_path)
self.db = await AIOSQLite.connect(self._db_path)
self.db = await AIOSQLite.connect(self._db_path, isolation_level=None)
await self.db.executescript(self.CREATE_TABLES_QUERY)
async def close(self):

View file

@ -287,7 +287,7 @@ class BaseLedger(metaclass=LedgerRegistry):
await self.join_network()
self.network.on_connected.listen(self.join_network)
async def join_network(self, *args):
async def join_network(self, *_):
log.info("Subscribing and updating accounts.")
async with self._header_processing_lock:
await self.update_headers()
@ -472,9 +472,10 @@ class BaseLedger(metaclass=LedgerRegistry):
await self.db.save_transaction_io_batch(
synced_txs, address, self.address_to_hash160(address), synced_history.getvalue()
)
for tx in synced_txs:
await self._on_transaction_controller.add(TransactionEvent(address, tx))
await asyncio.wait([
self._on_transaction_controller.add(TransactionEvent(address, tx))
for tx in synced_txs
])
if address_manager is None:
address_manager = await self.get_address_manager_for_address(address)
@ -517,7 +518,7 @@ class BaseLedger(metaclass=LedgerRegistry):
if tx is None:
# fetch from network
_raw = await self.network.retriable_call(self.network.get_transaction, txid)
_raw = await self.network.retriable_call(self.network.get_transaction, txid, remote_height)
if _raw:
tx = self.transaction_class(unhexlify(_raw))
cache_item.tx = tx # make sure it's saved before caching it

View file

@ -72,6 +72,10 @@ class ClientSession(BaseClientSession):
log.debug("got reply for %s from %s:%i", method, *self.server)
return reply
except RPCError as e:
if str(e).find('.*no such .*transaction.*') and args:
# shouldnt the server return none instead?
log.warning("Requested transaction missing from server: %s", args[0])
return None
log.warning("Wallet server (%s:%i) returned an error. Code: %s Message: %s",
*self.server, *e.args)
raise e
@ -220,20 +224,17 @@ class BaseNetwork:
def _update_remote_height(self, header_args):
self.remote_height = header_args[0]["height"]
def get_transaction(self, tx_hash):
return self.rpc('blockchain.transaction.get', [tx_hash])
def get_transaction(self, tx_hash, known_height=None):
# use any server if its old, otherwise restrict to who gave us the history
restricted = not known_height or 0 > known_height > self.remote_height - 10
return self.rpc('blockchain.transaction.get', [tx_hash], restricted)
def get_transaction_height(self, tx_hash, known_height=None):
restricted = True # by default, check master for consistency
if known_height:
if 0 < known_height < self.remote_height - 10:
restricted = False # we can get from any server, its old
restricted = not known_height or 0 > known_height > self.remote_height - 10
return self.rpc('blockchain.transaction.get_height', [tx_hash], restricted)
def get_merkle(self, tx_hash, height):
restricted = True # by default, check master for consistency
if 0 < height < self.remote_height - 10:
restricted = False # we can get from any server, its old
restricted = 0 > height > self.remote_height - 10
return self.rpc('blockchain.transaction.get_merkle', [tx_hash, height], restricted)
def get_headers(self, height, count=10000):