From 1052126522ee0ee1d244de1e0be94be58e370495 Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Tue, 24 Mar 2020 00:54:55 -0300 Subject: [PATCH 1/3] add wallet_syncing status --- lbry/extras/daemon/components.py | 1 + lbry/wallet/ledger.py | 2 +- lbry/wallet/tasks.py | 3 +++ tests/integration/blockchain/test_wallet_commands.py | 12 ++++++++++++ 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lbry/extras/daemon/components.py b/lbry/extras/daemon/components.py index 5271c1558..8a08be97a 100644 --- a/lbry/extras/daemon/components.py +++ b/lbry/extras/daemon/components.py @@ -146,6 +146,7 @@ class WalletComponent(Component): best_hash = await self.wallet_manager.get_best_blockhash() result.update({ 'headers_synchronization_progress': progress, + 'wallet_syncing': len(self.wallet_manager.ledger._update_tasks) > 0, 'blocks': max(local_height, 0), 'blocks_behind': max(remote_height - local_height, 0), 'best_blockhash': best_hash, diff --git a/lbry/wallet/ledger.py b/lbry/wallet/ledger.py index cfd89b6ee..6e9607b58 100644 --- a/lbry/wallet/ledger.py +++ b/lbry/wallet/ledger.py @@ -334,7 +334,7 @@ class Ledger(metaclass=LedgerRegistry): log.info("Subscribing and updating accounts.") async with self._header_processing_lock: await self._update_tasks.add(self.initial_headers_sync()) - await self.subscribe_accounts() + await self._update_tasks.add(self.subscribe_accounts()) await self._update_tasks.done.wait() self._on_ready_controller.add(True) diff --git a/lbry/wallet/tasks.py b/lbry/wallet/tasks.py index 05bf9af83..f57b55f5f 100644 --- a/lbry/wallet/tasks.py +++ b/lbry/wallet/tasks.py @@ -8,6 +8,9 @@ class TaskGroup: self._tasks = set() self.done = Event() + def __len__(self): + return len(self._tasks) + def add(self, coro): task = self._loop.create_task(coro) self._tasks.add(task) diff --git a/tests/integration/blockchain/test_wallet_commands.py b/tests/integration/blockchain/test_wallet_commands.py index c65fdfb10..6bb98c324 100644 --- a/tests/integration/blockchain/test_wallet_commands.py +++ b/tests/integration/blockchain/test_wallet_commands.py @@ -1,5 +1,6 @@ import asyncio import json +import os from lbry.wallet import ENCRYPT_ON_DISK from lbry.error import InvalidPasswordError @@ -19,6 +20,17 @@ class WalletCommands(CommandTestCase): await self.daemon.jsonrpc_wallet_add(wallet.id) self.assertEqual(len(session.hashX_subs), 28) + async def test_wallet_syncing_status(self): + address = await self.daemon.jsonrpc_address_unused() + sendtxid = await self.blockchain.send_to_address(address, 1) + + async def eventually_will_sync(): + while not (await self.daemon.jsonrpc_status())['wallet']['wallet_syncing']: + pass + check_sync = asyncio.create_task(eventually_will_sync()) + await self.confirm_tx(sendtxid, self.ledger) + await asyncio.wait_for(check_sync, timeout=10) + async def test_wallet_reconnect(self): await self.conductor.spv_node.stop(True) self.conductor.spv_node.port = 54320 From 460bdc4148684eecb7db5e23f875637fc5cbaaa5 Mon Sep 17 00:00:00 2001 From: Victor Shyba Date: Tue, 24 Mar 2020 21:22:51 -0300 Subject: [PATCH 2/3] move wallet_syncing to wallet status is_syncing --- lbry/extras/daemon/components.py | 1 - lbry/extras/daemon/daemon.py | 6 +++++- tests/integration/blockchain/test_wallet_commands.py | 4 ++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lbry/extras/daemon/components.py b/lbry/extras/daemon/components.py index 8a08be97a..5271c1558 100644 --- a/lbry/extras/daemon/components.py +++ b/lbry/extras/daemon/components.py @@ -146,7 +146,6 @@ class WalletComponent(Component): best_hash = await self.wallet_manager.get_best_blockhash() result.update({ 'headers_synchronization_progress': progress, - 'wallet_syncing': len(self.wallet_manager.ledger._update_tasks) > 0, 'blocks': max(local_height, 0), 'blocks_behind': max(remote_height - local_height, 0), 'best_blockhash': best_hash, diff --git a/lbry/extras/daemon/daemon.py b/lbry/extras/daemon/daemon.py index 28c7022e7..4196f9491 100644 --- a/lbry/extras/daemon/daemon.py +++ b/lbry/extras/daemon/daemon.py @@ -1326,7 +1326,11 @@ class Daemon(metaclass=JSONRPCServerType): Dictionary of wallet status information. """ wallet = self.wallet_manager.get_wallet_or_default(wallet_id) - return {'is_encrypted': wallet.is_encrypted, 'is_locked': wallet.is_locked} + return { + 'is_encrypted': wallet.is_encrypted, + 'is_syncing': len(self.ledger._update_tasks) > 0, + 'is_locked': wallet.is_locked + } @requires(WALLET_COMPONENT) def jsonrpc_wallet_unlock(self, password, wallet_id=None): diff --git a/tests/integration/blockchain/test_wallet_commands.py b/tests/integration/blockchain/test_wallet_commands.py index 6bb98c324..61eef4f44 100644 --- a/tests/integration/blockchain/test_wallet_commands.py +++ b/tests/integration/blockchain/test_wallet_commands.py @@ -25,8 +25,8 @@ class WalletCommands(CommandTestCase): sendtxid = await self.blockchain.send_to_address(address, 1) async def eventually_will_sync(): - while not (await self.daemon.jsonrpc_status())['wallet']['wallet_syncing']: - pass + while not self.daemon.jsonrpc_wallet_status()['is_syncing']: + await asyncio.sleep(0) check_sync = asyncio.create_task(eventually_will_sync()) await self.confirm_tx(sendtxid, self.ledger) await asyncio.wait_for(check_sync, timeout=10) From 86242139dafa5bd2b5dd8f6d9ec061c5331ebb72 Mon Sep 17 00:00:00 2001 From: Jack Robison Date: Thu, 26 Mar 2020 13:56:51 -0400 Subject: [PATCH 3/3] update tests --- .../blockchain/test_wallet_commands.py | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tests/integration/blockchain/test_wallet_commands.py b/tests/integration/blockchain/test_wallet_commands.py index 61eef4f44..cd86fa51d 100644 --- a/tests/integration/blockchain/test_wallet_commands.py +++ b/tests/integration/blockchain/test_wallet_commands.py @@ -280,7 +280,9 @@ class WalletEncryptionAndSynchronization(CommandTestCase): wallet = daemon.wallet_manager.default_wallet wallet.save() - self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': False}) + self.assertEqual(daemon.jsonrpc_wallet_status(), { + 'is_locked': False, 'is_encrypted': False, 'is_syncing': False + }) self.assertIsNone(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK)) self.assertWalletEncrypted(wallet.storage.path, False) @@ -292,22 +294,26 @@ class WalletEncryptionAndSynchronization(CommandTestCase): daemon.jsonrpc_wallet_decrypt() # already not encrypted daemon.jsonrpc_wallet_encrypt('password') - self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True}) + self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True, + 'is_syncing': False}) self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True}) self.assertWalletEncrypted(wallet.storage.path, True) daemon.jsonrpc_wallet_lock() - self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': True, 'is_encrypted': True}) + self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': True, 'is_encrypted': True, + 'is_syncing': False}) # can't sign transactions with locked wallet with self.assertRaises(AssertionError): await daemon.jsonrpc_channel_create('@foo', '1.0') daemon.jsonrpc_wallet_unlock('password') - self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True}) + self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True, + 'is_syncing': False}) await daemon.jsonrpc_channel_create('@foo', '1.0') daemon.jsonrpc_wallet_decrypt() - self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': False}) + self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': False, + 'is_syncing': False}) self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': False}) self.assertWalletEncrypted(wallet.storage.path, False) @@ -319,7 +325,8 @@ class WalletEncryptionAndSynchronization(CommandTestCase): self.assertTrue(daemon2.jsonrpc_wallet_encrypt('password')) self.assertTrue(daemon2.jsonrpc_wallet_lock()) self.assertTrue(daemon2.jsonrpc_wallet_unlock("password")) - self.assertEqual(daemon2.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True}) + self.assertEqual(daemon2.jsonrpc_wallet_status(), + {'is_locked': False, 'is_encrypted': True, 'is_syncing': False}) async def test_sync_with_encryption_and_password_change(self): daemon, daemon2 = self.daemon, self.daemon2 @@ -340,7 +347,8 @@ class WalletEncryptionAndSynchronization(CommandTestCase): await daemon.jsonrpc_sync_apply('password2', data=data['data'], blocking=True) # sync_apply with new password2 also sets it as new local password self.assertEqual(wallet.encryption_password, 'password2') - self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True}) + self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True, + 'is_syncing': True}) self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True}) self.assertWalletEncrypted(wallet.storage.path, True) @@ -357,7 +365,8 @@ class WalletEncryptionAndSynchronization(CommandTestCase): await daemon2.jsonrpc_sync_apply('password3', data=data['data'], blocking=True) # the other device got new password and on disk encryption self.assertEqual(wallet2.encryption_password, 'password3') - self.assertEqual(daemon2.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True}) + self.assertEqual(daemon2.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True, + 'is_syncing': True}) self.assertEqual(daemon2.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True}) self.assertWalletEncrypted(wallet2.storage.path, True)