electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 1bd9b3a66aac28d2ff2c556370c26138bf23de09
parent de83ab6d4a05ec7f036da16e8054ca158666e3d0
Author: SomberNight <somber.night@protonmail.com>
Date:   Wed,  4 Sep 2019 20:15:54 +0200

commands: fix "restore" cmd

Previously commands did not run on the asyncio thread but now they do.
"restore" was polling like "while 1: time.sleep()", blocking the event loop.

Now "restore" does not sync the wallet; which is actually cleaner
as previously this wallet would never get unloaded from the daemon (syncing forever).

This is also symmetric with the "create" cmd which also does not try to sync with the network.

However now it became difficult to write a script that restores a wallet and wants to wait
until it gets synced. Workaround for now is to poll with "list_wallets" whether it's synced.

We could create a new command that blocks until the loaded wallet gets synced.

Diffstat:
Melectrum/commands.py | 4++--
Melectrum/tests/test_wallet.py | 11+++++------
Melectrum/wallet.py | 20++++++--------------
3 files changed, 13 insertions(+), 22 deletions(-)

diff --git a/electrum/commands.py b/electrum/commands.py @@ -221,12 +221,12 @@ class Commands: or bitcoin private keys. If you want to be prompted for an argument, type '?' or ':' (concealed) """ + # TODO create a separate command that blocks until wallet is synced d = restore_wallet_from_text(text, path=self.config.get_wallet_path(), passphrase=passphrase, password=password, - encrypt_file=encrypt_file, - network=self.network) + encrypt_file=encrypt_file) return { 'path': d['wallet'].storage.path, 'msg': d['msg'], diff --git a/electrum/tests/test_wallet.py b/electrum/tests/test_wallet.py @@ -170,7 +170,6 @@ class TestCreateRestoreWallet(WalletTestCase): encrypt_file = True d = restore_wallet_from_text(text, path=self.wallet_path, - network=None, passphrase=passphrase, password=password, encrypt_file=encrypt_file, @@ -183,28 +182,28 @@ class TestCreateRestoreWallet(WalletTestCase): def test_restore_wallet_from_text_xpub(self): text = 'zpub6nydoME6CFdJtMpzHW5BNoPz6i6XbeT9qfz72wsRqGdgGEYeivso6xjfw8cGcCyHwF7BNW4LDuHF35XrZsovBLWMF4qXSjmhTXYiHbWqGLt' - d = restore_wallet_from_text(text, path=self.wallet_path, network=None, gap_limit=1) + d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1) wallet = d['wallet'] # type: Standard_Wallet self.assertEqual(text, wallet.keystore.get_master_public_key()) self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) def test_restore_wallet_from_text_xkey_that_is_also_a_valid_electrum_seed_by_chance(self): text = 'yprvAJBpuoF4FKpK92ofzQ7ge6VJMtorow3maAGPvPGj38ggr2xd1xCrC9ojUVEf9jhW5L9SPu6fU2U3o64cLrRQ83zaQGNa6YP3ajZS6hHNPXj' - d = restore_wallet_from_text(text, path=self.wallet_path, network=None, gap_limit=1) + d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1) wallet = d['wallet'] # type: Standard_Wallet self.assertEqual(text, wallet.keystore.get_master_private_key(password=None)) self.assertEqual('3Pa4hfP3LFWqa2nfphYaF7PZfdJYNusAnp', wallet.get_receiving_addresses()[0]) def test_restore_wallet_from_text_xprv(self): text = 'zprvAZzHPqhCMt51fskXBUYB1fTFYgG3CBjJUT4WEZTpGw6hPSDWBPZYZARC5sE9xAcX8NeWvvucFws8vZxEa65RosKAhy7r5MsmKTxr3hmNmea' - d = restore_wallet_from_text(text, path=self.wallet_path, network=None, gap_limit=1) + d = restore_wallet_from_text(text, path=self.wallet_path, gap_limit=1) wallet = d['wallet'] # type: Standard_Wallet self.assertEqual(text, wallet.keystore.get_master_private_key(password=None)) self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) def test_restore_wallet_from_text_addresses(self): text = 'bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw bc1qnp78h78vp92pwdwq5xvh8eprlga5q8gu66960c' - d = restore_wallet_from_text(text, path=self.wallet_path, network=None) + d = restore_wallet_from_text(text, path=self.wallet_path) wallet = d['wallet'] # type: Imported_Wallet self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', wallet.get_receiving_addresses()[0]) self.assertEqual(2, len(wallet.get_receiving_addresses())) @@ -214,7 +213,7 @@ class TestCreateRestoreWallet(WalletTestCase): def test_restore_wallet_from_text_privkeys(self): text = 'p2wpkh:L4jkdiXszG26SUYvwwJhzGwg37H2nLhrbip7u6crmgNeJysv5FHL p2wpkh:L24GxnN7NNUAfCXA6hFzB1jt59fYAAiFZMcLaJ2ZSawGpM3uqhb1' - d = restore_wallet_from_text(text, path=self.wallet_path, network=None) + d = restore_wallet_from_text(text, path=self.wallet_path) wallet = d['wallet'] # type: Imported_Wallet addr0 = wallet.get_receiving_addresses()[0] self.assertEqual('bc1q2ccr34wzep58d4239tl3x3734ttle92a8srmuw', addr0) diff --git a/electrum/wallet.py b/electrum/wallet.py @@ -2100,7 +2100,8 @@ class Wallet(object): raise WalletFileException("Unknown wallet type: " + str(wallet_type)) -def create_new_wallet(*, path, passphrase=None, password=None, encrypt_file=True, seed_type=None, gap_limit=None): +def create_new_wallet(*, path, passphrase=None, password=None, + encrypt_file=True, seed_type=None, gap_limit=None) -> dict: """Create a new wallet""" storage = WalletStorage(path) if storage.file_exists(): @@ -2121,9 +2122,9 @@ def create_new_wallet(*, path, passphrase=None, password=None, encrypt_file=True return {'seed': seed, 'wallet': wallet, 'msg': msg} -def restore_wallet_from_text(text, *, path, network=None, +def restore_wallet_from_text(text, *, path, passphrase=None, password=None, encrypt_file=True, - gap_limit=None): + gap_limit=None) -> dict: """Restore a wallet from text. Text can be a seed phrase, a master public key, a master private key, a list of bitcoin addresses or bitcoin private keys.""" @@ -2164,17 +2165,8 @@ def restore_wallet_from_text(text, *, path, network=None, assert not storage.file_exists(), "file was created too soon! plaintext keys might have been written to disk" wallet.update_password(old_pw=None, new_pw=password, encrypt_storage=encrypt_file) wallet.synchronize() - - if network: - wallet.start_network(network) - _logger.info("Recovering wallet...") - wallet.wait_until_synchronized() - wallet.stop_threads() - # note: we don't wait for SPV - msg = "Recovery successful" if wallet.is_found() else "Found no history for this wallet" - else: - msg = ("This wallet was restored offline. It may contain more addresses than displayed. " - "Start a daemon (not offline) to sync history.") + msg = ("This wallet was restored offline. It may contain more addresses than displayed. " + "Start a daemon and use load_wallet to sync its history.") wallet.storage.write() return {'wallet': wallet, 'msg': msg}